Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
ASP.NET Core 5 Secure Coding Cookbook

You're reading from   ASP.NET Core 5 Secure Coding Cookbook Practical recipes for tackling vulnerabilities in your ASP.NET web applications

Arrow left icon
Product type Paperback
Published in Jul 2021
Publisher Packt
ISBN-13 9781801071567
Length 324 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Roman Canlas Roman Canlas
Author Profile Icon Roman Canlas
Roman Canlas
Arrow right icon
View More author details
Toc

Table of Contents (15) Chapters Close

Preface 1. Chapter 1: Secure Coding Fundamentals 2. Chapter 2: Injection Flaws FREE CHAPTER 3. Chapter 3: Broken Authentication 4. Chapter 4: Sensitive Data Exposure 5. Chapter 5: XML External Entities 6. Chapter 6: Broken Access Control 7. Chapter 7: Security Misconfiguration 8. Chapter 8: Cross-Site Scripting 9. Chapter 9: Insecure Deserialization 10. Chapter 10: Using Components with Known Vulnerabilities 11. Chapter 11: Insufficient Logging and Monitoring 12. Chapter 12: Miscellaneous Vulnerabilities 13. Chapter 13: Best Practices 14. Other Books You May Enjoy

Fixing XPath injection

Data-driven ASP.NET Core web applications can use XML databases as a means to store information and records. These data types are in XML format, and one way of navigating through the nodes of XML is by XPath.

Developers can, by mistake, dynamically construct XPath queries with untrusted data. This neglect can result in an arbitrary query execution or the retrieval of sensitive data from the XML database.

In this recipe, we will fix the XPath injection vulnerability in code.

Getting ready

Using Visual Studio Code, open the sample Online Banking app folder at \Chapter02\xpath-injection\before\OnlineBankingApp\.

This example uses the following XML data:

<?xml version="1.0" encoding="utf-8"?>
<knowledgebase>
    <knowledge>
        <topic lang="en">Types of Transfers</topic>
        <description lang="en">
            Make transfers from checking and savings to:
            Checking and savings
            Make transfers from line of credit to:
            Checking and savings
        </description>
        <tags>transfers, transferring funds</tags>
        <sensitivity>Public</sensitivity>
    </knowledge>
    <knowledge>
        <topic lang="en">Expedited Withdrawals</topic>
        <description lang="en">
        Expedited withdrawals are available to our         executive account holders.
        You may reach out to Stanley Jobson at         stanley.jobson@bank.com
        </description>
      <tags>withdrawals, expedited withdrawals</tags>
      <sensitivity>Confidential</sensitivity>
    </knowledge>
</knowledgebase>

How to do it…

