*本文原创作者: phith0n ,本文属FreeBuf原创奖励计划,未经许可禁止转载

这次 Code-Breaking Puzzles 中我出了一道看似很简单的题目pcrewaf,将其代码简化如下:

function is_php($data){

return preg_match('/].*/is', $data);

}

if(!is_php($input)) {

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

}

大意是判断一下用户输入的内容有没有 PHP 代码,如果没有,则写入文件。这种时候,如何绕过 is_php() 函数来写入 webshell 呢?

这道题看似简单,深究其原理,还是值得写一篇文章的。

0×01 正则表达式是什么

正则表达式是一个可以被「有限状态自动机」接受的语言类。

「有限状态自动机」,其拥有有限数量的状态,每个状态可以迁移到零个或多个状态,输入字串决定执行哪个状态的迁移。

而常见的正则引擎,又被细分为 DFA(确定性有限状态自动机)与 NFA(非确定性有限状态自动机)。他们匹配输入的过程分别是:

DFA: 从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入

NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态

由于 NFA 的执行过程存在回溯,所以其性能会劣于 DFA,但它支持更多功能。大多数程序语言都使用了 NFA 作为正则引擎,其中也包括 PHP 使用的 PCRE 库。

0×02 回溯的过程是怎样的

所以,我们题目中的正则 ].*,假设匹配的输入是 <?php phpinfo();//aaaaa,实际执行流程是这样的:

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

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

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

在调试正则表达式的时候,我们可以查看当前回溯的次数:

这里回溯了 8 次。

0×03 PHP 的 pcre.backtrack_limit 限制利用

PHP 为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit。我们可以通过 var_dump(ini_get(‘pcre.backtrack_limit’));的方式查看当前环境下的上限:

这里有个有趣的事情,就是 PHP 文档中,中英文版本的数值是不一样的:

我们应该以英文版为参考。

可见,回溯次数上限默认是 100 万。那么,假设我们的回溯次数超过了 100 万,会出现什么现象呢?比如:

可见,preg_match 返回的非 1 和 0,而是 false。

preg_match 函数返回 false 表示此次执行失败了,我们可以调用 var_dump(preg_last_error() === PREG_BACKTRACK_LIMIT_ERROR);,发现失败的原因的确是回溯次数超出了限制:

所以,这道题的答案就呼之欲出了。我们通过发送超长字符串的方式,使正则执行失败,最后绕过目标对 PHP 语言的限制。

对应的 POC 如下:

import requests

from io import BytesIO

files = {

'file': BytesIO(b'aaa<?php eval($_POST[txt]);//' + b'a' * 1000000)

}

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

print(res.headers)

0×04 PCRE 另一种错误的用法

延伸一下,很多基于 PHP 的 WAF,如:

if(preg_match('/SELECT.+FROM.+/is', $input)) {

die('SQL Injection');

}

均存在上述问题,通过大量回溯可以进行绕过。

另外,我遇到更常见的一种 WAF 是:

if(preg_match('/UNION.+?SELECT/is', $input)) {

die('SQL Injection');

}

这里涉及到了正则表达式的「非贪婪模式」。在 NFA 中,如果我输入 UNION/*aaaaa*/SELECT,这个正则表达式执行流程如下:

.+? 匹配到/

因为非贪婪模式,所以.+? 停止匹配,而由 S 匹配*

S 匹配*失败,回溯,再由.+? 匹配*

因为非贪婪模式,所以.+? 停止匹配,而由 S 匹配 a

S 匹配 a 失败,回溯,再由.+? 匹配 a

回溯次数随着 a 的数量增加而增加。所以,我们仍然可以通过发送大量 a,来使回溯次数超出 pcre.backtrack_limit 限制,进而绕过 WAF:

0×05 修复方法

那么,如何修复这个问题呢?

其实如果我们仔细观察 PHP 文档,是可以看到 preg_match 函数下面的警告的:

如果用 preg_match 对字符串进行匹配,一定要使用===全等号来判断返回值,如:

function is_php($data){

return preg_match('/].*/is', $data);

}

if(is_php($input) === 0) {

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

}

这样,即使正则执行失败返回 false,也不会进入 if 语句。

*本文原创作者: phith0n ,本文属FreeBuf原创奖励计划,未经许可禁止转载

