XPath Injection attacks occur when a web site uses user-supplied information to construct an XPath query for XML data. By sending intentionally malformed information into the web site, an attacker can find out how the XML data is structured, or access data that he may not normally have access to. He may even be able to elevate his privileges on the web site if the XML data is being used for authentication (such as an XML based user file).
Example Vulnerability
We'll use this XML snippet for the examples. <?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee ID="1">
<FirstName>Arnold</FirstName>
<LastName>Baker</LastName>
<UserName>ABaker</UserName>
<Password>SoSecret</Password>
<Type>Admin</Type>
</Employee>
<Employee ID="2">
<FirstName>Peter</FirstName>
<LastName>Pan</LastName>
<UserName>PPan</UserName>
<Password>NotTelling</Password>
<Type>User</Type>
</Employee>
</Employees>
Suppose we have a user authentication system on a web page that used a data file of this sort to login users. Once a username and password have been supplied the software might use XPath to look up the user:
VB:
Dim FindUserXPath as String
FindUserXPath = "//Employee[UserName/text()='" & Request("Username") & "' And
Password/text()='" & Request("Password") & "']"
C#:
String FindUserXPath;
FindUserXPath = "//Employee[UserName/text()='" + Request("Username") + "' And
Password/text()='" + Request("Password") + "']";
With a normal username and password this XPath would work, but an attacker may send a bad username and password and get an XML node selected without knowing the username or password, like this: Username: blah' or 1=1 or 'a'='a
Password: blah
FindUserXPath becomes //Employee[UserName/text()='blah' or 1=1 or
'a'='a' And Password/text()='blah']
Logically this is equivalent to:
//Employee[(UserName/text()='blah' or 1=1) or
('a'='a' And Password/text()='blah')]
In this case, only the first part of the XPath needs to be true. The password part becomes irrelevant, and the UserName part will match ALL employees because of the "1=1" part.
Prevention of XPath Injection
Just like the techniques to avoid SQL injection, you need to use a parameterized XPath interface if one is available, or escape the user input to make it safe to include in a dynamically constructed query. If you are using quotes to terminate untrusted input in a dynamically constructed XPath query, then you need to escape that quote in the untrusted input to ensure the untrusted data can't try to break out of that quoted context. In the following example, single quotes (') are used to terminate the Username and Password parameters. So, we need to replace any ' characters in this input with the XML encoded version of that character, which is "'".
Another better mitigation option is to use a precompiled XPath query. Precompiled XPath queries are already preset before the program executes, rather than created on the fly after the user's input has been added to the string. This is a better route because you don't have to worry about missing a character that should have been escaped.
Example Vulnerability
We'll use this XML snippet for the examples. <?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee ID="1">
<FirstName>Arnold</FirstName>
<LastName>Baker</LastName>
<UserName>ABaker</UserName>
<Password>SoSecret</Password>
<Type>Admin</Type>
</Employee>
<Employee ID="2">
<FirstName>Peter</FirstName>
<LastName>Pan</LastName>
<UserName>PPan</UserName>
<Password>NotTelling</Password>
<Type>User</Type>
</Employee>
</Employees>
Suppose we have a user authentication system on a web page that used a data file of this sort to login users. Once a username and password have been supplied the software might use XPath to look up the user:
VB:
Dim FindUserXPath as String
FindUserXPath = "//Employee[UserName/text()='" & Request("Username") & "' And
Password/text()='" & Request("Password") & "']"
C#:
String FindUserXPath;
FindUserXPath = "//Employee[UserName/text()='" + Request("Username") + "' And
Password/text()='" + Request("Password") + "']";
With a normal username and password this XPath would work, but an attacker may send a bad username and password and get an XML node selected without knowing the username or password, like this: Username: blah' or 1=1 or 'a'='a
Password: blah
FindUserXPath becomes //Employee[UserName/text()='blah' or 1=1 or
'a'='a' And Password/text()='blah']
Logically this is equivalent to:
//Employee[(UserName/text()='blah' or 1=1) or
('a'='a' And Password/text()='blah')]
In this case, only the first part of the XPath needs to be true. The password part becomes irrelevant, and the UserName part will match ALL employees because of the "1=1" part.
Prevention of XPath Injection
Just like the techniques to avoid SQL injection, you need to use a parameterized XPath interface if one is available, or escape the user input to make it safe to include in a dynamically constructed query. If you are using quotes to terminate untrusted input in a dynamically constructed XPath query, then you need to escape that quote in the untrusted input to ensure the untrusted data can't try to break out of that quoted context. In the following example, single quotes (') are used to terminate the Username and Password parameters. So, we need to replace any ' characters in this input with the XML encoded version of that character, which is "'".
Another better mitigation option is to use a precompiled XPath query. Precompiled XPath queries are already preset before the program executes, rather than created on the fly after the user's input has been added to the string. This is a better route because you don't have to worry about missing a character that should have been escaped.
No comments:
Post a Comment