﻿# V5312\. OWASP\. Possible XPath injection\. Potentially tainted data is used in the XPath expression\.

The analyzer has detected that unverified external data is used to create an XPath expression\. This can result in an XPath injection\.

Injection\-related vulnerabilities belong to the OWASP Top 10 Application Security Risks: [A3:2021\-Injection](https://owasp.org/Top10/A03_2021-Injection/)\.

Look at the following example:

```cpp
public class UserData {
    HttpServletRequest request;
    MessageDigest digest;
    Document doc;

    public void retrieveUserData() {
        String user = request.getParameter("username");
        String password = request.getParameter("password");
        String passwordHash = Arrays.toString(
                digest.digest(password.getBytes(StandardCharsets.UTF_8))
        );
        var xpath = XPathFactory.newInstance().newXPath();

        String query = "//users/user[" +
                "username/text() = '%s' and" +
                "passwordHash/text() = '%s']" +
                "/data/text()";
        query = String.format(query, user, passwordHash);

        try {
            String result = xpath.evaluate(query, doc);
            // ....
        } catch (XPathExpressionException e) {
            // ....
        }
        //....
    }
}
```

In the example, an XPath expression is used to get user data from an XML file\. The username is stored "as is" and the password is encrypted\.

An attacker can pass any data as a username and password\. The check is compromised if an expression that makes the XPath condition always true is passed in the input data\. Since the password is stored in encrypted form, the unsafe expression should be injected along with the username\. 

Let's say the username is `john` and add the following expression to it:

```cpp
' or ''='
```

You can enter any characters instead of a password\. Then, the XPath expression will look like this:

```cpp
[
  username/text()='john' or ''='' and
  passwordHash/text() = '750084105bcbe9d2c89ba9b'
]
```

Now the expression contains the `or` operator\. Let's look at how it is evaluated:

1. Since the username exists, the `username/text()='john'` expression is true\.
1. Random characters were entered as the password, so the `passwordHash/text() = '750084105bcbe9d2c89ba9b'` expression is false\.
1. The ''\='' expression is always true\.
1. The `and` operator has a higher priority than `or`, so the `''='' and passwordHash/text() = '750084105bcbe9d2c89ba9b'` expression is evaluated\. The result is false\.
1. The `or` operator executes last\. The `username/text()='john' or false` expression is true\. So, the entire condition is true\.

Thus, the result of the XPath query is the `john` user data, regardless of whether the password is correct or not\. This can lead to a data breach\.

Do not use unverified external data in XPath expressions\. To improve security, it is better to escape potentially dangerous characters in external data\. The `<`, `>`, and `'` are examples of such symbols\. Escaping can be done via simple `replaceAll`:

```cpp
public class UserData {
    HttpServletRequest request;
    MessageDigest digest;
    Document doc;

    public void retrieveUserData() {
        String user = request.getParameter("username")
                .replaceAll("'", "&abos;");
        String password = request.getParameter("password");
        String passwordHash = Arrays.toString(
                digest.digest(password.getBytes(StandardCharsets.UTF_8))
        );
        var xpath = XPathFactory.newInstance().newXPath();

        String query = "//users/user[" +
                "username/text() = '%s' and" +
                "passwordHash/text() = '%s']" +
                "/data/text()";
        query = String.format(query, user, passwordHash);

        try {
            String result = xpath.evaluate(query, doc);
            // ....
        } catch (XPathExpressionException e) {
            // ....
        }
        //....
    }
}
```

Apache Commons Text also contains the `StringEscapeUtils` [utility class](https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/StringEscapeUtils.html), two methods of which are `escapeXml10` and `escapeXml11`\. All necessary characters can be escaped using these methods\.

There are other ways to prevent XPath injections\. For example, Oracle [suggests](https://docs.oracle.com/en/java/javase/21/docs/api/java.xml/javax/xml/xpath/XPathVariableResolver.html) implementing a resolver class\. You can use it in XPath class objects\. In the XPath expression, you can set user\-defined variables and functions to be processed by the resolver\.