Переглянути джерело

prevents injection of malicious doc types

Johannes M. Schmitt 12 роки тому
батько
коміт
a2a6cdca8d

+ 12 - 0
src/Symfony/Component/Serializer/Encoder/XmlEncoder.php

@@ -54,6 +54,7 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec
      */
     public function decode($data, $format)
     {
+        $this->assertNoCustomDocType($data);
         $internalErrors = libxml_use_internal_errors(true);
         $disableEntities = libxml_disable_entity_loader(true);
         libxml_clear_errors();
@@ -290,6 +291,17 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec
         throw new UnexpectedValueException('An unexpected value could not be serialized: '.var_export($data, true));
     }
 
+    private function assertNoCustomDocType($data)
+    {
+        $dom = new \DOMDocument;
+        $dom->loadXML($data);
+        foreach ($dom->childNodes as $child) {
+            if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
+                throw new \InvalidArgumentException('Document types are not allowed.');
+            }
+        }
+    }
+
     /**
      * Selects the type of node to create and appends it to the parent.
      *

+ 17 - 6
tests/Symfony/Tests/Component/Serializer/Encoder/XmlEncoderTest.php

@@ -53,6 +53,15 @@ class XmlEncoderTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
     }
 
+    /**
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Document types are not allowed.
+     */
+    public function testDocTypeIsNotAllowed()
+    {
+        $this->encoder->decode('<?xml version="1.0"?><!DOCTYPE foo><foo></foo>', 'foo');
+    }
+
     public function testAttributes()
     {
         $obj = new ScalarDummy;
@@ -233,20 +242,22 @@ 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('<?xml version="1.0"?><!DOCTYPE scan[<!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=XmlEncoderTest.php">]><scan>&test;</scan>', 'xml');
+            $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) {
+
+            $this->fail('No exception was thrown.');
+        } catch (\Exception $e) {
             chdir($oldCwd);
-            throw $e;
+
+            if (!$e instanceof \InvalidArgumentException) {
+                $this->fail('Expected InvalidArgumentException');
+            }
         }
     }