正则表达式的回溯绕过

目录

一、回溯绕过 

二、防止正则表达式回溯绕过的方法 

三、PHP利用PCRE回溯次数限制绕过某些安全限制

1、 首先,来看一段PHP代码

2、正则回溯的过程

3、PHP的pcre.backtrack_limit 限制利用


一、回溯绕过 

        正则表达式的回溯绕过是指通过构造恶意输入,使得正则表达式引擎在匹配字符串时产生大量回溯操作,从而导致性能下降甚至造成拒绝服务(DoS)攻击。

        由于模式中的量词(例如星号*、加号+、问号?、花括号{}等)使得可能有多种不同的匹配方式,导致引擎需要尝试不同的组合,直到找到匹配的结果。这种尝试的过程就称为回溯。回溯操作会导致时间复杂度呈指数级增长,对于复杂的正则表达式和长字符串,性能损失会非常明显。

        攻击者可以通过构造一些恶意输入,使得正则表达式在尝试匹配时陷入大量的回溯过程,从而使得服务器的资源耗尽,无法继续响应其他请求,从而实现拒绝服务攻击。

        回溯绕过是一种常见的正则表达式攻击手段,合理使用正则表达式引擎和对输入进行有效验证是防止此类攻击的关键。

二、防止正则表达式回溯绕过的方法 

防止正则表达式回溯绕过的方法包括:

        1. 使用非回溯性的正则表达式引擎:某些正则表达式引擎支持非回溯的匹配算法,例如"正则表达式2"(Regular Expression 2,RE2)引擎,该引擎能够保证线性时间复杂度,从而避免回溯导致的性能问题。

        2. 限制正则表达式的复杂性:在编写正则表达式时,尽量避免使用过于复杂的表达式,特别是避免嵌套量词和回溯的使用。

        3. 输入验证和过滤:对于用户输入的数据,进行有效的验证和过滤,确保输入符合预期的格式和内容,防止恶意输入进入正则表达式匹配的过程。

        4. 采用其他字符串匹配算法:对于复杂的字符串匹配需求,可以考虑使用其他字符串匹配算法,如Aho-Corasick算法、Knuth-Morris-Pratt算法等,这些算法不涉及回溯,性能较为稳定。

三、PHP利用PCRE回溯次数限制绕过某些安全限制

1、 首先,来看一段PHP代码

].*/is', $data);  
}

        上面这段PHP代码实现了一个函数 is_php($data),用于检查输入的数据是否包含PHP代码片段。然后,在调用 is_php() 函数之后,代码使用 eval() 函数来执行用户输入的数据。这段代码存在严重的安全漏洞。

       安全问题:

        1. eval( ) 函数: eval( ) 函数用于执行字符串形式的PHP代码,但是这样的用法极其危险,因为它会执行任意代码,导致远程代码执行(Remote Code Execution,RCE)漏洞。不应该将未经验证的用户输入直接传递给 eval( )。

        2. 正则表达式漏洞:正则表达式 '/<\?.*[(`;?>].*/is' 存在问题。该表达式试图匹配包含 等标记的任意字符,但是由于缺乏边界约束,可能导致误匹配和绕过。例如,

2、正则回溯的过程

正则表达式 :

/<\?.*[(`;?>].*/is

测试文本 :

所以,如上之后  实际执行流程是这样的:

        1.第一个 .* 可以匹配任何字符,所以最终匹配到了输入串的结尾,也就是 //aaaaa。但此时显然是不对的,因为正则显示.*后面还应该有一个字符 [(`;?>]。     正则表达式的回溯绕过_第1张图片

         2.所以 NFA 就开始回溯,先吐出一个 a,输入变成第6步显示的 //aaaa,但仍然匹配不上正则,继续吐出 a,变成 //aaa,仍然匹配不上 正则表达式的回溯绕过_第2张图片

正则表达式的回溯绕过_第3张图片

        3.最终直到吐出;,输入变成第 13步显示的 ] ,这个结果满足正则表达式的要求,于是不再回溯。14步开始向后匹配;,15步匹配 . 第二个.匹配到了字符串末尾,最后结束匹配。

正则表达式的回溯绕过_第4张图片

正则表达式的回溯绕过_第5张图片正则表达式的回溯绕过_第6张图片

3、PHP的pcre.backtrack_limit 限制利用

        在PHP中,pcre.backtrack_limit  是一个配置选项,用于限制PCRE(Perl Compatible Regular Expressions)引擎的回溯深度。PCRE是PHP正则表达式引擎的一部分,它用于解析和匹配正则表达式。在PHP文档中,这个值一般是 100万

        我们通过发送超长字符串的方式,使正则执行失败,最后绕过目标对 PHP 语言的限制。

对应的DOC如下

import requests
from io import BytesIO

files = {
  'file': BytesIO(b'aaa

你可能感兴趣的:(网安,正则表达式,php,bug)