PHP中preg_replace函数解析
preg_replace — 执行一个正则表达式的搜索和替换
mixed preg_replace( mixed $pattern, mixed $replacement, mixed $subject)
搜索subject中匹配pattern的部分,以replacement进行替换。
常见于CTF竞赛中web题目中
1、/g 表示该表达式将用来在输入字符串中查找所有可能的匹配,返回的结果可以是多个。如果不加/g最多只会匹配一个
2、/i 表示匹配的时候不区分大小写,这个跟其它语言的正则用法相同
3、/m 表示多行匹配。什么是多行匹配呢?就是匹配换行符两端的潜在匹配。影响正则中的^$符号
4、/s 与/m相对,单行模式匹配。
5、/e 可执行模式,此为PHP专有参数,例如preg_replace函数。
6、/x 忽略空白模式。
对一个正则表达式模式或部分模式 两边添加圆括号 将导致相关 匹配存储到一个临时缓冲区 中
,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,
最多可存储 99 个捕获的子表达式。每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的
一位或两位十进制数。
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;
function complex($re, $str) {
preg_replace( '/(' . $re . ')/ei','strtolower("\\1")', $str);
}
foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}
function getFlag(){
@eval($_GET['cmd']);
}
#代码源于CTF题目“[BJDCTF2020]ZJCTF,不过如此”,部分解题过程。
其大致含义就是匹配出的任意内容,都用()包含起来,作为子字符串,存在缓冲区,\1是访问括号内的内容
对于该题可构造的部分payload:\S*=${phpinfo()}用来测试
实际为\S=${getFlag()},其实为了利用/e来利用漏洞,使函数执行
\S 在这里的作用是匹配任意长度的非空白字符序列。这样做的目的是为了确保可以成功触发 ${phpinfo()} 部分的执行,从而在服务器上执行恶意代码。
\S* 可以被替换为其他的正则表达式模式,只要能够匹配一些文本并触发 ${phpinfo()} 部分的执行即可。这些替代模式包括但不限于:
- .*: 匹配任意长度的字符序列(包括空白字符)。
- \w*: 匹配任意长度的字母数字字符序列。
- [^<>]*: 匹配任意长度的除尖括号之外的字符序列。
- [a-zA-Z0-9]*: 匹配任意长度的字母数字字符序列
对于payload中${}的解释,它这里其实是一个可变变量
我们输入了${phpinfo()},那么它呢因为被括号包裹了,就会存进缓冲区,而这里用到了/e,就相当于将第二个语句给执行了,就相当于eval(xx),第二个语句也就是\1,而\1的含义是${phpinfo()},他这个时候总的语句呢就是eval(${phpinfo()}),这玩意就相当于变量里面套变量,所以我们需要先执行里面的,也就是${phpinfo()} 中的 phpinfo() 会被当做变量先执行,执行后,即变成 ${1} (phpinfo()成功执行返回true)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具