ThinkPHP 5.x 系列文件上传getshell
字数 901 2025-08-06 18:07:59

ThinkPHP 5.x 文件上传漏洞分析与利用

漏洞概述

ThinkPHP 5.x 系列在使用官方文件上传示例进行开发时,存在一个文件上传漏洞,可能导致攻击者上传恶意文件并获取服务器权限(getshell)。

漏洞背景

该漏洞存在于ThinkPHP 5.x框架中,当开发者使用官方提供的文件上传示例代码时,由于缺乏足够的文件类型和内容检查,攻击者可以绕过安全限制上传PHP等可执行文件。

漏洞原理

  1. 官方示例缺陷:ThinkPHP官方提供的文件上传示例代码未对上传文件的内容进行严格验证
  2. 文件类型绕过:攻击者可以通过修改HTTP请求中的Content-Type或文件扩展名来绕过检查
  3. 路径可控:上传路径可能被攻击者部分控制,导致文件被上传到可执行目录

漏洞复现步骤

环境准备

  • ThinkPHP 5.x 框架
  • 使用官方文件上传示例代码

攻击流程

  1. 构造恶意文件

    • 创建一个包含PHP代码的文件,例如shell.php
    • 可以伪装成图片文件:shell.php.jpg
  2. 修改请求参数

    • 修改Content-Type为合法类型(如image/jpeg
    • 使用双扩展名:filename="shell.php.jpg"
  3. 上传文件

    • 通过文件上传接口提交恶意文件
    • 利用框架的文件移动功能将文件保存到服务器
  4. 访问恶意文件

    • 直接访问上传的PHP文件执行代码
    • 获取服务器权限

漏洞利用代码示例

// 构造恶意上传请求的示例代码
$file = [
    'name' => 'shell.php.jpg',
    'type' => 'image/jpeg',
    'tmp_name' => '/tmp/phpshell',
    'error' => 0,
    'size' => 1234
];

// 使用ThinkPHP的文件上传方法
$upload = new \think\File($file);
$upload->move('/path/to/webroot');

防御措施

  1. 严格文件验证

    • 检查文件内容而不仅仅是扩展名或MIME类型
    • 使用finfo_file()函数验证实际文件类型
  2. 重命名上传文件

    // 生成随机文件名并保留原始扩展名
    $filename = md5(uniqid()) . '.' . pathinfo($upload->getInfo('name'), PATHINFO_EXTENSION);
    
  3. 限制上传目录

    • 将上传目录设置为不可执行
    • 配置Web服务器禁止执行上传目录中的PHP文件
  4. 更新框架版本

    • 升级到ThinkPHP最新版本,修复已知漏洞
  5. 使用安全配置

    // 在配置文件中设置严格的上传限制
    'file_upload' => [
        'ext'     => ['jpg', 'png', 'gif'], // 只允许图片扩展名
        'mime'    => ['image/jpeg', 'image/png', 'image/gif'], // 只允许图片MIME类型
        'size'    => 1024*1024, // 限制文件大小
        'save_path' => './uploads/', // 指定安全的上传路径
    ]
    

实际案例修复代码

public function upload()
{
    $file = request()->file('file');
    
    // 严格验证
    $info = $file->validate([
        'size' => 1024*1024,
        'ext'  => 'jpg,png,gif',
        'type' => 'image/jpeg,image/png,image/gif'
    ])->move('./uploads/');
    
    if($info){
        // 重命名文件
        $newName = md5(uniqid()) . '.' . $info->getExtension();
        rename($info->getPathname(), $info->getPath() . DS . $newName);
        
        return json(['status' => 1, 'path' => '/uploads/' . $newName]);
    }else{
        return json(['status' => 0, 'msg' => $file->getError()]);
    }
}

总结

ThinkPHP 5.x文件上传漏洞主要源于开发者过于依赖框架提供的示例代码而未进行足够的安全验证。通过严格的文件内容检查、安全的文件命名策略和适当的服务器配置,可以有效地防御此类漏洞。开发者应始终遵循"不信任用户输入"的原则,对所有上传文件进行严格验证。

ThinkPHP 5.x 文件上传漏洞分析与利用 漏洞概述 ThinkPHP 5.x 系列在使用官方文件上传示例进行开发时,存在一个文件上传漏洞,可能导致攻击者上传恶意文件并获取服务器权限(getshell)。 漏洞背景 该漏洞存在于ThinkPHP 5.x框架中,当开发者使用官方提供的文件上传示例代码时,由于缺乏足够的文件类型和内容检查,攻击者可以绕过安全限制上传PHP等可执行文件。 漏洞原理 官方示例缺陷 :ThinkPHP官方提供的文件上传示例代码未对上传文件的内容进行严格验证 文件类型绕过 :攻击者可以通过修改HTTP请求中的Content-Type或文件扩展名来绕过检查 路径可控 :上传路径可能被攻击者部分控制,导致文件被上传到可执行目录 漏洞复现步骤 环境准备 ThinkPHP 5.x 框架 使用官方文件上传示例代码 攻击流程 构造恶意文件 : 创建一个包含PHP代码的文件,例如 shell.php 可以伪装成图片文件: shell.php.jpg 修改请求参数 : 修改Content-Type为合法类型(如 image/jpeg ) 使用双扩展名: filename="shell.php.jpg" 上传文件 : 通过文件上传接口提交恶意文件 利用框架的文件移动功能将文件保存到服务器 访问恶意文件 : 直接访问上传的PHP文件执行代码 获取服务器权限 漏洞利用代码示例 防御措施 严格文件验证 : 检查文件内容而不仅仅是扩展名或MIME类型 使用 finfo_file() 函数验证实际文件类型 重命名上传文件 : 限制上传目录 : 将上传目录设置为不可执行 配置Web服务器禁止执行上传目录中的PHP文件 更新框架版本 : 升级到ThinkPHP最新版本,修复已知漏洞 使用安全配置 : 实际案例修复代码 总结 ThinkPHP 5.x文件上传漏洞主要源于开发者过于依赖框架提供的示例代码而未进行足够的安全验证。通过严格的文件内容检查、安全的文件命名策略和适当的服务器配置,可以有效地防御此类漏洞。开发者应始终遵循"不信任用户输入"的原则,对所有上传文件进行严格验证。