XPath injection: manipulating queries on XML data
XPath is a query language for navigating XML documents. An XPath injection occurs when an application builds an XPath expression by directly concatenating user input, in the same way an SQL injection occurs in database queries. The attacker can modify the query's logic by injecting XPath operators and functions.
Example: authentication bypass
Vulnerable XPath authentication
<!-- Fichier XML des utilisateurs -->
<users>
<user>
<username>admin</username>
<password>secret</password>
<role>admin</role>
</user>
</users>
// Requête XPath construite par concaténation :
const query = `//user[username='${username}' and password='${password}']`;
// Payload : username = "admin' or '1'='1" / password = "x"
// Requête résultante :
//user[username='admin' or '1'='1' and password='x']
// Équivalent à : //user[username='admin']
// Retourne le nœud admin sans vérifier le mot de passe
Data extraction via blind XPath
When the response doesn't directly include the XML data, the attacker can extract data character by character. Using XPath functions like string-length(), substring(), and contains(), the attacker builds boolean queries whose result (true/false, visible in the application's behaviour) lets them infer the XML document's content.
Prevention
The main fix is to use parameterised XPath queries (with variables). All modern XPath implementations support variables, which separate the query structure from the data, like prepared statements in SQL.
Parameterised XPath (Java)
// Vulnérable
String query = "//user[username='" + username + "' and password='" + password + "']";
// Correct : utilisation de variables XPath
XPath xpath = XPathFactory.newInstance().newXPath();
SimpleVariableResolver resolver = new SimpleVariableResolver();
resolver.addVariable(new QName("username"), username);
resolver.addVariable(new QName("password"), password);
xpath.setXPathVariableResolver(resolver);
String safeQuery = "//user[username=$username and password=$password]";
NodeList result = (NodeList) xpath.evaluate(safeQuery, doc, XPathConstants.NODESET);
If XML data isn't necessary (data could be in a relational database), consider migrating to SQL with prepared statements, which benefit from broader support and documentation for injection prevention.
Further reading
A question after reading?
Does your application query XML data with XPath? Send a message.
Or book a 30-minute scoping call directly
Book a call →