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 LDAP injection

The Light Directory Access Protocol (LDAP) is a standard protocol used to access directory services such as Microsoft's Active Directory and Apache Directory. Web applications use LDAP to search the directory server to get users and group information, which also serves as a means of authentication. This retrieval of data from the web application to the LDAP directory server is possible because of the LDAP query language and its filters. Developers write code to compose these queries. Like any other dynamic query construction, this method can open the code to injection, particularly LDAP injection, when the concatenated user-controlled input is not validated or sanitized.

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

Getting ready

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

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/LdapDirectoryService.cs file and locate the vulnerable part of the code in the Search(string userName) method:
    public User Search(string userName)
    {
        using (DirectoryEntry entry =         new DirectoryEntry(config.Path))
        {
            entry.AuthenticationType =            AuthenticationTypes.Anonymous;
            using (DirectorySearcher searcher =             new DirectorySearcher(entry))
            {
                searcher.Filter = "(&(" +                UserNameAttribute + "="                     + userName + "))";
                searcher.PropertiesToLoad.Add                 (EmailAttribute);
                searcher.PropertiesToLoad.Add                 (UserNameAttribute);
                var result = searcher.FindOne();
    // code removed for brevity
  5. To fix the LDAP injection vulnerability, refactor the code to include a whitelist validation of the userName parameter:
    public User Search(string userName)
    {
        if (Regex.IsMatch(userName, "^[a-zA-Z][a-zA-Z0-        9]*$")){
            using (DirectoryEntry entry =             new DirectoryEntry(config.Path))
            {
                entry.AuthenticationType =                AuthenticationTypes.Anonymous;
                using (DirectorySearcher searcher =                 new DirectorySearcher(entry))
                {
                    searcher.Filter = "(&(" +                     UserNameAttribute + "=" + userName                         + "))";
                    searcher.PropertiesToLoad.Add                     (EmailAttribute);
                    searcher.PropertiesToLoad.Add                     (UserNameAttribute);
                    var result = searcher.FindOne();
    // code removed for brevity

Reusing the whitelisting technique through the use of regular expressions, we again utilize the IsMatch method to ascertain whether the pattern matches the input. If the input does not match the regular expression, the input is then rejected.

How it works…

In our sample solution, we have a web page that allows an admin user to search for a specific user account using the search bar:

Figure 2.7 – Manage Users page

Figure 2.7 – Manage Users page

Entering a user ID and hitting the Search button will send an LDAP query to the LDAP directory service to search for a user that has the exact user ID:

Figure 2.8 – Search user result

Figure 2.8 – Search user result

Note

The steps on setting up your LDAP directory service are not provided in this book. Suppose you want a working directory server that runs in your local machine to work with the sample solution. In that case, I suggest you install ApacheDS and follow the steps from the Setting up an LDAP server for development/testing using Apache Directory Studio page in the official Crafter CMS documentation: https://docs.craftercms.org/en/3.1/developers/cook-books/how-tos/setting-up-an-ldap-server-for-dev.html.

Change the Ldap entry in appsettings.json if necessary:

"Ldap": {

"Path": "LDAP://localhost:10389/DC=example,DC=com",

"UserDomainName": "example"

},

As the Search method is invoked, an LDAP query is dynamically composed, and a filter is concatenated with the value entered in the search textbox:

searcher.Filter = "(&(" + UserNameAttribute + "=" + userName + "))";

The userName parameter is not sanitized or validated, and a bad actor can exploit this by injecting suspicious filters that could retrieve sensitive information from the LDAP directory server.

To mitigate this risk, we used Regex's IsMatch method to add a whitelist validation approach. The conditional expression will only be equivalent to true if any of the characters in userName are alphanumeric:

public User Search(string userName)
{
    if (Regex.IsMatch(userName, "^[a-zA-Z][a-zA-Z0-9]*$")){
        using (DirectoryEntry entry = new             DirectoryEntry(config.Path))
        {
// code removed for brevity

Include as part of the overall secure coding strategy the implementation of a whitelist input validation to check user-controlled inputs, safeguarding your ASP.NET Core web application from LDAP injection attacks.