.NET Top 10 OWASP Protection: A Guide (Part 1)



Profile picture of Nikita Starichenko Hacker Noon

@foxtailNikita Staritchenko

Full-stack developer over 7 years old

The Top 10 OWASP is a standard awareness document for developers and web application security. It represents a broad consensus on the most critical security risks for web applications.

In this article, I want to cover the first part of the TOP 10 vulnerabilities and how to protect yourself against them using .NET.

1. Injection

What it is?

Almost any data source can be an injection – vector, environment variables, settings, external and internal web services, and all types of users. Injection flaws occur when an attacker can send hostile data to an interpreter. Injection vulnerabilities are often found in SQL, LDAP, XPath, or NoSQL queries, OS commands, XML parsers, SMTP headers, expression languages, and ORM queries. Injection may result in loss of data, corruption or disclosure to unauthorized parties, loss of liability or denial of access.

What has to be done?

SQL injection

  1. Using an object-relational mapper (ORM) or stored procedures is the most effective way to address the SQL Injection vulnerability.
  2. Use parameterized queries when a direct SQL query must be used.
  3. Practice Least Privilege – Log into the database using an account with a minimum set of permissions required to do its job i.e. not the same account

Good example:

    var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id";
        new SqlParameter("@FirstName", firstname),
        new SqlParameter("@Id", id));

Bad example:

    string strQry = "SELECT * FROM Users WHERE UserName='" + txtUser.Text + "' AND Password='"
                    + txtPassword.Text + "'";
    EXEC strQry // SQL Injection vulnerability!

Operating system injection

  1. Use System.Diagnostics.Process.Start to call the underlying operating system functions.
  2. System.Diagnostics.Process process = new System.Diagnostics.Process();
    System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
    startInfo.FileName = "validatedCommand";
    startInfo.Arguments = "validatedArg1 validatedArg2 validatedArg3";
    process.StartInfo = startInfo;
  3. Use whitelist validation on all user-supplied entries. Input validation prevents malformed data from entering an information system.
  4. //User input
    string ipAddress = "";
    //check to make sure an ip address was provided
    if (!string.IsNullOrEmpty(ipAddress))
     // Create an instance of IPAddress for the specified address string (in
     // dotted-quad, or colon-hexadecimal notation).
     if (IPAddress.TryParse(ipAddress, out var address))
      // Display the address in standard notation.
      return address.ToString();
      //ipAddress is not of type IPAddress

LDAP injection

  1. Almost any character can be used in distinguished names. However, some must be escaped with the backslash escape character.
  2. The space character should be escaped only if it is the start or end character of a component name, such as a common name. Recessed spaces must not be escaped.

2. Broken authentication

What it is?

Attackers can detect broken authentication using manual means and exploit it using automated tools with password lists and dictionary attacks. Attackers only have access to a few accounts or to a single administrator account to compromise the system. Depending on the area of ​​the application, this may enable money laundering, social security fraud and identity theft, or disclose highly sensitive information protected by law.

