Book Image

ASP.NET Core 5 Secure Coding Cookbook

By : Roman Canlas
Book Image

ASP.NET Core 5 Secure Coding Cookbook

By: Roman Canlas

Overview of this book

ASP.NET Core developers are often presented with security test results showing the vulnerabilities found in their web apps. While the report may provide some high-level fix suggestions, it does not specify the exact steps that you need to take to resolve or fix weaknesses discovered by these tests. In ASP.NET Secure Coding Cookbook, you’ll start by learning the fundamental concepts of secure coding and then gradually progress to identifying common web app vulnerabilities in code. As you progress, you’ll cover recipes for fixing security misconfigurations in ASP.NET Core web apps. The book further demonstrates how you can resolve different types of Cross-Site Scripting. A dedicated section also takes you through fixing miscellaneous vulnerabilities that are no longer in the OWASP Top 10 list. This book features a recipe-style format, with each recipe containing sample unsecure code that presents the problem and corresponding solutions to eliminate the security bug. You’ll be able to follow along with each step of the exercise and use the accompanying sample ASP.NET Core solution to practice writing secure code. By the end of this book, you’ll be able to identify unsecure code causing different security flaws in ASP.NET Core web apps and you’ll have gained hands-on experience in removing vulnerabilities and security defects from your code.
Table of Contents (15 chapters)

Fixing command injection

Web applications such as the ones developed with ASP.NET Core have a plethora of components and libraries that enable them to execute OS commands in the host. If not written securely, the code that composes and runs these commands can likely expose the ASP.NET Core web application to command injection exploitation. Shell commands can be executed unexpectedly if this security flaw in code is not prevented.

In this recipe, we will identify the command injection vulnerability in code and fix the security vulnerability.

Getting ready

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

Testing command injection

Here are the steps:

  1. Navigate to Terminal | New Terminal in the menu or simply press Ctrl + Shift + ' in Visual Studio Code.
  2. Type the following command in the terminal to build and run the sample app:
    dotnet run
  3. Open a browser and go to http://localhost:5000/Backups/Create.
  4. The browser will display the web page for initiating database backup, as shown in the following screenshot:
    Figure 2.5 – Backup page

    Figure 2.5 – Backup page

  5. Enter this command injection payload, backup & calc, in the Backup Name field, and hit the Create button.
  6. Notice that the page redirected to the list of backup pages and the backup was created. However, the calculator app has appeared:
Figure 2.6 – Successful command injection

Figure 2.6 – Successful command injection

If this security bug is not handled, this problem could also expose the underlying hosts to Remote Code Execution (RCE).

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/BackupService.cs file and locate the vulnerable part of the code in the BackupDB(string backupname) method:
    public async Task BackupDB(string backupname)
    {
        using (Process p = new Process())
        {
            string source =             Environment.CurrentDirectory +                 "\\OnlineBank.db";
            string destination =            Environment.CurrentDirectory +                "\\backups\\" + backupname;
            p.StartInfo.Arguments =             " /c copy " + source + " " + destination;
            p.StartInfo.FileName = "cmd";
            p.StartInfo.CreateNoWindow = true;
    ...code removed for brevity
  5. To remediate the command injection vulnerability, add a new method that utilizes the built-in file copying function:
    public async Task FileCopyAsync(string sourceFileName,    string destinationFileName,     int bufferSize = 0x1000,     CancellationToken cancellationToken =         default(CancellationToken))
    {
        using (var sourceFile =         File.OpenRead(sourceFileName))
        {
            using (var destinationFile =            File.OpenWrite(destinationFileName))
            {
                await             sourceFile.CopyToAsync(destinationFile,                bufferSize, cancellationToken);
            }
        }
    }      
  6. Rewrite the entire body of the BackupDB method and use the newly created method:
    public async Task BackupDB(string backupname)
    {
        string source =         Environment.CurrentDirectory +             "\\OnlineBank.db";
        string destination =         Environment.CurrentDirectory + "\\backups\\"             + backupname;
        await FileCopyAsync(source, destination);
    }

We have refactored the BackUpDB method to use the FileCopyAsync method to limit your code to just perform file copying tasks, thereby preventing the execution of unwanted shell commands.

How it works…

In our sample solution, administrators are allowed to provide a name to create a database backup. The BackUpDB method accepts a user-controlled input parameter of the string type. The input string is used to form a command that will initiate a command shell to have files copied from the source to the destination.

The added input string is expected to have the destination filename, but this can be manipulated to include commands that are more than just a value for an argument. Without validation or sanitization, this could cause the application to execute unwanted shell commands under the web application's identity and authorization.

There's more…

One option of stopping OS command injection is to implement proper validation through the whitelisting technique. This technique can be achieved by using regular expressions (see the Input validation recipe in Chapter 1, Secure Coding Fundamentals):

  1. Add a reference to the System.Text.RegularExpressions namespace:
    using System.Text.RegularExpressions;
  2. Then, use the RegEx class and its IsMatch method to validate the input against a pattern to only accept valid characters:
    public async Task BackupDB(string backupname)
    {
        var regex = new Regex(@"^[a-zA-Z0-9]+$");
        if (!regex.IsMatch(backupname)) return;
        using (Process p = new Process())
        {
            string source =             Environment.CurrentDirectory +                "\\OnlineBank.db";
            string destination =             Environment.CurrentDirectory +                "\\backups\\" + backupname;
            p.StartInfo.Arguments = " /c copy " + source +             " " + destination;
            p.StartInfo.FileName = "cmd";
            p.StartInfo.CreateNoWindow = true;
    // code removed for brevity

We have now added a whitelisting validation with the use of the IsMatch method. The IsMatch method prevents non-alphanumeric characters and input from being processed in the succeeding lines of code, mitigating the risk of command injection.