Skip to content

Commit 5fd4ce4

Browse files
authored
Merge commit from fork
* Explicitly disable loading of external entities * Remove problematic options * Move test for dangerous XML before where the document is loaded * Defense in depth: test for DOCTYPE in two different ways * Add unit test * Use defined() for LIB_NO_XXE
1 parent f32fdf3 commit 5fd4ce4

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

src/SAML2/DOMDocumentFactory.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,27 @@ public static function fromString(string $xml) : DOMDocument
3030
{
3131
if (trim($xml) === '') {
3232
throw InvalidArgumentException::invalidType('non-empty string', $xml);
33+
} elseif (preg_match('/<(\s*)!(\s*)DOCTYPE/', $xml)) {
34+
throw new RuntimeException(
35+
'Dangerous XML detected, DOCTYPE nodes are not allowed in the XML body'
36+
);
3337
} elseif (PHP_VERSION_ID < 80000) {
3438
$entityLoader = libxml_disable_entity_loader(true);
39+
} else {
40+
libxml_set_external_entity_loader(null);
3541
}
3642

3743
$internalErrors = libxml_use_internal_errors(true);
3844
libxml_clear_errors();
3945

4046
$domDocument = self::create();
41-
$options = LIBXML_DTDLOAD | LIBXML_DTDATTR | LIBXML_NONET | LIBXML_PARSEHUGE;
47+
$options = LIBXML_NONET | LIBXML_PARSEHUGE;
48+
49+
/* LIBXML_NO_XXE available from PHP 8.4 */
50+
if (defined('LIBXML_NO_XXE')) {
51+
$options |= LIBXML_NO_XXE;
52+
}
53+
4254
if (defined('LIBXML_COMPACT')) {
4355
$options |= LIBXML_COMPACT;
4456
}

tests/SAML2/DOMDocumentFactoryTest.php

+16
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,22 @@ public function testStringThatContainsDocTypeIsNotAccepted() : void
9999
}
100100

101101

102+
/**
103+
* @group domdocument
104+
* @return void
105+
*/
106+
public function testStringThatContainsDocTypeIsNotAccepted2(): void
107+
{
108+
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>
109+
<!DOCTYPE foo [<!ENTITY % exfiltrate SYSTEM "file://dev/random">%exfiltrate;]>
110+
<foo>y</foo>';
111+
$this->expectException(RuntimeException::class);
112+
$this->expectExceptionMessage(
113+
'Dangerous XML detected, DOCTYPE nodes are not allowed in the XML body',
114+
);
115+
DOMDocumentFactory::fromString($xml);
116+
}
117+
102118
/**
103119
* @group domdocument
104120
* @return void

0 commit comments

Comments
 (0)