CVE-2016-1000004: Insufficient Verification of Data Authenticity (CWE-345)
value: Insufficient type checks were employed prior to casting input data in SimpleXMLElement_exportNode and simplexml_import_dom. This issue affects HHVM versions prior to 3.9.5, all versions between 3.10.0 and 3.12.3 (inclusive), and all versions between 3.13.0 and 3.14.1 (inclusive).
CWE description: The product does not sufficiently verify the origin or authenticity of data, in a way that causes it to accept invalid data.
CVSS v3 base score: 9.8
Published: 2020-02-19T13:15Z
Repository: https://github.com/facebook/hhvm
Language: PHP
Files changed: hphp/runtime/ext/simplexml/ext_simplexml.cpp, hphp/test/slow/ext_domdocument/simplexml_null.php, hphp/test/slow/ext_domdocument/simplexml_null.php.expectf
Commit date: 2016-07-01 09:19:25 -0700
Commit message: Type safety in simplexml import routines

Reviewed By: Orvid

Differential Revision: D3447275

fbshipit-source-id: d859c97f9d85c520b0e371cef6dcb19bb2ef7dbf

Diff: diff --git a/hphp/runtime/ext/simplexml/ext_simplexml.cpp b/hphp/runtime/ext/simplexml/ext_simplexml.cpp
index 6795c392411..3e825cc06fc 100644
--- a/hphp/runtime/ext/simplexml/ext_simplexml.cpp
+++ b/hphp/runtime/ext/simplexml/ext_simplexml.cpp
@@ -372,11 +372,11 @@ static xmlNodePtr php_sxe_get_first_node(SimpleXMLElement* sxe,
     return node;
   }
 }
 
 xmlNodePtr SimpleXMLElement_exportNode(const Object& sxe) {
-  assert(sxe->instanceof(SimpleXMLElement_classof()));
+  if (!sxe->instanceof(SimpleXMLElement_classof())) return nullptr;
   auto data = Native::data<SimpleXMLElement>(sxe.get());
   return php_sxe_get_first_node(data, data->nodep());
 }
 
 static Object sxe_prop_dim_read(SimpleXMLElement* sxe, const Variant& member,
@@ -1164,13 +1164,19 @@ static const Class* class_from_name(const String& class_name,
     cls = SimpleXMLElement_classof();
   }
   return cls;
 }
 
+const StaticString s_DOMNode("DOMNode");
+
 static Variant HHVM_FUNCTION(simplexml_import_dom,
-  const Object& node,
-  const String& class_name /* = "SimpleXMLElement" */) {
+                             const Object& node,
+                             const String& class_name) {
+  if (!node->instanceof(s_DOMNode)) {
+    raise_warning("Invalid Nodetype to import");
+    return init_null();
+  }
   auto domnode = Native::data<DOMNode>(node);
   xmlNodePtr nodep = domnode->nodep();
 
   if (nodep) {
     if (nodep->doc == nullptr) {
diff --git a/hphp/test/slow/ext_domdocument/simplexml_null.php b/hphp/test/slow/ext_domdocument/simplexml_null.php
new file mode 100644
index 00000000000..35d08226fc9
--- /dev/null
+++ b/hphp/test/slow/ext_domdocument/simplexml_null.php
@@ -0,0 +1,5 @@
+<?php
+
+$date = date_create_immutable();
+var_dump(dom_import_simplexml($date));
+var_dump(simplexml_import_dom($date));
diff --git a/hphp/test/slow/ext_domdocument/simplexml_null.php.expectf b/hphp/test/slow/ext_domdocument/simplexml_null.php.expectf
new file mode 100644
index 00000000000..b3c55c5ae6e
--- /dev/null
+++ b/hphp/test/slow/ext_domdocument/simplexml_null.php.expectf
@@ -0,0 +1,5 @@
+Warning: Invalid Nodetype to import in %s/test/slow/ext_domdocument/simplexml_null.php on line 4
+NULL
+
+Warning: Invalid Nodetype to import in %s/test/slow/ext_domdocument/simplexml_null.php on line 5
+NULL

Vulnerable code:   assert(sxe->instanceof(SimpleXMLElement_classof()));
  const Object& node,
  const String& class_name /* = "SimpleXMLElement" */) {
Fixed code:   if (!sxe->instanceof(SimpleXMLElement_classof())) return nullptr;
const StaticString s_DOMNode("DOMNode");

                             const Object& node,
                             const String& class_name) {
  if (!node->instanceof(s_DOMNode)) {
    raise_warning("Invalid Nodetype to import");
    return init_null();
  }
<?php

$date = date_create_immutable();
var_dump(dom_import_simplexml($date));
var_dump(simplexml_import_dom($date));
Warning: Invalid Nodetype to import in %s/test/slow/ext_domdocument/simplexml_null.php on line 4
NULL

Warning: Invalid Nodetype to import in %s/test/slow/ext_domdocument/simplexml_null.php on line 5
NULL