Let's take a look at the steps for this recipe:

  1. Launch Visual Studio Code and open the starting exercise folder by typing the following command:
    code .
  2. Navigate to Terminal | New Terminal in the menu or simply press Ctrl + Shift + ' in Visual Studio Code.
  3. Type the following command in the terminal to build the sample app to confirm that there are no compilation errors:
    dotnet build
  4. Open the Services/KnowledgebaseService.cs file and locate the vulnerable part of the code in the Search method:
    public List<Knowledge> Search(string input)
    {
        List<Knowledge> searchResult = new         List<Knowledge>(); 
        var webRoot = _env.WebRootPath;
        var file = System.IO.Path.Combine(webRoot,        "Knowledgebase.xml");
        
        XmlDocument XmlDoc = new XmlDocument();
        XmlDoc.Load(file);
        
        XPathNavigator nav = XmlDoc.CreateNavigator();
        XPathExpression expr =        nav.Compile(@"//knowledge[tags[contains(text()            ,'" + input + "')] and sensitivity/text()                ='Public']");
        var matchedNodes = nav.Select(expr);
    // code removed for brevity

    An XPath expression is dynamically created by concatenating the user-controlled input. Without any validation or sanitization done on the input parameter, a malicious actor can manipulate the XPath query by injecting malicious string, changing the intent of the whole expression.

  5. To fix this security bug, let's refactor the code and implement input sanitization based on the whitelisting technique. To start, add a reference to both the System and System.Linq namespaces:
    using System;
    using System.Linq;
  6. Add a new method to the KnowledgebaseService class and name it Sanitize:
    private string Sanitize(string input)
    {
        if (string.IsNullOrEmpty(input)) {
            throw new ArgumentNullException("input",             "input cannot be null");
        }
        HashSet<char> whitelist = new HashSet<char>        (@"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ             abcdefghijklmnopqrstuvwxyz ");
        return string.Concat(input.Where(i =>        whitelist.Contains(i))); ;
    }
  7. Call the new Sanitize method, passing the input parameter to it as an argument. Assign the result to the sanitizedInput variable:
    public List<Knowledge> Search(string input)
    {
        string sanitizedInput = Sanitize(input);
        List<Knowledge> searchResult = new         List<Knowledge>(); 
        var webRoot = _env.WebRootPath;
        var file = System.IO.Path.Combine(webRoot,        "Knowledgebase.xml");
        
        XmlDocument XmlDoc = new XmlDocument();
        XmlDoc.Load(file);
        
        XPathNavigator nav = XmlDoc.CreateNavigator();
        XPathExpression expr =         nav.Compile(@"//knowledge[tags[contains(text()            ,'" + sanitizedInput + "')] and                 sensitivity/text()='Public']");
    // code removed for brevity

The custom Sanitize method will now remove unnecessary and possibly dangerous characters in the input string. The output is now passed into a sanitizedInput variable, making the XPath expression safe from exploitation.

How it works…

As we have learned in Chapter 1, Secure Coding Fundamentals, in the Input sanitization section, input sanitization is a defensive technique that can be practiced to remove suspicious characters in a user-supplied input. This approach will prevent the application from processing unwanted XPath injected into the query.

We have created the new Sanitize method that will serve as our sanitizer. Inside this method is a whitelist of defined characters and a Lambda invoked to remove the characters rejected from userName:

HashSet<char> whitelist = new HashSet<char>(@"1234567890ABCDEFGHI JKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ");
return string.Concat(input.Where(i =>    whitelist.Contains(i))); ;

Searching for a help article with an unacceptable character will not throw an exception, and our sample Online Banking web application will also not process the string:

Figure 2.9 – Searching the knowledge base

Figure 2.9 – Searching the knowledge base

There's more…

An alternative fix is to parameterize the XPath query. We will define a variable that will serve as a placeholder for an argument. This technique allows the data to be separated from code:

XmlDocument XmlDoc = new XmlDocument();
XmlDoc.Load(file);
XPathNavigator nav = XmlDoc.CreateNavigator();
XPathExpression expr =    nav.Compile(@"//knowledge[tags[contains(text(),$input)]        and sensitivity/text()='Public']");
XsltArgumentList varList = new XsltArgumentList();
varList.AddParam("input", string.Empty, input);
CustomContext context = new CustomContext(new NameTable(),    varList);
expr.SetContext(context);
var matchedNodes = nav.Select(expr);
foreach (XPathNavigator node in matchedNodes)
{ 
    searchResult.Add(new Knowledge() {Topic =      node.SelectSingleNode(nav.Compile("topic"))        .Value,Description = node.SelectSingleNode           (nav.Compile("description")).Value}); 
}

In the preceding code, the XPath expression is modified, and the $input variable is now a placeholder for the previously concatenated input value. We also used the XsltArgumentList object to create a list of arguments to include input before passing into the XpathExpression expression's custom context. In this way, the XPath query is parameterized and protected from malicious injection upon execution.

Note

This mitigation requires the creation of a user-defined custom context class that derives from XsltContext. There are other classes required to make this XPath parameterization possible. The class files are included in the sample solution, namely; Services\XPathExtensionFunctions.cs, Services\XPathExtensionVariable.cs, and Services\CustomContext.cs. The whole guide and source for these classes are also available online at the .NET official documentation: https://docs.microsoft.com/en-us/dotnet/standard/data/xml/user-defined-functions-and-variables.

You have been reading a chapter from
ASP.NET Core 5 Secure Coding Cookbook
Published in: Jul 2021
Publisher: Packt
ISBN-13: 9781801071567
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime