Skip to content

[Overflow Bug]RTKLIB stream.c: overflow in NTRIP path parsing via oversized mountpoint #789

@neosys007

Description

@neosys007
I would like to report a current-head `Intra-Object Overflow` in the NTRIP open path.
This is not the already-known `stropen(stream->path, path)` issue. The bug I am reporting here is a second, independent overflow that can still be triggered even when the overall `path` stays below `MAXSTRPATH`.

The relevant current-head object layout in `src/stream.c` is:

```c
typedef struct {
    int state;
    int type;
    int nb;
    char url[256];
    char mntpnt[256];
    char user[256];
    char passwd[256];
    char str[NTRIP_MAXSTR];
    unsigned char buff[NTRIP_MAXRSP];
    tcpcli_t *tcp;
} ntrip_t;
```

The parser helper used by `openntrip()` is:

```c
static void decodetcppath(const char *path, char *addr, char *port, char *user,
                          char *passwd, char *mntpnt, char *str)
{
    char buff[MAXSTRPATH], *p, *q;
    ...
    strcpy(buff, path);
    ...
    if ((p = strchr(p, '/'))) {
        if ((q = strchr(p + 1, ':'))) {
            *q = '\0';
            if (str) strcpy(str, q + 1);
        }
        *p = '\0';
        if (mntpnt) strcpy(mntpnt, p + 1);
    }
    ...
}
```

And `openntrip()` passes the fixed fields of `ntrip_t` directly into that helper:

```c
ntrip->url[0] = '\0';
ntrip->mntpnt[0] = ntrip->user[0] = ntrip->passwd[0] = ntrip->str[0] = '\0';
...
decodetcppath(path, addr, port, ntrip->user, ntrip->passwd, ntrip->mntpnt,
              ntrip->str);
```

Why I believe this is a real current-head bug:

1. `stropen()` documents NTRIP paths as:

```text
STR_NTRIPSVR user[:passwd]@address[:port]/moutpoint[:string]
STR_NTRIPCLI [user[:passwd]]@address[:port][/mountpoint]
```

2. A caller can provide a total `path` length safely below `MAXSTRPATH == 1024`, so this report does not rely on the earlier `stream->path` overflow.

3. Even with total path length below `1024`, the mountpoint component after `/` can still be longer than `255`.

4. There is no component-length validation before:

```c
strcpy(mntpnt, p + 1);
```

5. In `ntrip_t`, the destination `mntpnt[256]` is immediately followed by the live field `user[256]`.

So an oversized mountpoint causes a true intra-object overwrite from `mntpnt` into `user`.

A minimal trigger shape is:

```text
host/BBBBBBBBBBBBBBBB....
```

with a mountpoint component length above `256` but total path length still below `1024`.

I also built a reduced source-faithful proof that preserves the exact `ntrip_t` member order and the exact `decodetcppath()` logic. Its output is:

```text
path_len=325
distance_mntpnt_to_user=256
mntpnt_component_len=320
overflow_bytes_into_user=65
user_prefix_hex=4242424242424242
passwd_unchanged=1
```

That result shows:

- overall path length is only `325`, so this is not the earlier `stream->path` case
- `mntpnt[256]` is followed immediately by `user[256]`
- a `320`-byte mountpoint writes `65` bytes into the adjacent `user` field

I am making a narrow claim:

- this is current-head
- it is reachable from the documented NTRIP path grammar
- it is a real write-side intra-object overflow
- the concrete overwrite is `ntrip->mntpnt[256] -> ntrip->user[256]`

I think the right fix is to validate each parsed component against the actual destination field width before copying, and replace raw `strcpy()` with bounded copies for:

- `mntpnt`
- `user`
- `passwd`
- `str`
- `url`

Best regards
Pengpeng Hou
ISCAS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions