Hed9eh0g

前进的路上总是孤独的

thinkphp6.0.0-6.0.1 任意文件操作漏洞复现

本文共计有2062个字

前言

2020年1月10日,ThinkPHP团队发布一个补丁更新,修复了一处由不安全的SessionId导致的任意文件操作漏洞。该漏洞允许攻击者在目标环境启用session的条件下创建任意文件以及删除任意文件,在特定情况下还可以getshell。

根据tp官方的提交记录来看,是对setId函数(\vendor\topthink\framework\src\think\session\Store.php)做了修改:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

环境配置

首先该漏洞只存在于think6.0.0-6.0.1,因此如果版本太高要先进行降级操作。由于我的版本是6.0.2,与降级后的区别只是setId函数的不同,所以为了方便就直接在源码修改了。

    public function setId($id = null): void
    {
        //$this->id = is_string($id) && strlen($id) === 32 && ctype_alnum($id) ? $id : md5(microtime(true) . session_create_id());
        $this->id = is_string($id) && strlen($id) === 32 ? $id : md5(microtime(true) . session_create_id());
    }

另外,thinkphp6默认是没有开启session功能的,我们需要在app\middleware.php文件中,取消session中间件的注释,设置为如图:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

在app\controller\Index.php中:

  • 引入命名空间:

    use think\facade\Session;
  • index方法修改代码为:

    public function index()
    {
        Session::set('name','<?php phpinfo();?>');
        return 1;
    }

漏洞验证

抓包修改cookie为PHPSESSID=aaaabbbbccccddddeeeeffff1234.php

这里PHPSESSID值必须为32位的php文件名

改包之后发送,页面回显的cookie同样为PHPSESSID=aaaabbbbccccddddeeeeffff1234.php即代表将内容为<?php phpinfo();?>的代码成功写入文件名为sess_aaaabbbbccccddddeeeeffff1234.php的文件。

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

接着访问默认生成session文件的目录\runtime\session,可以看到的确写入shell成功:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

这里序列化形式是php存储session信息的默认方法,由于我们在index界面对session赋值Session::set('name','<?php phpinfo();?>');,所以该序列化形式就是对数组session['name']='<?php phpinfo();?>'的序列化结果。由于这里以php文件格式解析了,所以会执行代码。

漏洞分析

回溯写入Session时的$filename(vendor/topthink/framework/src/think/session/driver/File.php):

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

这里跟进writeFile函数可以看到是写入文件的操作:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

可以得知文件名filename对应是参数sessID经过getFileName函数得到的,跟进:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

也即在sessID的基础上添加了sess_前缀。

接着再看看sessID是怎么来的,且write函数是在哪里被调用(vendor/topthink/framework/src/think/session/Store.php):

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

跟进getID:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

直接返回id,再看看id是如何被设置的:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

根据源码可知$id从cookie中的PHPSESSID变量中获取的:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

从上面的分析就可以知道,session的id安全问题就是由于setID函数,当id的长度为32位时,直接就取对应的id作为值,而没有像版本修复后那样进行md5操作。因此当我们控制cookie的PHPSESSID为32位时,就会对session的内容以数组形式先进行序列化处理,然后执行write函数,也即对PHPSESSID进行前缀添加,然后最终被当做写入文件的文件名。

刚刚关注的是session文件名的生成,而这里的文件内容data对应就是session的内容,如果后端代码中存在可以控制session内容的操作,如Session::set('name',$_POST['c']);,就可以写入shell。

另外,原文中提到的可以删除任意文件,回溯到对delete函数的调用:

《thinkphp6.0.0-6.0.1 任意文件操作漏洞复现》

可以得知,需要$this->data 为空,也就是session设置的变量键值等于空,也即存在如Session::set('',$_POST['c']);这样的代码,才会进行删除操作。

参考文章

smi1e师傅的文章

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注