Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Applied patch SUPEE-3762 to address XML entity escaping vulnerability #20

Merged
merged 1 commit into from
Jun 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}