Bug 732516 (CVE-2011-3182) - CVE-2011-3182 php: multiple NULL pointer dereferences
Summary: CVE-2011-3182 php: multiple NULL pointer dereferences
Keywords:
Status: CLOSED NOTABUG
Alias: CVE-2011-3182
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks: 732517
TreeView+ depends on / blocked
 
Reported: 2011-08-22 19:00 UTC by Josh Bressers
Modified: 2021-02-24 14:53 UTC (History)
2 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2011-09-21 05:00:58 UTC
Embargoed:


Attachments (Terms of Use)

Description Josh Bressers 2011-08-22 19:00:24 UTC
Maksymilian Arciemowicz reported multiple NULL pointer dereference flaws in
PHP. PHP contains multiple unchecked calls to malloc(). If one of these
flaws fail, it could lead to a NULL pointer dereference, potentially
overwriting arbitrary memory.

It is not currently known how to exploit this flaw in PHP. The possibility
cannot be ruled out though.

Comment 1 Josh Bressers 2011-08-22 19:02:25 UTC
Advisory from Full Disclosure:

[ 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/

Comment 3 Huzaifa S. Sidhpurwala 2011-09-20 07:57:26 UTC
Following commits to the 5.3 branch would resolve the issue:

r313903 | pajoye | 2011-07-29 02:46:51 +0530 (Fri, 29 Jul 2011) | 1 line

- Fix #55301 (sybase part, take #2) check if malloc succeded
------------------------------------------------------------------------
r313835 | pajoye | 2011-07-28 16:31:04 +0530 (Thu, 28 Jul 2011) | 1 line

- Fix #55301 (mssql part) check if malloc succeded
------------------------------------------------------------------------
r313833 | pajoye | 2011-07-28 16:27:31 +0530 (Thu, 28 Jul 2011) | 1 line

- Fix #55301 (sybase part) check if malloc succeded
------------------------------------------------------------------------
r313832 | pajoye | 2011-07-28 16:22:45 +0530 (Thu, 28 Jul 2011) | 1 line

- Fix #55301 (url scanner part) check if malloc succeded
------------------------------------------------------------------------
r313831 | pajoye | 2011-07-28 16:12:45 +0530 (Thu, 28 Jul 2011) | 1 line

- Fix #55301 (readline part) check if malloc succeded
------------------------------------------------------------------------
r313830 | pajoye | 2011-07-28 16:09:19 +0530 (Thu, 28 Jul 2011) | 1 line

- Fix #55301 (interbase part) check if malloc succeded
------------------------------------------------------------------------
r313828 | pajoye | 2011-07-28 16:07:04 +0530 (Thu, 28 Jul 2011) | 1 line

- Fix #55301 (pdo_odbc part) check if malloc succeded
------------------------------------------------------------------------
r313827 | pajoye | 2011-07-28 16:04:16 +0530 (Thu, 28 Jul 2011) | 1 line

- Fix #55301 (com_dotnet part) check if malloc succeded
------------------------------------------------------------------------
r313826 | pajoye | 2011-07-28 16:01:34 +0530 (Thu, 28 Jul 2011) | 1 line

- Fix #55301 (curl part) check if malloc succeded
------------------------------------------------------------------------
r313782 | pajoye | 2011-07-27 19:53:06 +0530 (Wed, 27 Jul 2011) | 1 line

- Fix #55295, check if malloc failed

Comment 4 Huzaifa S. Sidhpurwala 2011-09-20 07:58:26 UTC
php upstream bug:
https://bugs.php.net/bug.php?id=55301

Comment 9 Doran Moppert 2020-02-11 00:11:27 UTC
Statement:

Red Hat does not consider this flaw to be a security issue.  It is improbable that a script would accept untrusted user input or unvalidated script input data and use it to malloc memory, without filtering/sanitizing it, therefore the value used to malloc memory is under the the full control of the script author and no trust boundary is crossed.


Note You need to log in before you can comment on or make changes to this bug.