Skip to content

Commit

Permalink
Merge pull request #20 from OpenMage/patch/SUPEE-3762
Browse files Browse the repository at this point in the history
Applied patch SUPEE-3762 to address XML entity escaping vulnerability
  • Loading branch information
LeeSaferite committed Jun 17, 2015
2 parents a94c3e1 + 882abe1 commit 820fb7e
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 11 deletions.
6 changes: 6 additions & 0 deletions app/etc/applied.patches.list
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,9 @@ patching file lib/PEAR/PEAR/PEAR5.php
patching file lib/Varien/Io/File.php


2014-08-12 23:00:46 UTC | SUPEE-3762 | EE_1.14.0.1 | v1 | 3608d69d73a826b371f9893b49ddcb347c9b3f37 | Thu Jun 12 11:08:43 2014 -0700 | v1.14.0.1..HEAD
patching file lib/Zend/Soap/Server.php
patching file lib/Zend/Xml/Exception.php
patching file lib/Zend/Xml/Security.php


25 changes: 14 additions & 11 deletions lib/Zend/Soap/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
*/
#require_once 'Zend/Server/Interface.php';

/** @see Zend_Xml_Security */
#require_once 'Zend/Xml/Security.php';

/** @see Zend_Xml_Exception */
#require_once 'Zend/Xml/Exception.php';

/**
* Zend_Soap_Server
*
Expand Down Expand Up @@ -729,21 +735,18 @@ protected function _setRequest($request)
$xml = $request;
}

libxml_disable_entity_loader(true);
$dom = new DOMDocument();
if(strlen($xml) == 0 || !$dom->loadXML($xml)) {
#require_once 'Zend/Soap/Server/Exception.php';
throw new Zend_Soap_Server_Exception('Invalid XML');
}
foreach ($dom->childNodes as $child) {
if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
try {
if(strlen($xml) == 0 || (!$dom = Zend_Xml_Security::scan($xml, $dom))) {
#require_once 'Zend/Soap/Server/Exception.php';
throw new Zend_Soap_Server_Exception(
'Invalid XML: Detected use of illegal DOCTYPE'
);
throw new Zend_Soap_Server_Exception('Invalid XML');
}
} catch (Zend_Xml_Exception $e) {
#require_once 'Zend/Soap/Server/Exception.php';
throw new Zend_Soap_Server_Exception(
$e->getMessage()
);
}
libxml_disable_entity_loader(false);
}
$this->_request = $xml;
return $this;
Expand Down
36 changes: 36 additions & 0 deletions lib/Zend/Xml/Exception.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Xml
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/


/**
* @see Zend_Exception
*/
#require_once 'Zend/Exception.php';


/**
* @category Zend
* @package Zend_Xml
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Xml_Exception extends Zend_Exception
{}
164 changes: 164 additions & 0 deletions lib/Zend/Xml/Security.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Xml
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/


/**
* @category Zend
* @package Zend_Xml_SecurityScan
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Xml_Security
{
const ENTITY_DETECT = 'Detected use of ENTITY in XML, disabled to prevent XXE/XEE attacks';

/**
* Heuristic scan to detect entity in XML
*
* @param string $xml
* @throws Zend_Xml_Exception
*/
protected static function heuristicScan($xml)
{
if (strpos($xml, '<!ENTITY') !== false) {
#require_once 'Exception.php';
throw new Zend_Xml_Exception(self::ENTITY_DETECT);
}
}

/**
* @param integer $errno
* @param string $errstr
* @param string $errfile
* @param integer $errline
* @return bool
*/
public static function loadXmlErrorHandler($errno, $errstr, $errfile, $errline)
{
if (substr_count($errstr, 'DOMDocument::loadXML()') > 0) {
return true;
}
return false;
}

/**
* Scan XML string for potential XXE and XEE attacks
*
* @param string $xml
* @param DomDocument $dom
* @throws Zend_Xml_Exception
* @return SimpleXMLElement|DomDocument|boolean
*/
public static function scan($xml, DOMDocument $dom = null)
{
// If running with PHP-FPM we perform an heuristic scan
// We cannot use libxml_disable_entity_loader because of this bug
// @see https://bugs.php.net/bug.php?id=64938
if (self::isPhpFpm()) {
self::heuristicScan($xml);
}

if (null === $dom) {
$simpleXml = true;
$dom = new DOMDocument();
}

if (!self::isPhpFpm()) {
$loadEntities = libxml_disable_entity_loader(true);
$useInternalXmlErrors = libxml_use_internal_errors(true);
}

// Load XML with network access disabled (LIBXML_NONET)
// error disabled with @ for PHP-FPM scenario
set_error_handler(array('Zend_Xml_Security', 'loadXmlErrorHandler'), E_WARNING);

$result = $dom->loadXml($xml, LIBXML_NONET);
restore_error_handler();

if (!$result) {
// Entity load to previous setting
if (!self::isPhpFpm()) {
libxml_disable_entity_loader($loadEntities);
libxml_use_internal_errors($useInternalXmlErrors);
}
return false;
}

// Scan for potential XEE attacks using ENTITY, if not PHP-FPM
if (!self::isPhpFpm()) {
foreach ($dom->childNodes as $child) {
if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
if ($child->entities->length > 0) {
#require_once 'Exception.php';
throw new Zend_Xml_Exception(self::ENTITY_DETECT);
}
}
}
}

// Entity load to previous setting
if (!self::isPhpFpm()) {
libxml_disable_entity_loader($loadEntities);
libxml_use_internal_errors($useInternalXmlErrors);
}

if (isset($simpleXml)) {
$result = simplexml_import_dom($dom);
if (!$result instanceof SimpleXMLElement) {
return false;
}
return $result;
}
return $dom;
}

/**
* Scan XML file for potential XXE/XEE attacks
*
* @param string $file
* @param DOMDocument $dom
* @throws Zend_Xml_Exception
* @return SimpleXMLElement|DomDocument
*/
public static function scanFile($file, DOMDocument $dom = null)
{
if (!file_exists($file)) {
#require_once 'Exception.php';
throw new Zend_Xml_Exception(
"The file $file specified doesn't exist"
);
}
return self::scan(file_get_contents($file), $dom);
}

/**
* Return true if PHP is running with PHP-FPM
*
* @return boolean
*/
public static function isPhpFpm()
{
if (substr(php_sapi_name(), 0, 3) === 'fpm') {
return true;
}
return false;
}
}

0 comments on commit 820fb7e

Please sign in to comment.