Skip to content

Commit c6ca992

Browse files
committed
Security improvement suggested by Nils Engelbertz to prevent DDOS by expansion of internally defined entities (XEE)
1 parent d9e316a commit c6ca992

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

lib/Saml2/Utils.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,20 @@ public static function loadXML($dom, $xml)
8484
assert('$dom instanceof DOMDocument');
8585
assert('is_string($xml)');
8686

87-
if (strpos($xml, '<!ENTITY') !== false) {
88-
throw new Exception('Detected use of ENTITY in XML, disabled to prevent XXE/XEE attacks');
89-
}
90-
9187
$oldEntityLoader = libxml_disable_entity_loader(true);
88+
9289
$res = $dom->loadXML($xml);
90+
9391
libxml_disable_entity_loader($oldEntityLoader);
9492

93+
foreach ($dom->childNodes as $child) {
94+
if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
95+
throw new Exception(
96+
'Detected use of DOCTYPE/ENTITY in XML, disabled to prevent XXE/XEE attacks'
97+
);
98+
}
99+
}
100+
95101
if (!$res) {
96102
return false;
97103
} else {

tests/src/OneLogin/Saml2/UtilsTest.php

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ public function testXMLAttacks()
7070
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>';
7171
try {
7272
$res = OneLogin_Saml2_Utils::loadXML($dom, $attackXXE);
73-
$this->fail('Exception was not raised');
73+
$this->assertFalse($res);
7474
} catch (Exception $e) {
75-
$this->assertEquals('Detected use of ENTITY in XML, disabled to prevent XXE/XEE attacks', $e->getMessage());
75+
$this->assertEquals('Detected use of DOCTYPE/ENTITY in XML, disabled to prevent XXE/XEE attacks', $e->getMessage());
7676
}
7777

7878
$xmlWithDTD = '<?xml version="1.0"?>
@@ -83,8 +83,12 @@ public function testXMLAttacks()
8383
<results>
8484
<result>test</result>
8585
</results>';
86-
$res2 = OneLogin_Saml2_Utils::loadXML($dom, $xmlWithDTD);
87-
$this->assertTrue($res2 instanceof DOMDocument);
86+
try {
87+
$res2 = OneLogin_Saml2_Utils::loadXML($dom, $xmlWithDTD);
88+
$this->assertFalse($res2);
89+
} catch (Exception $e) {
90+
$this->assertEquals('Detected use of DOCTYPE/ENTITY in XML, disabled to prevent XXE/XEE attacks', $e->getMessage());
91+
}
8892

8993
$attackXEE = '<?xml version="1.0"?>
9094
<!DOCTYPE results [<!ENTITY harmless "completely harmless">]>
@@ -93,9 +97,21 @@ public function testXMLAttacks()
9397
</results>';
9498
try {
9599
$res3 = OneLogin_Saml2_Utils::loadXML($dom, $attackXEE);
96-
$this->fail('Exception was not raised');
100+
$this->assertFalse($res3);
101+
} catch (Exception $e) {
102+
$this->assertEquals('Detected use of DOCTYPE/ENTITY in XML, disabled to prevent XXE/XEE attacks', $e->getMessage());
103+
}
104+
105+
$attackXEEutf16 = mb_convert_encoding('<?xml version="1.0" encoding="UTF-16"?>
106+
<!DOCTYPE results [<!ENTITY harmless "completely harmless">]>
107+
<results>
108+
<result>This result is &harmless;</result>
109+
</results>', 'UTF-16');
110+
try {
111+
$res4 = OneLogin_Saml2_Utils::loadXML($dom, $attackXEEutf16);
112+
$this->assertFalse($res4);
97113
} catch (Exception $e) {
98-
$this->assertEquals('Detected use of ENTITY in XML, disabled to prevent XXE/XEE attacks', $e->getMessage());
114+
$this->assertEquals('Detected use of DOCTYPE/ENTITY in XML, disabled to prevent XXE/XEE attacks', $e->getMessage());
99115
}
100116
}
101117

0 commit comments

Comments
 (0)