XPath injection occurs when an XML document is used for data storage in a manner similar to a relational database. This attack is similar to SQL injection, (guideline IDS07-J. Prevent SQL Injection) wherein an attacker can enter valid SQL constructs into the data fields of the query in use. Typically, the conditional field of the query resolves to a tautology or gives the attacker access to privileged information. This rule is a specific example of the broadly scoped guideline IDS00-J. Always validate user input.
Consider the following XML schema.
Code Block |
---|
<users> <user> <login>Utah</login> <password>C^f3</password> </user> <user> <login>Bohdi</login> <password>C@fe</password> </user> <user> <login>Busey</login> <password>cAf3</password> </user> </users> |
Untrusted code may attempt to retrieve user details from this file with an XPath statement constructed dynamically from user input.
Code Block |
---|
str_query = "//users/user[LoginID/text()= "& login & " and password/text()="& password &"]" |
An attacker may specify input such as, login = ' or 1=1
and password = ' or 1=1
, yielding the following query string.
Code Block |
---|
//users/user[LoginID/text()='' or 1=1 and password/text()='' or 1=1] |
This may expose all the records in the XML file
Noncompliant Code Example
In this noncompliant code example, a user name and password is read from the user and used to construct the query string. The evaluate function call returns a set of all nodes in the XML file, causing the login function to return true
and bypass any authorization.
Code Block | ||
---|---|---|
| ||
class XpathInjection { private boolean doLogin(String loginID, String password) throws ParserConfigurationException, SAXException,IOException, XPathExpressionException { DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse("users.xml"); XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr = xpath.compile("//users/user[login/text()='" + loginID +"'" + "and password/text()='" + password + "' ]"); Object result = expr.evaluate(doc, XPathConstants.NODESET); NodeList nodes = (NodeList) result; // Print first names to the console for (int i = 0; i < nodes.getLength(); i++) { System.out.println(nodes.item(i).getNodeValue());} return (nodes.getLength() >= 1); } } |
Compliant Solution
XPath injection can be prevented by adopting defenses similar to SQL injection:
- Treat all user input as untrusted and perform appropriate sanitization.
- When validating user input, verify the data type, length, format and the content. For example, use a regular expression that checks for XML tags and special characters in user input. This corresponds to input validation. (See guideline IDS00-J. Always validate user input.)
- In a client-server application, perform validation at both the client and the server side.
- Extensively test applications that supply, propagate or use user input.
In similar vulnerabilities such as SQL injection, an effective prevention technique is parameterization. In this technique, user-specified data is passed directly to an API as a parameter, which ensures that no data specified by the user is interpreted as executable logic. Unfortunately, such an interface does not currently exist in Java SE. However, this functionality can be emulated by using an interface such as XQuery that enables the user to effectively parameterize data by specifying a query statement in a separate file, and supplying the query at runtime. This compliant solution uses a query specified in a text file by reading it in the required format and entering values for the user name and password in a Map
. The XML query is constructed from these elements subsequently.
Input File: login.qry
Code Block |
---|
declare variable $loginID as xs:string external; declare variable $password as xs:string external;//users/user[@loginID= $loginID and @password=$password] |
Code Block | ||
---|---|---|
| ||
Document doc = new Builder().build("users.xml"); XQuery xquery = new XQueryFactory().createXQuery(new File("login.xry")); Map queryVars= new HashMap(); queryVars.put("loginid", "Utah"); // User name hardcoded for illustrative purposes queryVars.put("password", "securecoding"); // Password hardcoded for illustrative purposes Nodes results = xquery.execute(doc, null, queryVars).toNodes(); for (int i = 0; i < results.size(); i++) { System.out.println(results.get(i).toXML()); } |
Using this method, the data specified in the loginID
and password
fields is not interpreted as executable content at runtime.
Wiki Markup |
---|
In addition, OWASP \[[OWASP 2005|AA. Java References#OWASP 05]\] recommends |
Wiki Markup \[Prevention of XPath injection\] requires the following characters to be removed (ie prohibited) or properly escaped:
< > / ' = "
to prevent straight parameter injection- XPath queries should not contain any meta characters (such as
' = * ? //
or similar)- XSLT expansions should not contain any user input, or if they do, that you comprehensively test the existence of the file, and ensure that the files are within the bounds set by the Java 2 Security Policy.
Risk Assessment
Failing to validate user input may result in information disclosure and execution of unprivileged code.
Guideline | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
IDS09-J | medium | probable | medium | P8 | L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[Fortify 2008|AA. Java References#Fortify 08]\] "Input Validation and Representation: XML Injection" \[[Sen 2007|AA. Java References#Sen 07]\] \[[Sun 2006|AA. Java References#Sun 06]\] [Ensure Data Security|http://java.sun.com/developer/technicalArticles/xml/jaxp1-3/index.html#Ensure%20Data%20Security] \[[OWASP 2005|AA. Java References#OWASP 05]\] [Testing for XPath Injection|http://www.owasp.org/index.php/XPath_Injection_Testing_AoC] \[[MITRE 2009|AA. Java References#MITRE 09]\] [CWE ID 643|http://cwe.mitre.org/data/definitions/247.html] "Failure to Sanitize Data within XPath Expressions (aka 'XPath injection')" |
IDS08-J. Prevent XML Injection 10. Input Validation and Data Sanitization (IDS) IDS10-J. Prevent XML external entity attacks