php pcre回溯攻击,PHP利用PCRE回溯次数限制绕过某些安全限制 | 码农网相关推荐

  1. php pcre回溯攻击,php preg_match pcre回溯绕过

    原理 需要知识:正则NFA回溯原理,php的pcre.backtrack_limit设置. 正则NFA回溯原理 正则表达式是一个可以被"有限状态自动机"接受的语言类. " ...

  2. python回溯算法_什么是回溯法,Python解法交流?

    只有去多做题,才能慢慢掌握.力扣​leetcode-cn.com LeetCode 上的解释 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就 ...

  3. c语言 用回溯算法解决01背包问题,回溯法解决01背包问题

    <回溯法解决01背包问题>由会员分享,可在线阅读,更多相关<回溯法解决01背包问题(21页珍藏版)>请在人人文库网上搜索. 1.回溯法解决01背包问题,回溯法解决01背包问题, ...

  4. Serv-U的反弹攻击及其利用时间:2006-12-20 11:09来源:中国网管联盟 作者:网管整理 点击:899次...

    Serv-U的反弹攻击及其利用时间:2006-12-20 11:09来源:中国网管联盟 作者:网管整理 点击:899次     FTP反弹攻击(FTP Bounce Attack)是很古老的技术了,居 ...

  5. 浅谈XSS攻击的那些事(附常用绕过姿势)

    本文<浅谈XSS攻击的那些事(附常用绕过姿势)> 由一叶知安团队原创投稿安全脉搏首发,作者geek痕,安全脉搏独家首发表本文,如需要转载,请先联系安全脉搏授权:未经授权请勿转载. 随着互联 ...

  6. 此计算机必须为委派而被信任_实际利用Kerberos Bronze Bit漏洞绕过委派限制(CVE202017049)...

    0x00 前言 本文主要说明如何针对Kerberos Bronze Bit漏洞(CVE-2020-17049)进行实际利用的过程.在阅读这篇文章之前,我强烈建议大家首先阅读<Bronze Bit ...

  7. 6379端口恶意扫描_DNS重绑定的利用:端口扫描与绕过同源策略

    译文声明 本文是翻译文章,文章原作者bookgin,文章来源:http://bookgin.tw 原文地址:https://bookgin.tw/2019/01/05/abusing-dns-brow ...

  8. 利用jquery的qrcode.js插件生成二维码的两种方式的使用

    2019独角兽企业重金招聘Python工程师标准>>> 利用jquery的qrcode.js插件生成二维码的额两种方式,canvas(即画布)方式和table方式(原文地址http: ...

  9. Qt利用avilib实现录屏功能_openlayers6结合geoserver利用WFS服务实现图层编辑功能(附源码下载)...

    内容概览 1.openlayers6结合geoserver利用WFS服务实现图层编辑功能 2.源代码demo下载 效果图如下: 本篇主要是参照openlayers6结合geoserver利用WFS服务 ...

最新文章

  1. 微软压力测试工具 web application stress
  2. RHEL5一个网卡绑定多个IP
  3. 适应安装程序用的TreeView控件
  4. python编程小游戏-python趣味入门——写几个常玩的游戏
  5. [翻译] JTCalendar
  6. spring的bean范围_Spring Bean范围
  7. 产品认知:如何选择产品经理的产品方向?
  8. mysql_install_db: /usr/bin/perl: bad interpreter:
  9. licode学习之编译篇--3
  10. tar 整个linux系统,linux下tar解压
  11. 106 网络编程实战之基于socketserver实现多用户FTP服务器
  12. Java如何让程序一直运行,不停止
  13. 正确学习JavaScript知识和教程
  14. [绍棠] SwiftyJSON的使用详解
  15. 德乐Derler T-1series 120G SSD固态硬盘不认盘修复/开卡一例(SM2258XT主控),SM2259XT2可参考
  16. Xshell下载过期怎么办
  17. 你需了解:商务送礼的四大规矩
  18. 使用 Node 开发一个多人对战的射击游戏
  19. java.exe,javac.exe,javaw.exe 是什么进程? (转载)
  20. BLE学习笔记3:GAP初始化

热门文章

  1. 关闭打开苹果电脑Rootless机制
  2. sklearn对三维矩阵降维代码实现
  3. 【知乎】中国是否适合发展纯电动汽车?
  4. 论文中怎么引用yolo_论文中怎么加入脚注,并且对脚注的序号、位置、格式进行调整...
  5. 灌醉茅台董事长拿到便宜酒?潘长江和茅台双双回应...
  6. 落户北京经开区 小米汽车首车预计2024年下线并量产 网友:开始存钱!
  7. 中国移动将于11月4日首发上会 拟募资560亿元
  8. 年轻人原地过年,也不忘搞钱
  9. 那些除夕夜还在上BOSS直聘的人
  10. 华为P50 Pro外形首曝:新造型,头次见!