CVE-2016-10162 (published 2017-01-24T21:59Z)

The php_wddx_pop_element function in ext/wddx/wddx.c in PHP 7.0.x before 7.0.15 and 7.1.x before 7.1.1 allows remote attackers to cause a denial of service (NULL pointer dereference and application crash) via an inapplicable class name in a wddxPacket XML document, leading to mishandling in a wddx_deserialize call.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-476
cwe_name: NULL Pointer Dereference
description: The product dereferences a pointer that it expects to be valid but is NULL.
extended_description: 
            
            
            
         
         

Fix information:
repo_url: https://github.com/php/php-src
commit_details: repo_url: https://github.com/php/php-src
author: Stanislav Malyshev
author_date: 2016-12-31 20:14:20-08:00
msg: Fix bug #73831 - NULL Pointer Dereference while unserialize php object
repository: repo_url: https://github.com/php/php-src
repo_name: php/php-src
description: The PHP Interpreter
repo_language: C
owner: php
file_changes: filename: bug73831.phpt
change_type: ModificationType.ADD
diff: @@ -0,0 +1,23 @@
+--TEST--
+Bug #73831 (NULL Pointer Dereference while unserialize php object)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--FILE--
+<?php
+$xml = <<<EOF
+<?xml version="1.0" ?>
+<wddxPacket version="1.0">
+	<struct>
+		<var name="php_class_name">
+			<string>Throwable</string>
+                </var>
+        </struct>
+</wddxPacket>
+EOF;
+try {
+	$wddx = wddx_deserialize($xml);
+} catch(Error $e) { echo $e->getMessage(); }
+?>
+--EXPECTF--
+Warning: wddx_deserialize(): Class throwable can not be instantiated in %sbug73831.php on line %d
+Cannot instantiate interface Throwable

programming_language: PHP
filename: wddx.c
change_type: ModificationType.MODIFY
diff: @@ -908,7 +908,7 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
 
 		if (!strcmp((char *)name, EL_BINARY)) {
 			zend_string *new_str = NULL;
-			
+
 			if (ZSTR_EMPTY_ALLOC() != Z_STR(ent1->data)) {
 				new_str = php_base64_decode(
 					(unsigned char *)Z_STRVAL(ent1->data), Z_STRLEN(ent1->data));
@@ -967,22 +967,26 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
 							php_error_docref(NULL, E_WARNING, "Class %s can not be unserialized", Z_STRVAL(ent1->data));
 						} else {
 							/* Initialize target object */
-							object_init_ex(&obj, pce);
-
-							/* Merge current hashtable with object's default properties */
-							zend_hash_merge(Z_OBJPROP(obj),
-											Z_ARRVAL(ent2->data),
-											zval_add_ref, 0);
-
-							if (incomplete_class) {
-								php_store_class_name(&obj, Z_STRVAL(ent1->data), Z_STRLEN(ent1->data));
+							if (object_init_ex(&obj, pce) != SUCCESS || EG(exception)) {
+								zval_ptr_dtor(&ent2->data);
+								ZVAL_UNDEF(&ent2->data);
+								php_error_docref(NULL, E_WARNING, "Class %s can not be instantiated", Z_STRVAL(ent1->data));
+							} else {
+								/* Merge current hashtable with object's default properties */
+								zend_hash_merge(Z_OBJPROP(obj),
+												Z_ARRVAL(ent2->data),
+												zval_add_ref, 0);
+
+								if (incomplete_class) {
+									php_store_class_name(&obj, Z_STRVAL(ent1->data), Z_STRLEN(ent1->data));
+								}
+
+								/* Clean up old array entry */
+								zval_ptr_dtor(&ent2->data);
+
+								/* Set stack entry to point to the newly created object */
+								ZVAL_COPY_VALUE(&ent2->data, &obj);
 							}
-
-							/* Clean up old array entry */
-							zval_ptr_dtor(&ent2->data);
-
-							/* Set stack entry to point to the newly created object */
-							ZVAL_COPY_VALUE(&ent2->data, &obj);
 						}
 
 						/* Clean up class name var entry */

programming_language: C