I'm trying to implement a simple demo - to better understand XXE and SSRF techniques. I have written these two files below in an attempt to set this up.
I currently intercept the AJAX POST request and modify the data (params) by appending:
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<foo>&xxe;</foo>
*I have also tried another local file instead of /etc/passwd
; as I wasn't sure if it due to the www-data
can access the given file
I've read that PHP v8+ has patched the built-in parsers to not allow external entities by default. Hence i tried adding the following; though I believe its deprecated - libxml_disable_entity_loader(false);
Despite this, it seems like my XXE attempt is not working, and I'm not entirely sure why?
xxe.php -
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="postData()">Post data</button>
<br>
<br>
<script>
function postData(){
var xHTTP = new XMLHttpRequest();
var params = "<?xml version='1.0'?><entry><row>1</row><ex>a</ex><row>2</row><ex>b</ex></entry>";
xHTTP.onreadystatechange = function(){
if(this.readyState == 4){
console.log(xHTTP.responseText);
}
};
xHTTP.open("POST", '/xxe_post_handler.php', true);
xHTTP.setRequestHeader("Content-Type", "application/xml");
xHTTP.send(params);
}
</script>
</body>
</html>
xxe_post_handler.php -
<?php
libxml_disable_entity_loader(false);
if($_SERVER["REQUEST_METHOD"]=="POST"){
$postData = trim(file_get_contents('php://input'));
$xml = simplexml_load_string($postData);
foreach($xml->children() as $child){
printf("XML child: %s\n", $child);
}
$xmlDOM = new DOMDocument();
$xmlDOM->loadXML($postData);
$xD = $xmlDOM->documentElement;
foreach($xD->childNodes AS $xN){
print $xN->nodeName . " = " . $xN->nodeValue . "<br>";
}
}
?>