Skip to main content

Asymmetric denial of service - ReDoS

Need

Mitigation of Regular Expression Denial of Service (ReDoS)

Context

  • Usage of C# for building robust and scalable applications
  • Usage of System.Text.RegularExpressions for pattern matching and regular expression operations

Description

Non compliant code

public class RegexValidator
{
public bool IsValidEmail(string email)
{
var regex = new Regex(@"^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");
return regex.IsMatch(email);
}
}

The above code is a simple email validator written in C#. It uses a regular expression to validate if the input string is an email or not.

The problem with this code is the use of a complex regular expression. This regular expression can be exploited using a technique known as Regular Expression Denial of Service (ReDoS).

ReDoS attacks exploit the fact that most regular expression implementations have exponential time worst-case complexity: the time taken can grow exponentially in relation to input size. An attacker can send a carefully crafted input string that takes a very long time to process, effectively causing a denial of service.

The IsValidEmail function is vulnerable to such an attack. If an attacker sends a specially crafted email string that results in a very long processing time by the regular expression, it could cause the server to become unresponsive or crash.

Steps

  • Replace the complex regular expression with a simpler and more efficient one.
  • Avoid the use of excessive quantifiers and nested groups in the regular expression.
  • Consider using built-in email validation libraries or functions instead of manually validating with regular expressions.
  • Implement input validation and sanitization to prevent malicious input from reaching the regular expression evaluation.
  • Perform thorough testing and benchmarking to ensure the regular expression does not cause performance issues or potential denial of service.

Compliant code

public class EmailValidator
{
public bool IsValidEmail(string email)
{
try
{
var addr = new System.Net.Mail.MailAddress(email);
return addr.Address == email;
}
catch
{
return false;
}
}
}

The original code was vulnerable to Regular Expression Denial of Service (ReDoS) attacks due to the use of a complex regular expression for email validation. The complexity of the regular expression could lead to excessive CPU usage when evaluating certain strings, potentially causing a denial of service.

The updated code mitigates this vulnerability by replacing the regular expression with the built-in System.Net.Mail.MailAddress class provided by .NET. This class is designed to handle email addresses, and its constructor will throw an exception if the provided string is not a valid email address. By using this class, we can avoid the risks associated with complex regular expressions.

The IsValidEmail method now tries to create a new MailAddress object with the provided email. If the email is valid, the constructor will succeed and the method will return true. If the email is not valid, the constructor will throw an exception, which is caught and causes the method to return false.

This approach is simpler, more efficient, and safer than the original regular expression. It also provides more accurate email validation, as it uses .NET's built-in functionality rather than a custom regular expression.

Remember to always validate and sanitize user input to prevent malicious data from causing issues. Regular expressions can be powerful tools, but they can also be dangerous if not used carefully. Always test your regular expressions thoroughly to ensure they do not cause performance issues or vulnerabilities.

References