Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: tested NCCE, works

...

Code Block
//users/user[LoginID/text()='&LOGIN&' and password/text()='&PASSWORD&' ]

An attacker may specify input If an attacker knows that Utah is a valid login ID, they can specify an input login ID such as:

Code Block
Utah' or 1''=1'

for both the login and password fields. This would yield the following query string:

Code Block
//users/user[LoginIDlogin/text()='Utah' or 1''=1'' and password/text()='' or 1=1xxxx' ]

This may expose all the records in the XML fileThe ''='' is automatically true, and causes the password to never be validated. Consequently the attacker is falsely logged in as user Utah.

Noncompliant Code Example

...

If passed the attack string for login described above, the evaluate() method call returns a set of all nodes in the XML file, causing the login() method to return true and bypass any authorization.

Code Block
bgColor#FFcccc
class XpathInjection {
  private boolean doLogin(String loginID, 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[login/text()='" + 
         loginID + "' 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 = System.out.println(nodesnodes.item(i).getChildNodes().item(i1).getNodeValuegetChildNodes().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:

...

This compliant solution uses a query specified in a text file by reading the file in the required format and then entering values for the user name and password in a Map. The XQuery library constructs the XML query from these elements.

Code Block
bgColor#ccccff

Document doc = new Builder().build
private boolean doLogin(String loginID, String pwd)
  throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {

  DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
  domFactory.setNamespaceAware(true);
  DocumentBuilder builder = domFactory.newDocumentBuilder();
  Document doc = builder.parse("users.xml");

  XQuery xquery = new XQueryFactory().createXQuery(new File("login.xry"));

  Map queryVars = new HashMap();

  queryVars.put("loginid", loginID);  
       // eg "Utah"
queryVars.put("password", pwd);
            // eg "C^f3"

Nodes results NodeList nodes = xquery.execute(doc, null, queryVars).toNodes();

  // Print first names to the console 
  for (int i = 0; i < resultsnodes.sizegetLength(); i++) {
    Node node = nodes.item(i).getChildNodes().item(1).getChildNodes().item(0);
    System.out.println(results node.getgetNodeValue(i).toXML()));
  }

  return (nodes.getLength() >= 1);
}

Using this method, the data specified in the loginID and password fields cannot be interpreted as executable content at runtime.

...