[Serializer] Fix XML decoding attack vector through external entities

This commit is contained in:
Jordi Boggiano 2012-02-24 13:26:13 +01:00 committed by Fabien Potencier
parent 3223f51bb1
commit 3e64d36cbd
2 changed files with 29 additions and 0 deletions

View File

@ -54,7 +54,18 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec
*/ */
public function decode($data, $format) 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); $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->count()) {
if (!$xml->attributes()) { if (!$xml->attributes()) {
return (string) $xml; return (string) $xml;

View File

@ -9,6 +9,7 @@ use Symfony\Tests\Component\Serializer\Fixtures\Dummy;
use Symfony\Tests\Component\Serializer\Fixtures\ScalarDummy; use Symfony\Tests\Component\Serializer\Fixtures\ScalarDummy;
use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Normalizer\CustomNormalizer; use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
/* /*
@ -232,6 +233,23 @@ class XmlEncoderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expected, $this->encoder->decode($source, 'xml')); $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('<?xml version="1.0"?><!DOCTYPE scan[<!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=XmlEncoderTest.php">]><scan>&test;</scan>', 'xml');
chdir($oldCwd);
} catch (UnexpectedValueException $e) {
chdir($oldCwd);
throw $e;
}
}
protected function getXmlSource() protected function getXmlSource()
{ {
return '<?xml version="1.0"?>'."\n". return '<?xml version="1.0"?>'."\n".