SecureBlockLog inStart a pentest
Vulnerability Repository
HighInjection

XPath Injection

Unsanitized user input in XPath queries manipulates XML document traversal, enabling authentication bypass and extraction of all data from the XML store.

CVSS 7.5CWE CWE-643OWASP A03:2021 — Injection

Description

XPath injection (CWE-643) occurs when user-supplied data is concatenated directly into an XPath 1.0 or 2.0 query used to traverse an XML document or XML database (such as eXist-db or BaseX). XPath is a query language for selecting nodes from an XML document — functionally similar to SQL for relational databases — and it shares SQL injection's root cause: treating user input as query syntax rather than as data.

XPath injection is less common than SQL injection but appears regularly in applications that store configuration, user data, or content in XML format, in SOAP-based web services, and in legacy enterprise applications built on XML-native databases. It also affects applications that parse RSS/Atom feeds or SAML assertions using XPath queries.

Because XPath operates on a self-contained XML document, a successful XPath injection can expose the entire document to an attacker — there are no table-level permissions to constrain access. This often means usernames, passwords (frequently stored in plaintext or weakly hashed in XML configs), API keys, and all application data can be extracted in a single exploit chain.

How It Works

A web login form backed by an XML user store might construct this query:

/users/user[name='USERNAME' and password='PASSWORD']

Built by string concatenation:

String query = "/users/user[name='" + username + "' and password='" + password + "']";

Authentication bypass payload — supply ' or '1'='1 as the username and ' or '1'='1 as the password:

/users/user[name='' or '1'='1' and password='' or '1'='1']

This always evaluates to true and returns the first user node, typically the administrator account.

Full document extraction using the string() and count() functions — XPath 1.0 supports blind boolean-based extraction using expressions like:

' or substring(//user[1]/password,1,1)='a

By iterating through character positions and comparing against the character set, an attacker reconstructs all password values — exactly like blind SQL injection, just with XPath syntax.

XPath 2.0 environments (common in Java with Saxon processor) support the doc() function, which can read external files — turning XPath injection into an arbitrary file read vulnerability.

Detection tools include manual Burp Suite manipulation. The xcat tool automates XPath 1.0 blind extraction:

xcat run --public "https://target.com/login" --username admin --payload "' or 1=1 or '1'='"

Impact

  • Authentication Bypass — Logging in as any user (including administrators) without a valid password
  • Full Data Extraction — Enumerating all nodes in the XML document, including passwords, API keys, and PII
  • Privilege Escalation — Accessing administrator credentials to take over the application
  • Blind Data Exfiltration — Inferring document content character by character using boolean responses, even with no direct output
  • Arbitrary File Read — In XPath 2.0 environments via the doc() function

Detection

  1. Inject XPath metacharacters — append ', ", ], and [ to login and search fields. Unhandled XPath syntax errors (e.g., javax.xml.xpath.XPathExpressionException) confirm the injection context.
  2. Test authentication bypass — supply ' or '1'='1 and admin' or '1'='1 as username values with any password. Successful login confirms the vulnerability.
  3. Boolean-based blind testing — craft queries like ' or 1=1 or '1'='1 (true) vs ' or 1=2 or '1'='1 (false) and compare response sizes or application behavior.
  4. Test SOAP/XML endpoints — XPath injection frequently appears in SOAP message handlers and XML-based configuration APIs, not just HTML login forms.
  5. Fuzz XPath functions — inject count(/*), string-length(/*), and name(/*) to attempt error-based extraction.
  6. Review code for XPath construction — grep for XPath.evaluate(, document.selectNodes(, xpath.find(, and look for adjacent string concatenation with unsanitized parameters.

Remediation

Use parameterized XPath queries. Several XPath libraries support variable binding which prevents injection:

// Java — javax.xml.xpath with variable resolver
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setXPathVariableResolver(variableResolver); // bind $username, $password
String expr = "/users/user[@name=$username and @password=$password]";
NodeList result = (NodeList) xpath.evaluate(expr, doc, XPathConstants.NODESET);

Escape user input before embedding in XPath. If parameterized queries are not available, escape single quotes by doubling them (''') and validate that the input matches the expected character set using an allowlist regex.

Migrate sensitive data out of XML files. User credentials should be stored in a database with proper hashing (bcrypt, Argon2), not in XML configuration files.

Validate input type and format. Usernames typically follow a restricted character set. Reject any input containing ', ", [, ], *, /, =, or whitespace before it reaches any XPath context.

Apply least-privilege access. The application user should not have access to the entire XML document. Restructure the data model so sensitive nodes require additional authorization checks at the application layer.

Ready when you are
Scope a pentest in the next two minutes.
Start scoping