...
Untrusted code may attempt to retrieve user details from this file with an XPath statement constructed dynamically from user input.
Code Block |
---|
//users/user[LoginIDlogin/text()='&LOGIN&' and password/text()='&PASSWORD&' ] |
...
This would yield the following query string:
Code Block |
---|
//users/user[passwordlogin/text()='xxxx' and loginpassword/text()='' or '1'='1' ] |
This time, the '1'='1'
tautology disables both login ID and password validation, and the attacker is inappropriately logged in without knowledge of either a login ID or a password.
...
An effective technique for preventing the related issue of SQL injection is parameterization, whereby . Parameterization ensures that user-specified data is passed to an API as a parameter , thus ensuring that user-specified such that the data is never interpreted as executable logiccontent. Unfortunately, Java SE currently lacks an analogous interface for XPath queries. SQL parameterization can be emulated by using an interface ( such as XQuery
) that supports specifying a query statement in a separate file that is supplied at runtime.
Input File: login.qry
...
This compliant solution uses a query specified in a text file by reading the file in the required format and then entering inserting values for the user name and password in a Map
. The XQuery
library constructs the XML query from these elementsinputs.
Code Block | ||
---|---|---|
| ||
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); queryVars.put("password", pwd); NodeList nodes = xquery.execute(doc, null, queryVars).toNodes(); // 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( node.getNodeValue()); } return (nodes.getLength() >= 1); } |
...