thinkphp缓存漏洞本质是攻击者通过可控输入污染缓存文件内容导致rce,典型于3.2.x及部分5.x早期版本,主因是缓存写入未过滤换行符、未校验完整性、未限制执行上下文。

ThinkPHP缓存漏洞本质是攻击者通过可控输入污染缓存文件内容,使服务器在解析缓存时执行恶意代码。这类漏洞在3.2.x和部分5.x早期版本中尤为典型,核心风险点在于缓存写入未过滤换行符、未校验数据完整性、未限制执行上下文。
缓存漏洞常见利用方式
攻击者通常借助以下路径达成RCE:
-
换行注入+PHP标签闭合:向S()函数传入含%0A(\n)的字符串,如
a3=%0A%24a%3deval(%24_POST%5b%27a3%27%5d)%3b%2f%2f,导致缓存文件中插入恶意PHP语句,并被<?php ... ?>包裹后直接解析执行 -
缓存文件名可预测:S('name', $data)生成的缓存文件名为
md5('name').php,攻击者可精准构造访问路径,如/Runtime/Cache/Home/1e89c3c2a6f7d0b5e4a9c8b7a6f5d4e3.php - 配合其他漏洞扩大影响:例如先利用路由RCE写入一句话木马到缓存,再通过Nginx配置错误或目录遍历二次加载该缓存文件,绕过常规WebShell检测
关键防御措施
防御需覆盖写入、存储、加载三个环节,不能只堵单点:
-
写入层过滤换行与危险字符:修改
thinkphp/library/think/cache/driver/File.php中的set()方法,在serialize($value)后立即清理换行:$data = str_replace(["\r", "\n"], '', $data); -
存储层禁用PHP解析:将缓存目录移出Web可访问路径(如改至
/var/tmp/thinkphp_cache),或在Nginx中禁止执行PHP:location ~* ^/Runtime/Cache/.*\.php$ { return 403; } -
加载层强制白名单校验:若必须保留缓存文件在Web目录下,应在
get()方法中加入校验逻辑——对反序列化后的数据做类型检查(如仅允许数组、字符串、整数),拒绝含__destruct、__wakeup等魔术方法的对象
业务代码层面规避风险
很多缓存漏洞实际源于开发习惯问题,而非框架本身缺陷:
- 避免将未经处理的用户输入(尤其是POST/GET参数)直接传入S()、F()等缓存写入函数;确需缓存动态内容时,先过滤、转义、截断,再拼接固定前缀,如
S('user_'.$uid.'_profile', $cleaned_data) - 禁用
DATA_CACHE_COMPRESS(开启gzip压缩可能干扰反序列化校验)、禁用DATA_CACHE_CHECK(MD5校验不防篡改,仅防损坏) - 生产环境关闭所有调试类缓存机制,包括
Trace、Debug、Log相关缓存开关,防止敏感信息落盘
验证与长期防护
修复后必须验证是否真正生效:
- 手动触发一次缓存写入,检查生成的
.php文件内容是否仍含换行或eval等关键字 - 用curl模拟攻击载荷访问缓存路径,确认返回403或空白页,而非PHP解析结果
- 将缓存目录权限设为
750,属主为Web服务运行用户(如www-data),禁止其他用户读写 - 在CI/CD流程中加入静态扫描规则,自动检测项目中所有
S(、F(调用点,标记高危用法并阻断发布
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











