因用户输入与高开销正则表达式的比较而导致的拒绝服务攻击¶
ID: cs/redos
Kind: path-problem
Security severity: 7.5
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-1333
- external/cwe/cwe-730
- external/cwe/cwe-400
Query suites:
- csharp-code-scanning.qls
- csharp-security-extended.qls
- csharp-security-and-quality.qls
将用户输入与在最坏情况下需要指数时间的正则表达式进行匹配,可能会允许恶意用户通过精心设计需要很长时间才能执行的输入来执行拒绝服务(“DoS”)攻击。
大多数正则表达式引擎(包括 C# 标准库实现)都设计为使用扩展的正则表达式语法。尽管这为用户提供了灵活性,但它可能会阻止引擎在所有情况下都构建匹配器的有效实现。特别是,某些正则表达式的“最坏情况时间复杂度”(请参阅参考资料)可能是“指数级的”。这将允许恶意用户提供一些输入,导致正则表达式需要很长时间才能执行。
通常,如果正则表达式对自身重复或包含重叠选项的子表达式应用重复,则该正则表达式容易受到此攻击。例如,(a+)+
容易受到诸如 aaaaaaaaaaaaaaaaaaaaaaaaaaab
之类的字符串的攻击。有关确切情况的更多信息,请参阅参考资料。
建议¶
修改正则表达式以避免指数级的最坏情况时间。如果无法做到这一点,则应使用超时来避免拒绝服务。对于 C# 应用程序,可以为 Regex
构造函数提供超时。或者,使用 AppDomain.SetData
方法设置 REGEX_DEFAULT_MATCH_TIMEOUT
应用程序域属性来应用全局超时。
示例¶
以下示例显示了一个 HTTP 请求参数,该参数与最坏情况下性能呈指数级的正则表达式匹配。在第一种情况下,它在没有超时的情况下匹配,这可能导致拒绝服务。在第二种情况下,使用超时在 1 秒后取消对正则表达式的评估。
using System;
using System.Web;
using System.Text.RegularExpressions;
public class ReDoSHandler : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
string userInput = ctx.Request.QueryString["userInput"];
// BAD: User input is matched against a regex with exponential worst case behavior
new Regex("^([a-z]*)*$").Match(userInput);
// GOOD: Regex is given a timeout to avoid DoS
new Regex("^([a-z]*)*$",
RegexOptions.IgnoreCase,
TimeSpan.FromSeconds(1)).Match(userInput);
}
}