php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71683 Null pointer dereference in zend_hash_str_find_bucket
Submitted: 2016-02-28 15:02 UTC Modified: 2016-03-11 23:20 UTC
From: dmoorefo at gmail dot com Assigned: yohgaki
Status: Closed Package: Reproducible crash
PHP Version: 7.0.3 OS: Ubuntu 14.04.1 32-bit
Private report: No CVE-ID:
 [2016-02-28 15:02 UTC] dmoorefo at gmail dot com
Description:
------------
A crafted ini file will cause a null pointer dereference leading to a segfault: 

; crash.ini
session.auto_start=1
session.use_only_cookies=

It appears that setting session.auto_start makes php run as if in a web server context yet it is running as a command line program. When REQUEST_URI is checked from the http globals, zend_hash_str_find_bucket is called with a null hash table. This causes a 4 byte invalid read at 0x10.

 
From ext/session/session.c:1613:

if (PS(define_sid) && !PS(id) &&
    (data = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]),
    "REQUEST_URI", sizeof("REQUEST_URI") - 1)) &&Z_TYPE_P(data) == IS_STRING &&
    (p = strstr(Z_STRVAL_P(data), PS(session_name))) && p[lensess] == '='

I could not reproduce this with PHP 5.6.18.


Test script:
---------------
Compile 7.0.3 with ./configure and make.

# python -c "print 'session.auto_start=1\nsession.use_only_cookies='" > crash.ini
# ./sapi/cli/php -c crash.ini -r ''
Segmentation fault
#

# uname -a
Linux x-Acer 3.19.0-33-generic #38~14.04.1-Ubuntu SMP Fri Nov 6 18:17:49 UTC 2015 i686 i686 i686 GNU/Linux

Expected result:
----------------
No segfault.

Actual result:
--------------
==30268== Memcheck, a memory error detector
==30268== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==30268== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==30268== Command: php -c min-000000 -r 
==30268== 
==30268== Invalid read of size 4
==30268==    at 0x8450C37: zend_hash_str_find_bucket (zend_hash.c:515)
==30268==    by 0x8450C37: zend_hash_str_find (zend_hash.c:1959)
==30268==    by 0x829756B: php_session_start (session.c:1613)
==30268==    by 0x829B366: php_rinit_session (session.c:2624)
==30268==    by 0x829B385: zm_activate_session (session.c:2632)
==30268==    by 0x8438058: zend_activate_modules (zend_API.c:2536)
==30268==    by 0x83A06DF: php_request_startup (main.c:1626)
==30268==    by 0x8553892: do_cli (php_cli.c:945)
==30268==    by 0x8554A4C: main (php_cli.c:1345)
==30268==  Address 0x10 is not stack'd, malloc'd or (recently) free'd


(gdb) bt
#0  0x08450c37 in zend_hash_str_find_bucket (h=0x8e64879d, len=0xb, str=0x895d637 "REQUEST_URI", 
    ht=0x0) at /root/php-7.0.3/Zend/zend_hash.c:515
#1  zend_hash_str_find (ht=0x0, str=0x895d637 "REQUEST_URI", len=0xb)
    at /root/php-7.0.3/Zend/zend_hash.c:1959
#2  0x0829756c in php_session_start () at /root/php-7.0.3/ext/session/session.c:1613
#3  0x0829b367 in php_rinit_session (auto_start=0x1) at /root/php-7.0.3/ext/session/session.c:2624
#4  0x0829b386 in zm_activate_session (type=0x1, module_number=0x13)
    at /root/php-7.0.3/ext/session/session.c:2632
#5  0x08438059 in zend_activate_modules () at /root/php-7.0.3/Zend/zend_API.c:2536
#6  0x083a06e0 in php_request_startup () at /root/php-7.0.3/main/main.c:1626
#7  0x08553893 in do_cli (argc=0x3, argv=0x8a67fb0) at /root/php-7.0.3/sapi/cli/php_cli.c:945
#8  0x08554a4d in main (argc=0x3, argv=0x8a67fb0) at /root/php-7.0.3/sapi/cli/php_cli.c:1345
(gdb) i r
eax            0x0	0x0
ecx            0x8e648754	0x8e648754
edx            0x895d642	0x895d642
ebx            0x8e64879d	0x8e64879d
esp            0xbfffdb50	0xbfffdb50
ebp            0xbfffdba8	0xbfffdba8
esi            0x0	0x0
edi            0x8a681f8	0x8a681f8
eip            0x8450c37	0x8450c37 <zend_hash_str_find+503>
eflags         0x10282	[ SF IF RF ]
cs             0x73	0x73
ss             0x7b	0x7b
ds             0x7b	0x7b
es             0x7b	0x7b
fs             0x0	0x0
gs             0x33	0x33
 


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-03-01 15:39 UTC] johannes@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: yohgaki
 [2016-03-01 15:39 UTC] johannes@php.net
