Skip to content

XPath Injection

XPath Injection

Description

XPath injection is a type of attack that can change the intent of an XPath query that is executed on an application’s backend. An application might be vulnerable to this attack if special characters are injected into a user-supplied input value, that input is not filtered and is concatenated with other strings to construct an XPath query, which is executed against an XML document.

Impacts of this attack can include bypassing authentication logic, or the disclosure of sensitive data within the XML document being queried.

Examples

Java

 String xmlInput = "<users>" +
            "<user><username>admin</username><password>admin@123</password></user>" +
            "<user><username>guest</username><password>guest@123</password></user>" +
            "</users>";

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xmlInput)));

//Input example : 
String inputUsername = "admin' or '1'='1' or '";
String inputPassword = "randomPassword";

XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();

String query = String.format("//user[username/text()='%s' and password/text()='%s']", inputUsername, inputPassword);
XPathExpression expr = xpath.compile(query);

Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;

System.out.println(nodes.getLength() > 0 ? "Authenticated" : "Authentication Failed");

Javascript

const express = require('express');
const libxml = require('libxmljs');

const app = express();
const xmlInput = `<users>
  <user><username>admin</username><password>admin@123</password></user>
  <user><username>guest</username><password>guest@123</password></user>
</users>`;

app.post('/authenticate', (req, res) => {
  const { username, password } = req.body;

  const xmlDoc = libxml.parseXml(xmlInput);
  const query = `//user[username/text()='${username}' and password/text()='${password}']`;
  const nodes = xmlDoc.find(query);

  res.send(nodes.length > 0 ? 'Authenticated' : 'Authentication Failed');
});

Php

<?php
$xmlInput = "<users>" .
    "<user><username>admin</username><password>admin@123</password></user>" .
    "<user><username>guest</username><password>guest@123</password></user>" .
    "</users>";

//Input example : 
$inputUsername = "admin' or '1'='1' or '";
$inputPassword = "randomPassword";

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

$xpath = new DOMXPath($doc);

$query = "//user[username/text()='$inputUsername' and password/text()='$inputPassword']";
$nodes = $xpath->query($query);

echo ($nodes->length > 0) ? "Authenticated" : "Authentication Failed";
?>

Recommendation

To mitigate XPath Injection vulnerabilities, it is important to:

  • Use parameterized queries or prepared statements, which separate the user input from the query logic.
  • Properly validate and sanitize user input before using it in XPath queries.
import org.dom4j.Document;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import org.jaxen.SimpleVariableContext;

import java.io.File;

public class Main {
    public static void main(String[] args) {
        try {
            // Assuming 'user' and 'pass' variables are already defined
            String user = "username";
            String pass = "password";

            // Load your XML document
            File inputFile = new File("input.xml");
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputFile);

            // Create a SimpleVariableContext and set variables
            SimpleVariableContext svc = new SimpleVariableContext();
            svc.setVariableValue("user", user);
            svc.setVariableValue("pass", pass);

            // Define your XPath expression
            String xpathString = "/users/user[@name=$user and @pass=$pass]";

            // Create XPath object and set the variable context
            XPath safeXPath = document.createXPath(xpathString);
            safeXPath.setVariableContext(svc);

            // Evaluate XPath expression and check if any node is selected
            boolean isExist = safeXPath.selectSingleNode(document) != null;
            System.out.println(isExist);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Standards

  • GDPR:
    • ART_32
  • PCI_STANDARDS:
    • REQ_6_4
    • REQ_6_5
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_3_4
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5