January 23, 2005

Mitigating XPath Injection Attacks in .NET

It's already 2005 and everybody's aware of SQL injection attacks nowadays. But it's silly to think that this kind of attack is only about SQL, right? SQL injection is just one particular case of a general code injection attack - when somebody too gullible allows user input to become a ...

I'm not going to explain what XPath injection attack is, it should be clear now or if it isn't - just go and read "Blind XPath Injection" paper by Amit Klein. I'd like to show you how to mitigate such kind of attacks in your .NET code.

So, considering above XPath selection, how would you defend your system from an evil user with fancy ' or ''=' as his name and password? All input is evil, so you definitely need to validate input fields before running SelectNodes, e.g. by checking if it doesn't contain apostrophes, but after all that's just a defensive kind of actions, which only patches some currently known vulnerabilities, while preserving unsecure code intact inviting hackers to come up with something slightly different, like using ' instead of apostrophes. A much better way to mitigate XPath injection attacks is to stop building dynamic XPath expressions from user input. Just as with SQL, the solution is simple - use parameters instead. Compile parametrized XPath expression and pass user input as a parameter value, not as part of expression. In addition to safety this aproach also nicely saves you CPU cycles on recompiling XPath expression for each selection.

.NET has everything for doing XPath selections that way. But unfortunately the XsltContext API isn't really intuitive one and is poorly documented. Happily there are XML MVPs around :). So Daniel Cazzulino has created handy DynamicContext class, which you can find in recently released Mvp.Xml v1.0 library, particulary in the Mvp.Xml.Common.XPath namespace. Read excellent Daniel's explanation for more info. I only want to show you couple of lines that leverage that class. Instead of crappy "//customer[@name='" + txtUser.Text + "' and @password='" + txtPassword.Text + "']" you can have shiny clear "//customer[@name=$name and @password=$password]", precompiled and bulletproof!

//Can be done at initialization time 
string xpath = "//customer[@name=$name and @password=$password]";
XPathExpression expr = DynamicContext.Compile(xpath);

//Run-time
DynamicContext ctx = new DynamicContext();
ctx.AddVariable("name", txtUser.Text);
ctx.AddVariable("password",txtPasowrd.Text);
expr.SetContext(ctx);
XPathNodeIterator custData = customers.Select(expr);
And you don't even have to validate user input here - it's all done for free.

Go download Mvp.Xml and start to play with its classes, there are some gems there that can save you hours of coding and make your code faster and safer. And be aware of XPath injection attack and ways to mitigate it in .NET.

Update from Daniel Cazzulino:

Better yet, they can directly use the XPathCache class (1 line of code!!!):
XPathNodeIterator custData = XPathCache.Select(
    "//customer[@name=$name and @password=$password]",
    customersDocument,
    new XPathVariable("name", txtName.Text), 
    new XPathVariable("password", txtPassword.Text));
And all will be equally precompiled, cached and secure :) . There is an overload for each need, and you can do pretty anything with a single line.