Extensible Markup Language (XML) can be used for data storage in a manner similar to a relational database. Data is frequently retrieved from such an XML document using XPaths. XPath injection can occur when data supplied to an XPath retrieval routine to retrieve data from an XML document is used without proper sanitization. This attack is similar to SQL injection or XML injection (see the appropriate parts of IDS00-J. Sanitize untrusted data passed across a trust boundary) whereby an . An attacker can enter valid SQL or XML constructs in the data fields of the query in use. In typical attacks, the conditional field of the query resolves to a tautology or otherwise gives the attacker access to privileged information.
...
The passwords are hashed in compliance with 13. Store passwords using a hash function. MD5 hashes are shown here for illustrative purposes; in practice, you should use a safer algorithm such as SHA-256.
Untrusted code may attempt to retrieve user details from this file with an XPath statement constructed dynamically from user input:.
Code Block |
---|
//users/user[username/text()='&LOGIN&' and password/text()='&PASSWORD&' ] |
If an attacker knows that Utah
is a valid user name, he or she can specify an input such as the following:
Code Block |
---|
Utah' or '1'='1 |
This yields the following query string:.
Code Block |
---|
//users/user[username/text()='Utah' or '1'='1' and password/text()='xxxx'] |
Because the '1'='1'
is automatically true, the password is never validated. Consequently, the attacker is inappropriately authenticated as user Utah
without knowledge of user knowing Utah
's password.
Noncompliant Code Example
...
Code Block | ||
---|---|---|
| ||
private boolean doLogin(String userName, char[] password) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException { DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse("users.xml"); String pwd = hashPassword( password); XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr = xpath.compile("//users/user[username/text()='" + userName + "' and password/text()='" + pwd + "' ]"); 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++) { Node node = nodes.item(i).getChildNodes().item(1).getChildNodes().item(0); System.out.println( "Authenticated: " + node.getNodeValue()); } return (nodes.getLength() >= 1); } |
Compliant Solution (XQuery)
XPath injection can be prevented by adopting defenses similar to those used to prevent SQL injection:
...
An effective technique for preventing the related issue of SQL injection is parameterization. Parameterization ensures that user-specified data is passed to an API as a parameter such that the data is never interpreted as executable content. Unfortunately, Java SE currently lacks an analogous interface for XPath queries. However, an XPath analog to SQL parameterization can be emulated by using an interface such as XQuery that supports specifying a query statement in a separate file supplied at runtime.
...