heap-buffer-overflow READ in parseURL
kcwu opened this issue · 3 comments
kcwu commented
input (xxd cases/tats-w3m-199
)
00000000: 3c61 2068 7265 663d 676f 7068 6572 3a52 <a href=gopher:R
00000010: 3e >
how to reproduce:
LD_PRELOAD=./AFLplusplus/utils/libdislocator/libdislocator.so LD_LIBRARY_PATH=./notgc ./w3m-tats -T text/html -dump cases/tats-w3m-199
This is detected with help of dummy libgc wrapper. See https://github.com/kcwu/fuzzing-w3m/tree/master/notgc for detail.
This is detected with help of libdislocator, an abusive allocator. See https://github.com/AFLplusplus/AFLplusplus/tree/stable/utils/libdislocator for detail.
More detail to reproduce please see http://github.com/kcwu/fuzzing-w3m
For your convenience,
gdbline:
LD_LIBRARY_PATH=./notgc gdb -ex "set environment LD_PRELOAD=./AFLplusplus/utils/libdislocator/libdislocator.so" --args ./w3m-tats -T text/html -dump cases/tats-w3m-199
found by AFL++
rkta commented
On Sun, Oct 10, 2021 at 08:37:37PM -0700, Kuang-che Wu wrote:
input (`xxd cases/tats-w3m-199`)
```
00000000: 3c61 2068 7265 663d 676f 7068 6572 3a52 <a href=gopher:R
00000010: 3e >
```
how to reproduce:
```
LD_PRELOAD=./AFLplusplus/utils/libdislocator/libdislocator.so LD_LIBRARY_PATH=./notgc ./w3m-tats -T text/html -dump cases/tats-w3m-199
```
This is the offending code:
#ifdef USE_GOPHER
if (p_url->scheme == SCM_GOPHER && *p == 'R') {
p++;
tmp = Strnew();
Strcat_char(tmp, *(p++));
while (*p && *p != '/')
p++;
Strcat_charp(tmp, p);
while (*p)
p++;
p_url->file = copyPath(tmp->ptr, -1, COPYPATH_SPC_IGNORE);
}
else
#endif /* USE_GOPHER */
Problem here is, that 'p' is incremented twice without checking for the
end of the string.
The interesting question for me is: What does this 'if' actually check?
What is special here about the 'R'? I did not find anything related in
RFC 1436 or in RFC 4266.
We could do something like this, though:
diff --git a/url.c b/url.c
index 1fbda17f..07f3ea09 100644
--- a/url.c
+++ b/url.c
@@ -978,7 +978,10 @@ parseURL(char *url, ParsedURL *p_url, ParsedURL *current)
}
#ifdef USE_GOPHER
if (p_url->scheme == SCM_GOPHER && *p == 'R') {
- p++;
+ if (!*++p) {
+ p_url->file = "";
+ goto do_query;
+ }
tmp = Strnew();
Strcat_char(tmp, *(p++));
while (*p && *p != '/')