|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [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
 
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 03:00:01 2025 UTC | 
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.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?