CVE-2014-9714: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site scripting (XSS) vulnerability in the WddxPacket::recursiveAddVar function in HHVM (aka the HipHop Virtual Machine) before 3.5.0 allows remote attackers to inject arbitrary web script or HTML via a crafted string to the wddx_serialize_value function.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Published: 2015-04-13T14:59Z
Repository: https://github.com/facebook/hhvm
Language: PHP
Files changed: hphp/runtime/ext/wddx/ext_wddx.cpp, hphp/test/slow/ext_wddx/htmlent.php, hphp/test/slow/ext_wddx/htmlent.php.expect
Commit date: 2014-11-20 17:00:42 -0800
Commit message: HTMLEncode strings in wddx_serialize_value()

Summary: Strings returned through wddx_serialize_value should be HTMLEncode()'d during
serialization.

Fixes #4283

{sync, type="child", parent="internal", parentrevid="1691695", parentrevfbid="1537976659780590", parentdiffid="5726084"}

Reviewed By: @JoelMarcey

Differential Revision: D1691695

Signature: t1:1691695:1416530595:722bfcdaf7c0dbee379bea886cd4c43d997ca7dd

Diff: diff --git a/hphp/runtime/ext/wddx/ext_wddx.cpp b/hphp/runtime/ext/wddx/ext_wddx.cpp
index be49b776f18..9d249de0d7b 100644
--- a/hphp/runtime/ext/wddx/ext_wddx.cpp
+++ b/hphp/runtime/ext/wddx/ext_wddx.cpp
@@ -124,13 +124,17 @@ bool WddxPacket::recursiveAddVar(const String& varName,
     return true;
   }
 
   std::string varType = getDataTypeString(varVariant.getType()).data();
   if (!getWddxEncoded(varType, "", varName, false).empty()) {
-    std::string varValue = varVariant.toString().data();
+    std::string varValue;
     if (varType.compare("boolean") == 0) {
       varValue = varVariant.toBoolean() ? "true" : "false";
+    } else {
+      varValue = StringUtil::HtmlEncode(varVariant.toString(),
+                                        StringUtil::QuoteStyle::Double,
+                                        "UTF-8", false, false).toCppString();
     }
     m_packetString += getWddxEncoded(varType, varValue, varName, hasVarTag);
     return true;
   }
 
diff --git a/hphp/test/slow/ext_wddx/htmlent.php b/hphp/test/slow/ext_wddx/htmlent.php
new file mode 100644
index 00000000000..c87d13db3df
--- /dev/null
+++ b/hphp/test/slow/ext_wddx/htmlent.php
@@ -0,0 +1,5 @@
+<?php
+$s = wddx_serialize_value("Test for &");
+var_dump($s);
+$d = wddx_deserialize($s);
+var_dump($d);
diff --git a/hphp/test/slow/ext_wddx/htmlent.php.expect b/hphp/test/slow/ext_wddx/htmlent.php.expect
new file mode 100644
index 00000000000..82c95fdf287
--- /dev/null
+++ b/hphp/test/slow/ext_wddx/htmlent.php.expect
@@ -0,0 +1,2 @@
+string(92) "<wddxPacket version='1.0'><header/><data><string>Test for &amp;</string></data></wddxPacket>"
+string(10) "Test for &"

Vulnerable code:     std::string varValue = varVariant.toString().data();
Fixed code:     std::string varValue;
    } else {
      varValue = StringUtil::HtmlEncode(varVariant.toString(),
                                        StringUtil::QuoteStyle::Double,
                                        "UTF-8", false, false).toCppString();
<?php
$s = wddx_serialize_value("Test for &");
var_dump($s);
$d = wddx_deserialize($s);
var_dump($d);
string(92) "<wddxPacket version='1.0'><header/><data><string>Test for &amp;</string></data></wddxPacket>"
string(10) "Test for &"