diff options
author | Azat Khuzhin <a3at.mail@gmail.com> | 2016-01-31 00:57:16 +0300 |
---|---|---|
committer | Azat Khuzhin <a3at.mail@gmail.com> | 2016-02-01 16:37:16 +0300 |
commit | 329acc18a0768c21ba22522f01a5c7f46cacc4d5 (patch) | |
tree | 2e464b81ff67438884a2ba7151becbe1186bb7c7 /evutil.c | |
parent | 49bd79047bc9aca3ca43fb79eac3901e7805c0df (diff) | |
download | libevent-329acc18a0768c21ba22522f01a5c7f46cacc4d5.tar.gz |
evutil_parse_sockaddr_port(): fix buffer overflow
@asn-the-goblin-slayer:
"Length between '[' and ']' is cast to signed 32 bit integer on line 1815. Is
the length is more than 2<<31 (INT_MAX), len will hold a negative value.
Consequently, it will pass the check at line 1816. Segfault happens at line
1819.
Generate a resolv.conf with generate-resolv.conf, then compile and run
poc.c. See entry-functions.txt for functions in tor that might be
vulnerable.
Please credit 'Guido Vranken' for this discovery through the Tor bug bounty
program."
Reproducer for gdb (https://gist.github.com/azat/be2b0d5e9417ba0dfe2c):
start
p (1ULL<<31)+1ULL
# $1 = 2147483649
p malloc(sizeof(struct sockaddr))
# $2 = (void *) 0x646010
p malloc(sizeof(int))
# $3 = (void *) 0x646030
p malloc($1)
# $4 = (void *) 0x7fff76a2a010
p memset($4, 1, $1)
# $5 = 1990369296
p (char *)$4
# $6 = 0x7fff76a2a010 '\001' <repeats 200 times>...
set $6[0]='['
set $6[$1]=']'
p evutil_parse_sockaddr_port($4, $2, $3)
# $7 = -1
Before:
$ gdb bin/http-connect < gdb
(gdb) $1 = 2147483649
(gdb) (gdb) $2 = (void *) 0x646010
(gdb) (gdb) $3 = (void *) 0x646030
(gdb) (gdb) $4 = (void *) 0x7fff76a2a010
(gdb) (gdb) $5 = 1990369296
(gdb) (gdb) $6 = 0x7fff76a2a010 '\001' <repeats 200 times>...
(gdb) (gdb) (gdb) (gdb)
Program received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () at memcpy-sse2-unaligned.S:36
After:
$ gdb bin/http-connect < gdb
(gdb) $1 = 2147483649
(gdb) (gdb) $2 = (void *) 0x646010
(gdb) (gdb) $3 = (void *) 0x646030
(gdb) (gdb) $4 = (void *) 0x7fff76a2a010
(gdb) (gdb) $5 = 1990369296
(gdb) (gdb) $6 = 0x7fff76a2a010 '\001' <repeats 200 times>...
(gdb) (gdb) (gdb) (gdb) $7 = -1
(gdb) (gdb) quit
Fixes: #318
Diffstat (limited to 'evutil.c')
-rw-r--r-- | evutil.c | 6 |
1 files changed, 3 insertions, 3 deletions
@@ -2058,12 +2058,12 @@ evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int * cp = strchr(ip_as_string, ':'); if (*ip_as_string == '[') { - int len; + size_t len; if (!(cp = strchr(ip_as_string, ']'))) { return -1; } - len = (int) ( cp-(ip_as_string + 1) ); - if (len > (int)sizeof(buf)-1) { + len = ( cp-(ip_as_string + 1) ); + if (len > sizeof(buf)-1) { return -1; } memcpy(buf, ip_as_string+1, len); |