From a33a4b3081e4c231cadccfa2a1f76f983467c324 Mon Sep 17 00:00:00 2001 From: bnu Date: Wed, 4 Feb 2015 13:49:21 +0900 Subject: [PATCH] =?UTF-8?q?fix=20#1227=20SECISSUE=20-=20XXE=20=EC=B7=A8?= =?UTF-8?q?=EC=95=BD=EC=A0=90=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?-=20Drupal=EC=9D=98=20=EC=86=8C=EC=8A=A4=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=B0=B8=EA=B3=A0=ED=95=98=EC=97=AC=20`Security::d?= =?UTF-8?q?etectingXEE()`=20=EC=B6=94=EA=B0=80=20=20=20-=20https://github.?= =?UTF-8?q?com/drupal/drupal/commit/90e884ad0f7f2cf269d953f7d70966de9fd821?= =?UTF-8?q?ff=20-=20blogapi=20=EC=95=A0=EB=93=9C=EC=98=A8=20=EB=B0=8F=20`C?= =?UTF-8?q?ontext::=5FsetXmlRpcArgument()`=EC=97=90=EC=84=9C=20=EC=B7=A8?= =?UTF-8?q?=EC=95=BD=EC=A0=90=20=EB=B0=A9=EC=96=B4=20-=20=EC=A0=9C?= =?UTF-8?q?=EB=B3=B4=20:=20=ED=95=9C=EA=B5=AD=EC=9D=B8=ED=84=B0=EB=84=B7?= =?UTF-8?q?=EC=A7=84=ED=9D=A5=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/blogapi/blogapi.addon.php | 13 ++++++-- classes/context/Context.class.php | 9 +++++- classes/security/Security.class.php | 49 +++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/addons/blogapi/blogapi.addon.php b/addons/blogapi/blogapi.addon.php index d78bf0eb7..913f3ae4c 100644 --- a/addons/blogapi/blogapi.addon.php +++ b/addons/blogapi/blogapi.addon.php @@ -30,8 +30,10 @@ if($_REQUEST['act'] != 'api') // Read func file require_once(_XE_PATH_ . 'addons/blogapi/blogapi.func.php'); +$xml = $GLOBALS['HTTP_RAW_POST_DATA']; + // If HTTP_RAW_POST_DATA is NULL, Print error message -if(!$GLOBALS['HTTP_RAW_POST_DATA']) +if(!$xml) { $content = getXmlRpcFailure(1, 'Invalid Method Call'); printContent($content); @@ -39,7 +41,14 @@ if(!$GLOBALS['HTTP_RAW_POST_DATA']) // xmlprc parsing // Parse the requested xmlrpc -$xml = new SimpleXMLElement($GLOBALS['HTTP_RAW_POST_DATA']); +if(Security::detectingXEE($xml)) +{ + header("HTTP/1.0 400 Bad Request"); + exit; +} + +if(version_compare(PHP_VERSION, '5.2.11', '<=')) libxml_disable_entity_loader(true); +$xml = new SimpleXMLElement($xml, LIBXML_NONET | LIBXML_NOENT); $method_name = (string)$xml->methodName; $params = $xml->params->param; diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index 0cad7d3f5..1ed44854d 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -1240,8 +1240,15 @@ class Context return; } + $xml = $GLOBALS['HTTP_RAW_POST_DATA']; + if(Security::detectingXEE($xml)) + { + header("HTTP/1.0 400 Bad Request"); + exit; + } + $oXml = new XmlParser(); - $xml_obj = $oXml->parse(); + $xml_obj = $oXml->parse($xml); $params = $xml_obj->methodcall->params; unset($params->node_name, $params->attrs, $params->body); diff --git a/classes/security/Security.class.php b/classes/security/Security.class.php index c326d6a34..176ba0ed5 100644 --- a/classes/security/Security.class.php +++ b/classes/security/Security.class.php @@ -175,6 +175,55 @@ class Security return $var; } + /** + * @brief check XML External Entity + * + * @see from drupal. https://github.com/drupal/drupal/commit/90e884ad0f7f2cf269d953f7d70966de9fd821ff + * + * @param string $xml + * @return bool + */ + static function detectingXEE($xml) + { + if(!$xml) return FALSE; + + if(strpos($xml, '/s', '', substr($xml, 0, 100), 1); + $xml = trim(substr_replace($xml, $header, 0, 100)); + if($xml == '') + { + return TRUE; + } + + // Strip DTD. + $header = preg_replace('/^]*+>/i', '', substr($xml, 0, 200), 1); + $xml = trim(substr_replace($xml, $header, 0, 200)); + if($xml == '') + { + return TRUE; + } + + // Confirm the XML now starts with a valid root tag. A root tag can end in [> \t\r\n] + $root_tag = substr($xml, 0, strcspn(substr($xml, 0, 20), "> \t\r\n")); + + // Reject a second DTD. + if(strtoupper($root_tag) == '