diff --git a/data/patches/OPSA-2013-003.diff b/data/patches/OPSA-2013-003.diff new file mode 100644 index 0000000..8352544 --- /dev/null +++ b/data/patches/OPSA-2013-003.diff @@ -0,0 +1,20 @@ +diff --git a/lib/vendor/php-openid/Auth/Yadis/XML.php b/lib/vendor/php-openid/Auth/Yadis/XML.php +index 2704c78..f5e80a5 100644 +--- a/lib/vendor/php-openid/Auth/Yadis/XML.php ++++ b/lib/vendor/php-openid/Auth/Yadis/XML.php +@@ -234,7 +234,14 @@ function setXML($xml_string) + return false; + } + +- if (!@$this->doc->loadXML($xml_string)) { ++ // disable external entities and libxml errors ++ $loader = libxml_disable_entity_loader(true); ++ $errors = libxml_use_internal_errors(true); ++ $parse_result = @$this->doc->loadXML($xml_string); ++ libxml_disable_entity_loader($loader); ++ libxml_use_internal_errors($errors); ++ ++ if (!$parse_result) { + return false; + } + diff --git a/data/version.php b/data/version.php index bc478cf..ea8237a 100644 --- a/data/version.php +++ b/data/version.php @@ -10,5 +10,5 @@ if (!defined('OPENPNE_VERSION')) { - define('OPENPNE_VERSION', '3.8.7'); + define('OPENPNE_VERSION', '3.8.7.1'); } diff --git a/doc/en/OpenPNE3_Setup_Guide.txt b/doc/en/OpenPNE3_Setup_Guide.txt index 76f1c7e..b9a6e10 100644 --- a/doc/en/OpenPNE3_Setup_Guide.txt +++ b/doc/en/OpenPNE3_Setup_Guide.txt @@ -13,7 +13,7 @@ Web Server Apache * The "mod_rewrite" module is available PHP - PHP version 5.2.3 or later + PHP version 5.2.11 or later (if you want to use with earlier than PHP 5.2.11, you should build PHP with libxml 2.9+) * The "mbstring" module is available * The "xml" module is available * The "PCRE" module is available (That must be support UTF-8) diff --git a/doc/ja/OpenPNE3_Setup_Guide.txt b/doc/ja/OpenPNE3_Setup_Guide.txt index 7ef58b3..36caaf0 100644 --- a/doc/ja/OpenPNE3_Setup_Guide.txt +++ b/doc/ja/OpenPNE3_Setup_Guide.txt @@ -13,7 +13,7 @@ Webサーバ Apache * mod_rewrite を使用可能 PHP - PHP5.2.3 以降 + PHP 5.2.11 以降 (PHP 5.2.11 未満で動作させる場合は libxml 2.9 以降と一緒に PHP をビルドしてください) * PHP の mbstring 拡張モジュールを使用可能 * PHP の XML 拡張モジュールを使用可能 * PHP の PCRE 拡張モジュールを使用可能 (UTF-8 サポート) diff --git a/lib/plugin/opPearRest.class.php b/lib/plugin/opPearRest.class.php index 38aa2df..514e00e 100644 --- a/lib/plugin/opPearRest.class.php +++ b/lib/plugin/opPearRest.class.php @@ -27,7 +27,10 @@ public function retrieveData($url, $accept = false, $forcestring = false, $chann public function retrieveXml($url) { $content = $this->downloadHttp($url); - $result = @simplexml_load_string($content); + $result = @opToolkit::loadXmlString($content, array( + 'return' => 'SimpleXMLElement', + )); + return $result; } diff --git a/lib/plugin/opPlugin.class.php b/lib/plugin/opPlugin.class.php index 242e3f9..cc3acdb 100644 --- a/lib/plugin/opPlugin.class.php +++ b/lib/plugin/opPlugin.class.php @@ -125,7 +125,11 @@ protected function getPackageInfo() { return false; } - return simplexml_load_file($xmlPath); + $content = file_get_contents($xmlPath); + + return opToolkit::loadXmlString($content, array( + 'return' => 'SimpleXMLElement', + )); } public function setIsActive($isActive) diff --git a/lib/task/opPluginArchiveTask.class.php b/lib/task/opPluginArchiveTask.class.php index 484d5d8..84edaab 100644 --- a/lib/task/opPluginArchiveTask.class.php +++ b/lib/task/opPluginArchiveTask.class.php @@ -47,7 +47,11 @@ protected function execute($arguments = array(), $options = array()) throw new sfException(sprintf('Plugin "%s" dosen\'t have a definition file.', $pluginName)); } - $infoXml = simplexml_load_file($packagePath.'/package.xml'); + $content = file_get_contents($packagePath.'/package.xml'); + $infoXml = opToolkit::loadXmlString($content, array( + 'return' => 'SimpleXMLElement', + )); + $filename = sprintf('%s-%s.tgz', (string)$infoXml->name, (string)$infoXml->version->release); $dirPath = sfConfig::get('sf_plugins_dir').'/'.$pluginName; diff --git a/lib/util/opToolkit.class.php b/lib/util/opToolkit.class.php index 61fb771..41c733f 100644 --- a/lib/util/opToolkit.class.php +++ b/lib/util/opToolkit.class.php @@ -582,4 +582,48 @@ static public function writeCacheFile($pathToCacheFile, $content) $filesystem->chmod($pathToCacheFile, 0666); umask($currentUmask); } + + /** + * Parse the input data and create either a SimpleXmlElement object or a DOMDocument (from CakePHP 2.3.9) + * + * This method is based Xml::_loadXmlString() in CakePHP 2.3.9 with many our arranged + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @license http://www.opensource.org/licenses/mit-license.php MIT License + * + * @param string $input The input to load. + * @param array $options The options to use. + * @return SimpleXmlElement|DOMDocument + */ + public static function loadXmlString($input, $options = array()) + { + $hasDisable = function_exists('libxml_disable_entity_loader'); + $internalErrors = libxml_use_internal_errors(true); + $isDisableEntityLoader = ($hasDisable && empty($options['loadEntities'])); + if ($isDisableEntityLoader) + { + $entityLoaderConfig = libxml_disable_entity_loader(true); + } + + $returnClass = isset($options['return']) ? strtolower($options['return']) : ''; + + if ('simplexml' === $returnClass || 'simplexmlelement' === $returnClass) + { + $xml = simplexml_load_string($input); + } + else + { + $xml = new DOMDocument(); + $xml->loadXML($input); + } + + if ($isDisableEntityLoader) + { + libxml_disable_entity_loader($entityLoaderConfig); + } + libxml_use_internal_errors($internalErrors); + + return $xml; + } } diff --git a/lib/vendor/php-openid/Auth/Yadis/XML.php b/lib/vendor/php-openid/Auth/Yadis/XML.php index 2704c78..f5e80a5 100644 --- a/lib/vendor/php-openid/Auth/Yadis/XML.php +++ b/lib/vendor/php-openid/Auth/Yadis/XML.php @@ -234,7 +234,14 @@ function setXML($xml_string) return false; } - if (!@$this->doc->loadXML($xml_string)) { + // disable external entities and libxml errors + $loader = libxml_disable_entity_loader(true); + $errors = libxml_use_internal_errors(true); + $parse_result = @$this->doc->loadXML($xml_string); + libxml_disable_entity_loader($loader); + libxml_use_internal_errors($errors); + + if (!$parse_result) { return false; } diff --git a/test/unit/util/opToolkitLoadXmlStringTest.php b/test/unit/util/opToolkitLoadXmlStringTest.php new file mode 100644 index 0000000..8d15160 --- /dev/null +++ b/test/unit/util/opToolkitLoadXmlStringTest.php @@ -0,0 +1,25 @@ +diag('opToolkit::loadXmlString()'); + +$path_to_feed = realpath(dirname(__FILE__).'/../../fixtures/feeds/www.xss.feed.rss'); +$xml = 'ok'; +$xml_with_xxe = ']>ok&xxe;'; + +$t->comment('with no external entities'); + +$t->isa_ok(opToolkit::loadXmlString($xml), 'DOMDocument', 'returns an instance of "DOMDocument"'); +$t->isa_ok(opToolkit::loadXmlString($xml, array('return' => 'SimpleXMLElement')), 'SimpleXMLElement', 'returns an instanceof "SimpleXMLElement"'); + +$t->comment('with external entities'); + +$t->isa_ok(opToolkit::loadXmlString($xml_with_xxe), 'DOMDocument', 'returns an instance of "DOMDocument"'); +$t->isa_ok(opToolkit::loadXmlString($xml_with_xxe, array('return' => 'SimpleXMLElement')), 'SimpleXMLElement', 'returns an instanceof "SimpleXMLElement"'); +$t->is(opToolkit::loadXmlString($xml_with_xxe)->textContent, 'ok', 'generated XML string by "DOMDocument" does not have entitied value'); +$t->is((string)opToolkit::loadXmlString($xml_with_xxe, array('return' => 'SimpleXMLElement')), 'ok', 'generated XML string by "SimpleXMLElement" does not have entitied value'); +$t->isnt(opToolkit::loadXmlString($xml_with_xxe, array('loadEntities' => true))->textContent, 'ok', 'generated XML string by "DOMDocument" has entitied value if "loadEntities" option is specified'); +$t->isnt((string)opToolkit::loadXmlString($xml_with_xxe, array('return' => 'SimpleXMLElement', 'loadEntities' => true)), 'ok', 'generated XML string by "SimpleXMLElement" has entitied value if "loadEntities" option is specified');