ThinkPHP 5.0.20 缓存文件写入漏洞本质是Cache::set()未校验用户输入,导致攻击者可控键名与内容,在runtime/cache/下生成并执行恶意PHP文件;修复需入口哈希键名、参数编码value、配置禁用PHP执行三端同步加固。

ThinkPHP 5.0.20 缓存文件写入漏洞本质是 Cache::set() 未对用户输入做校验,导致攻击者可控制缓存键名(key)与内容(value),最终在 runtime/cache/ 目录下生成并执行恶意 PHP 文件。修复不能只靠升级版本或加一两个 if 判断,必须从入口、参数、配置三端同步加固。
入口拦截:强制哈希缓存键名
所有传入 Cache::set() 的 key 必须经过不可逆哈希处理,禁止原始用户输入直接作键名:
- 将
Cache::set($_GET['key'], $value)改为Cache::set(md5($_GET['key']), $value) - 若需保留语义可拼接前缀,如
'user_' . md5($_GET['id']),但绝不可拼接../、/、.php等路径敏感字符 - 全局搜索项目中所有
Cache::set(、cache(、$cache->set(调用点,逐个确认 key 是否已哈希
参数过滤:严格处理缓存内容
value 是实际写入缓存文件的内容,必须防止注入可执行代码:
- 对所有传入的 value 做
base64_encode()或json_encode()编码,读取时再解码 - 禁用
htmlspecialchars()以外的输出类函数直接写入缓存——它不防 RCE,仅防 XSS - 特别警惕
file_get_contents(input('path'))这类调用,若input('path')可控,可能引入恶意脚本内容
配置加固:切断文件落地与执行链路
即使 key 和 value 被污染,也要确保无法生成或访问 PHP 文件:
立即学习“PHP免费学习笔记(深入)”;
- 修改
config/cache.php,将'data_path'设为绝对路径且不在 Web 根目录下,例如/var/data/myapp/cache/ - 若仍用
runtime/cache/,必须在 Web 服务器层禁止执行 PHP:Nginx 加location ~ ^/runtime/cache/.*\.php$ { return 403; };Apache 加<filesmatch> Require all denied </filesmatch>针对该路径 - 检查
runtime/目录权限,确保 Web 进程仅有写权限,无执行权限(Linux 下可用chmod -R 755 runtime+chown -R www:www runtime)
验证是否真正修复
修复后必须手动验证漏洞链是否断开:
- 构造测试请求:
GET /?key=../test&value=%3C%3Fphp%20phpinfo();%3F%3E(URL 编码后的 PHP 代码) - 检查
runtime/cache/目录下是否生成了含phpinfo()的文件,尤其是带.php后缀或路径穿越命名的文件 - 尝试直接访问疑似生成的缓存路径(如
/runtime/cache/xx/xxx.php),应返回 403 或 404,而非执行结果



















