ThinkPHP6.0 任意文件操作 漏洞分析复现

作者: secflag 分类: 漏洞分析 发布时间: 2020-03-01 08:23

一、漏洞简介

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

攻击者可利用此漏洞构造恶意的数据报文,向服务器写入任意内容的文件,从而能够达到远程代码执行.

二、影响范围

ThinkPHP6.0.0

ThinkPHP6.0.1

三、环境搭建

使用ThinkPHP6.0.0版本搭建,利用中间件phpstudy运行搭建的网站,

四、漏洞复现

利用条件:

在目标环境为Windows且开启session的情况下,容易遭受任意文件删除攻击。

在目标环境开启session且写入的session可控的情况下,容易遭受任意文件写入攻击。

修改/app/controller/Index.php 文件

增加下面这段代码:

修改 /app/middleware.php 文件如下

使用burp构造数据报文如下:

默认在目标/ runtime/session文件夹下生成如下文件

写入的文件内容

拼接URL地址:

替换payload获取webshell

获取webshell

五、漏洞分析

根据官方github的commit推测,可能是在存储session时导致的文件写入。然后,跟踪:vendor/topthink/framework/src/think/session/Store.php

public function save(): void

这里调用了一个write函数,跟进一下:vendor/topthink/framework/src/think/session/driver/File.php

调用writeFile函数,跟入:

写入文件的操作。

继续看一下文件名是否可控,该文件名来自于最开始的getId()得到的$sessionId的值。看一下函数内容:

在 session 初始化时,程序会将 PHPSESSID 对应的值赋值给 \think\session\Store:id 。这里如果 PHPSESSID 对应值长度等于32,则无任何过滤直接赋值,看一下调用setId的地方:vendor/topthink/framework/src/think/middleware/SessionInit.php:46。

然后在程序构造响应数据返回给用户时,会先将 session 写入文件,而这个文件的文件名则由之前的 PHPSESSID 拼接而成。由于没有任何的过滤,这也就造成了任意文件创建、覆盖。在session 数据可控的情况下,可以达到 getshell 的目的

六、漏洞修复

目前官网已经更新了thinkphp6.0.2版本,修复了该漏洞,建议尽快升级最新版本。