Assigning to yohgaki who works on session things. I don't think this is a security bug - if you can run PHP from CLI and use a custom ini you have full power already.
 [2016-03-01 18:58 UTC] yohgaki@php.net
Ack
 [2016-03-01 19:07 UTC] yohgaki@php.net
-Status: Assigned +Status: Analyzed
 [2016-03-01 19:07 UTC] yohgaki@php.net
Offending line should be 

(data = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "REQUEST_URI", sizeof("REQUEST_URI") - 1))

IIRC, $_SERVER is jit global and it is not initialized here. I'll prepare patch soon, but I need to check code if initializing array is better or not.
 [2016-03-09 10:14 UTC] yohgaki@php.net
This is patch fixes the crash.

diff --git a/ext/session/session.c b/ext/session/session.c
index 994d762..d0ee626 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -1611,6 +1611,7 @@ PHPAPI void php_session_start(void) /* {{{ */
 		 * '<session-name>=<session-id>' to allow URLs of the form
 		 * http://yoursite/<session-name>=<session-id>/script.php */
 		if (PS(define_sid) && !PS(id) &&
+			zend_is_auto_global_str("_SERVER", sizeof("_SERVER")-1) == SUCCESS &&
 			(data = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "REQUEST_URI", sizeof("REQUEST_URI") - 1)) &&
 			Z_TYPE_P(data) == IS_STRING &&
 			(p = strstr(Z_STRVAL_P(data), PS(session_name))) &&

As I commented earlier, it was jit global issue.
We may fix this as a reliability issue which is a part of security property, but I don't think this crash is exploitable, is this?
 [2016-03-09 20:09 UTC] dmoorefo at gmail dot com
Agreed - the exploitability of this is extremely low and it should be reclassified as a reliability issue.

I have verified that the patch fixes the issue in 7.0.3 and 7.0.4.
 [2016-03-09 22:42 UTC] stas@php.net
-Type: Security +Type: Bug
 [2016-03-09 22:42 UTC] stas@php.net
Does not look like security issue. It's CLI and requires special settings which are extremely uncommon for CLI.
 [2016-03-11 01:33 UTC] yohgaki@php.net
OK. I'll just merge the fix to branches.
 [2016-03-11 23:19 UTC] yohgaki@php.net
Related to #71754
The fix committed for #71754 breaks transid. Correct patch will be committed soon.
 [2016-03-11 23:20 UTC] yohgaki@php.net
Related to Bug #71754
 [2016-03-11 23:34 UTC] yohgaki@php.net
Automatic comment on behalf of yohgaki
Revision: http://git.php.net/?p=php-src.git;a=commit;h=50fca7a02a6dff553b0b8cfbb8bfba39c88fb6ae
Log: Fixed Bug #71683 Null pointer dereference in zend_hash_str_find_bucket
 [2016-03-11 23:34 UTC] yohgaki@php.net
-Status: Analyzed +Status: Closed
 [2016-03-11 23:43 UTC] yohgaki@php.net
Automatic comment on behalf of yohgaki
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ca61f5954bf9e64072bfa31b4a7431e211a109e7
Log: Fixed Bug #71754 Regression in PHP7.0: trivial script segfaults php-cgi Fixed Bug #71683 Null pointer dereference in zend_hash_str_find_bucket Fixed Bug #71599 trans sid handling rework broke interaction with cookies
 [2016-03-11 23:43 UTC] yohgaki@php.net
Automatic comment on behalf of yohgaki
Revision: http://git.php.net/?p=php-src.git;a=commit;h=50fca7a02a6dff553b0b8cfbb8bfba39c88fb6ae
Log: Fixed Bug #71683 Null pointer dereference in zend_hash_str_find_bucket
 [2016-03-14 14:59 UTC] ab@php.net
Automatic comment on behalf of yohgaki
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ca61f5954bf9e64072bfa31b4a7431e211a109e7
Log: Fixed Bug #71754 Regression in PHP7.0: trivial script segfaults php-cgi Fixed Bug #71683 Null pointer dereference in zend_hash_str_find_bucket Fixed Bug #71599 trans sid handling rework broke interaction with cookies
 [2016-07-20 11:33 UTC] davey@php.net
Automatic comment on behalf of yohgaki
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ca61f5954bf9e64072bfa31b4a7431e211a109e7
Log: Fixed Bug #71754 Regression in PHP7.0: trivial script segfaults php-cgi Fixed Bug #71683 Null pointer dereference in zend_hash_str_find_bucket Fixed Bug #71599 trans sid handling rework broke interaction with cookies
 [2016-07-20 11:33 UTC] davey@php.net
Automatic comment on behalf of yohgaki
Revision: http://git.php.net/?p=php-src.git;a=commit;h=50fca7a02a6dff553b0b8cfbb8bfba39c88fb6ae
Log: Fixed Bug #71683 Null pointer dereference in zend_hash_str_find_bucket
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Feb 19 11:01:37 2017 UTC