$xpath = "//user[login/text()=$login and password/text()=$password]/attribute::id"; if( file_exists($file) ) { $xml = simplexml_load_file($file); if($result = $xml->xpath($xpath)) echo "You are now logged in as user $result[0]."; else echo "Invalid login name or password."; } else exit("Failed to open $file."); ?> 

No checks are performed on the input. This means that a malevolent user can “short-circuit”  the test by entering ’ or 1=1  for both the login name and password, resulting in $xpath  being evaluated as shown here: 

//user[login/text()=’’ or 1=1 and password/text()=’’ or 1=1]/attribute::id 

Since the expression inside the square brackets always evaluates as true , it is effectively the same as this one, which matches the id  attribute of every user  element in the XML document: 

//user/attribute::id 

One way in which this particular attack can be circumvented is simply by quoting the variable names to be interpolated in the definition of $xpath , forcing the values passed from a Web form to be converted to strings: 

$xpath = "//user[login/text()=’$login’ and password/text()=’$password’]/attribute::id"; 

This is the same strategy that is often recommended for preventing SQL injection attacks. In general, the practices you should follow for preventing XPath injection attacks are the same as for preventing SQL injection: 

•Never accepted untested data from users in your application. 

•Check all user-submitted data for type; reject or convert data that is of the wrong type 

•Test numeric data for out of range values; truncate, round, or reject values that are out of range. Test strings for illegal characters and either strip them out or reject input containing them. 

•Do not output explicit error messages that might provide an unauthorized user with clues that could be used to compromise the system; log these to a file or database table instead. 

Just as SQL injection attacks can be used to obtain information about database schemas, so can XPath injection be used to traverse XML files to uncover their structure, as discussed in Amit Klein’s paper Blind XPath Injection (PDF file, 46KB). 

It is also important to check the output being sent back to the client. Consider what can happen when we use the MySQL ExtractValue()  function: 

mysql> SELECT ExtractValue( -> LOAD_FILE(’users.xml’), -> ’//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id’ -> ) AS id; +-------------------------------+ 

