From 3e64d36cbdc34acaa82e0e6318112cd2eacb6fec Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 24 Feb 2012 13:26:13 +0100 Subject: [PATCH] [Serializer] Fix XML decoding attack vector through external entities --- .../Serializer/Encoder/XmlEncoder.php | 11 +++++++++++ .../Serializer/Encoder/XmlEncoderTest.php | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index 4ffe330d6f..54fae35917 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -54,7 +54,18 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec */ public function decode($data, $format) { + $internalErrors = libxml_use_internal_errors(true); + $disableEntities = libxml_disable_entity_loader(true); + libxml_clear_errors(); + $xml = simplexml_load_string($data); + libxml_use_internal_errors($internalErrors); + libxml_disable_entity_loader($disableEntities); + + if ($error = libxml_get_last_error()) { + throw new UnexpectedValueException($error->message); + } + if (!$xml->count()) { if (!$xml->attributes()) { return (string) $xml; diff --git a/tests/Symfony/Tests/Component/Serializer/Encoder/XmlEncoderTest.php b/tests/Symfony/Tests/Component/Serializer/Encoder/XmlEncoderTest.php index 22bff31a62..e4aef6563a 100644 --- a/tests/Symfony/Tests/Component/Serializer/Encoder/XmlEncoderTest.php +++ b/tests/Symfony/Tests/Component/Serializer/Encoder/XmlEncoderTest.php @@ -9,6 +9,7 @@ use Symfony\Tests\Component\Serializer\Fixtures\Dummy; use Symfony\Tests\Component\Serializer\Fixtures\ScalarDummy; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Serializer; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\CustomNormalizer; /* @@ -232,6 +233,23 @@ class XmlEncoderTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); } + /** + * @expectedException Symfony\Component\Serializer\Exception\UnexpectedValueException + */ + public function testPreventsComplexExternalEntities() + { + $oldCwd = getcwd(); + chdir(__DIR__); + + try { + $decoded = $this->encoder->decode(']>&test;', 'xml'); + chdir($oldCwd); + } catch (UnexpectedValueException $e) { + chdir($oldCwd); + throw $e; + } + } + protected function getXmlSource() { return ''."\n".