1.ReDoS漏洞概述
正则表达式拒绝服务(ReDoS)是指利用正则表达式在处理特定恶意输入时所表现出来的极端性能问题,导致系统长时间挂起或无法响应。这种攻击的核心问题在于某些复杂或不当设计的正则表达式,会在处理大量输入数据时,尤其是当输入匹配失败时,消耗大量的处理时间和计算资源
2.非确定性有限自动机NFA算法
算法概述
NFA与确定性有限自动机 (DFA) 都用于识别特定语言中的字符串,但 NFA 允许在每个状态下进行多条可能的路径选择,逐一尝试所有可能的路径(如果需要),直到找到匹配项,而 DFA 每个状态只能有唯一的下一步
例如这个正则表达式:^(a+)+$
,用于匹配以字母 a 组成的字符串
对于输入aaaaX
,有 16 条可能的路径:
但对于输入aaaaaaaaaaaaaaaaX
,则有 65536 条可能的路径,每增加一条,路径数就会翻倍a
上述示例的根本原因是正则表达式引擎的一项名为回溯的功能,例如,在匹配此正则表达式时,它会检查:
- a+ 匹配一个 a,然后回溯。
- a+ 尝试匹配两个 a,再次回溯。
- 以此类推。
这种复杂的回溯在处理长输入时会导致性能急剧下降,消耗大量计算资源,最终可能导致服务的拒绝响应
问题正则表达式
问题正则表达式是指那些由于复杂的匹配模式和设计,容易在特定输入上陷入回溯处理,导致性能大幅下降甚至引发拒绝服务 (ReDoS) 的正则表达式。以下是问题正则表达式的主要特点:
- 重复的分组:像
(a+)+
这样的模式在处理长串相同字符(如多个 ‘a
’)时,可能产生大量的回溯尝试。例如,对于aaaaaaaaa!
的输入,正则表达式引擎可能会尝试不同的方式来匹配每个字符,但最终无法匹配,导致时间复杂度急剧增加。 - 嵌套的可选匹配:
<font style="color:#0e0e0e;">(a|aa)+</font>
和<font style="color:#0e0e0e;">(a|a?)+</font>
等模式由于包含可选项和重叠分组,在长输入上会导致大量的回溯 - 广泛匹配的通配符和重复:像
<font style="color:#0e0e0e;">(.*a){x}</font>
中的<font style="color:#0e0e0e;">.*</font>
会尝试匹配任意长度的字符序列(<font style="color:#0e0e0e;">.</font>
匹配任意一个字符,<font style="color:#0e0e0e;">*</font>
表示前面的字符可以出现零次或多次),配合 a 和 {x}(当 x 值较大时)会极大增加匹配的复杂性
3.ReDoS攻击的代码案例
以下示例检查用户名是否是用户输入的密码的一部分:
String userName = textBox1.Text;
String password = textBox2.Text;
Regex testPassword = new Regex(userName);
Match match = testPassword.Match(password);
if (match.Success)
{
MessageBox.Show("Do not include name in password.");
}
else
{
MessageBox.Show("Good password.");
}
如果攻击者输入<font style="color:#0e0e0e;">^(([a-z])+.)+[A-Z]([a-z])+$</font>
用户名和<font style="color:#0e0e0e;">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!</font>
密码,程序就会挂掉
4.检查ReDoS漏洞是否存在的工具
1、https://github.com/doyensec/regexploit
2、在线工具
https://devina.io/redos-checker