|
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 GroupAll rights reserved. |
Last updated: Mon Oct 27 16: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?