What has to be done?

  1. Use ASP.net Core Identity. The ASP.net Core Identity framework is well configured by default, where it uses secure password hashes and individual salt. Identity uses the PBKDF2 hash function for passwords and generates a random salt per user.
  2. Define a secure password policy
  3. //startup.cs
    services.Configure(options =>
     // Password settings
     options.Password.RequireDigit = true;
     options.Password.RequiredLength = 8;
     options.Password.RequireNonAlphanumeric = true;
     options.Password.RequireUppercase = true;
     options.Password.RequireLowercase = true;
     options.Password.RequiredUniqueChars = 6;
     options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
     options.Lockout.MaxFailedAccessAttempts = 3;
     options.SignIn.RequireConfirmedEmail = true;
     options.User.RequireUniqueEmail = true;
  4. Define a cookies policy
  5. //startup.cs
    services.ConfigureApplicationCookie(options =>
     options.Cookie.HttpOnly = true;
     options.Cookie.Expiration = TimeSpan.FromHours(1)
     options.SlidingExpiration = true;

3. Exposure of sensitive data

What it is?

Rather than directly attacking cryptography, attackers steal keys, perform man-in-the-middle attacks, or steal clear text data on the server, in transit, or from the user’s client. , for example the browser. The most common flaw is simply not encrypting sensitive data. When cryptography is used, weak key generation and management and low algorithm, protocol and encryption usage are common, especially for weak password hash storage techniques. Failure frequently compromises all data that should have been protected. Typically, this information includes Sensitive Personal Data (PII) such as health records, identifying information, personal data, and credit cards, which often require protection as defined by laws or regulations. such as EU GDPR or local privacy laws.

What has to be done?

  1. Use a strong hash to store the password credentials.
  2. Apply passwords with minimal complexity that will survive dictionary attack i.e. longer passwords that use the full character set (numbers, symbols, and letters) to increase entropy .
  3. Use a strong encryption routine such as AES-512 where personally identifiable data must be restored to its original format.
  4. Use TLS 1.2 for your entire site.
  5. Have a strong TLS policy, use TLS 1.2 where possible.
  6. Make sure the headers don’t disclose information about your app.

Example for headers

app.UseHsts(hsts => hsts.MaxAge(365).IncludeSubdomains());
app.UseReferrerPolicy(opts => opts.NoReferrer());
app.UseXXssProtection(options => options.FilterDisabled());
app.UseXfo(options => options.Deny());

app.UseCsp(opts => opts
 .StyleSources(s => s.Self())
 .StyleSources(s => s.UnsafeInline())
 .FontSources(s => s.Self())
 .FormActions(s => s.Self())
 .FrameAncestors(s => s.Self())
 .ImageSources(s => s.Self())
 .ScriptSources(s => s.Self())

4. XML External Entities (XXE)

What it is?

Attackers can exploit vulnerable XML processors if they can download XML or include hostile content in an XML document, exploiting vulnerable code, dependencies, or integrations. By default, many older XML processors allow the specification of an external entity, a URI that is dereferenced and evaluated during XML processing. These flaws can be used to extract data, execute a remote query from the server, analyze internal systems, perform a denial of service attack, as well as perform other attacks.

What has to be done?

  1. Use LINQ to XML. The XElement and XDocument objects in the System.Xml.Linq library are protected against XXE injection by default.
  2. Use XmlDictionaryReader. System.Xml.XmlDictionaryReader is safe by default, because when it tries to parse the DTD, the compiler throws an exception stating that “CData elements are not valid at the top level of an XML document”.
  3. Using XmlDocument, set XmlResolver to null.
  4.  static void LoadXML()
       string xxePayload = "]>"
                         + "<doc>&win;doc>";
       string xml = "" + xxePayload;
       XmlDocument xmlDoc = new XmlDocument();
       // Setting this to NULL disables DTDs - Its NOT null by default.
       xmlDoc.XmlResolver = null;
  5. Use XmlNodeReader. System.Xml.XmlNodeReader objects are secure by default and will ignore DTDs even when built with an insecure parser or wrapped in another unsafe parser.
  6. Use XmlReader. System.Xml.XmlReader objects are secure by default.
  7. Use XmlTextReader. In .NET Framework versions 4.5.2 and later, the internal XmlResolver of XmlTextReader is set to null by default, which causes XmlTextReader to ignore DTDs by default.
  8. Using XPathNavigator, give it a safe parser like XmlReader (which is safe by default) in the XPathDocument constructor.
  9. XmlReader reader = XmlReader.Create("example.xml");
    XPathDocument doc = new XPathDocument(reader);
    XPathNavigator nav = doc.CreateNavigator();
    string xml = nav.InnerXml.ToString();
  10. Use XslCompiledTransform. System.Xml.Xsl.XslCompiledTransform (an XML transformer) is safe by default as long as the parser supplied to it is safe.

5. Access control broken

What it is?

The exploitation of access control is an essential skill of attackers. Access control can be detected by manual means, or possibly by automation for the absence of access control in certain frameworks. Access control weaknesses are common due to the lack of automated detection and the lack of effective functional testing by application developers. The technical impact is that attackers act as users or administrators, or users using privileged functions, or creating, accessing, updating or deleting each record.

What has to be done?

  1. Make sure cookies are sent via httpOnly:
  2. Reduce the period during which a session can be stolen by reducing the session timeout and removing sliding expiration:
  3. ExpireTimeSpan = TimeSpan.FromMinutes(60),
    SlidingExpiration = false
  4. Protect login, registration and password reset methods from brute force attacks by limiting requests (see code below), also consider using ReCaptcha.
  5. [HttpPost]
    [AllowXRequestsEveryXSecondsAttribute(Name = "LogOn",
    Message = "You have performed this action more than {x} times in the last {n} seconds.",
    Requests = 3, Seconds = 60)]
    public async Task LogOn(LogOnViewModel model, string returnUrl)
  6. Authorize users on all external endpoints. The .NET framework has several ways of authorizing a user, use them at the method level:
  7. [Authorize(Roles = "Admin")]
    public ActionResult Index(int page = 1)
    // or better yet, at controller level:
    public class UserController
  8. When you have a resource (object) accessible by a reference (in the example below this is the identifier) ​​you need to make sure that the user is supposed to be there
  9. // Insecure
    public ActionResult Edit(int id)
      var user = _context.Users.FirstOrDefault(e => e.Id == id);
      return View("Details", new UserViewModel(user);
    // Secure
    public ActionResult Edit(int id)
      var user = _context.Users.FirstOrDefault(e => e.Id == id);
      // Establish user has right to edit the details
      if (user.Id != _userIdentity.GetUserId())
            HandleErrorInfo error = new HandleErrorInfo(
                new Exception("INFO: You do not have permission to edit these details"));
            return View("Error", error);
      return View("Edit", new UserViewModel(user);

PS Thanks for reading! Soon the second part.

Learn more about OWASP – https://owasp.org/www-project-top-ten/

Profile picture of Nikita Starichenko Hacker Noon


Join Hacker Midi

Create your free account to unlock your personalized reading experience.



Comments are closed.