Memory Corruption in During Deserialized-object Destruction

Sec Bug #73052 Memory Corruption in During Deserialized-object Destruction
Submitted: 2016-09-09 03:07 UTC Modified: 2016-09-16 13:36 UTC
From: taoguangchen at icloud dot com Assigned: stas (profile)
Status: Closed Package: *General Issues
PHP Version: 5.6.25 OS:
Private report: No CVE-ID: 2016-7411

 [2016-09-09 03:07 UTC] taoguangchen at icloud dot com

Description:
------------
Memory Corruption in During Deserialized-object Destruction

```
if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) {
    /* We've got partially constructed object on our hands here. Wipe it. */
    if(Z_TYPE_PP(rval) == IS_OBJECT) {
       zend_hash_clean(Z_OBJPROP_PP(rval));
    }
    ZVAL_NULL(*rval);
  return 0;
}
```

If object deserialization fails, the broken-object's properties will be cleaned. But the object still stored in objects_store, then destructor call with uninitialized properties in during shutdown, that result in memory corruption. 

PoC:
```
<?php

class obj {
    var $ryat;
    public function __destruct() {
        $this->ryat = null;
    }
}

$poc = 'O:3:"obj":1:{';
unserialize($poc);

?>
```

Fix:

You need to set the broken-object's destructor_called into 1.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports

 [2016-09-09 11:14 UTC] taoguangchen at icloud dot com

Fix:

```
if(Z_TYPE_PP(rval) == IS_OBJECT) {
	zend_hash_clean(Z_OBJPROP_PP(rval));
+	EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(rval)].destructor_called = 1;
}
```

 [2016-09-09 17:20 UTC] stas@php.net

It's not a good idea to directly access internal structures in serializer code, but I'll look for a better solution.

 [2016-09-12 03:31 UTC] taoguangchen at icloud dot com

You can also consider calling zend_object_store_ctor_failed()

```
if(Z_TYPE_PP(rval) == IS_OBJECT) {
	zend_hash_clean(Z_OBJPROP_PP(rval));
+	zend_object_store_ctor_failed(*rval, TSRMLS_CC);
}
```

 [2016-09-12 04:06 UTC] stas@php.net

Yes, zend_object_store_ctor_failed would be better here.

 [2016-09-12 04:20 UTC] stas@php.net

-Assigned To: +Assigned To: stas

 [2016-09-13 04:04 UTC] stas@php.net

-Status: Assigned +Status: Closed

 [2016-09-16 13:36 UTC] kaplan@php.net

-CVE-ID: needed +CVE-ID: 2016-7411