PHP 7.4 缓存无“时间戳漏洞”标准术语,实指两类风险:一是缓存键遗漏用户身份等关键上下文致敏感内容误共享;二是缓存失效依赖客户端可控时间参数(如?t=xxx)被篡改绕过校验。修复需服务端统一控制缓存策略,禁用客户端时间戳驱动逻辑,改用用户标识哈希、签名调试指令、内容哈希命名及事件触发式失效。

PHP 7.4 的缓存模块本身不内置“时间戳漏洞”这个标准术语,但实际开发中常指两类高发风险:一是缓存键未包含时间敏感上下文(如用户身份、权限状态),导致敏感内容被错误共享;二是缓存失效逻辑依赖客户端可控的时间参数(如 ?t=1729604520),被篡改后绕过刷新或触发条件竞争。这两类问题都不在 PHP 内核层面修复,而取决于你如何设计缓存策略和校验逻辑。
避免缓存键遗漏关键上下文
CDN、反向代理或应用层文件缓存若仅用 URL 路径作缓存键,会把不同用户的响应混在一起。例如访问 /profile?id=1001 和 /profile?id=1002 返回不同数据,但若缓存系统忽略查询参数或统一归一化,就可能返回错人的信息。
- 对含用户态的接口(如个人中心、订单列表),缓存键必须显式包含用户标识,比如拼接
sha256("profile_{$uid}_{$lang}"),而非直接缓存原始 URL - 使用 Symfony Cache 或 APCu 时,避免只传
$cache->get($request->getRequestUri()),应改为$cache->get('user_profile_' . $user->getId()) - 若用 Nginx 或 Varnish,检查
proxy_cache_key或hash配置是否包含$cookie_PHPSESSID或自定义 header(如X-User-ID)
禁用时间戳驱动的缓存控制参数
有些老项目允许前端通过 ?_t=123456789 强制刷新缓存,后端却未校验该参数来源或有效性。攻击者可构造任意时间戳绕过业务逻辑中的缓存跳过判断,或利用时间窗口发起重放攻击。
- 删除所有形如
if (isset($_GET['_t'])) { bypassCache(); }这类逻辑,缓存策略应由服务端统一决策,不交由客户端控制 - 如需强制刷新调试,改用带签名的后台指令(如
?debug_refresh=abc123&sig=xxx),且仅限本地 IP 或管理员 Token 访问 - 对静态资源,用内容哈希代替时间戳:将
style.css?t=1729604520改为style.a1b2c3d4.css,由构建工具生成,彻底消除时间维度干扰
缓存失效必须绑定真实业务事件
靠定时器或固定 TTL 清除缓存,容易出现“旧数据残留”或“频繁穿透”。时间戳若被用于模拟“最后更新时间”,又未与数据库变更强同步,就会产生一致性漏洞。
立即学习“PHP免费学习笔记(深入)”;
- 用户资料更新后,立刻执行
$cache->delete('user_profile_' . $userId),而不是等缓存自然过期 - 避免在缓存值里存一个“last_updated”时间戳并由前端比对——这等于把数据新鲜度判断权交给不可信端
- 对列表类缓存(如商品推荐),用版本号替代时间戳:
cacheKey = "recommend_v2_{$categoryId}",运营后台修改规则时主动递增版本号并清旧缓存
文件缓存需防范并发写入与路径污染
PHP 7.4 常用文件缓存(如自建 file_put_contents() + file_get_contents()),若缓存文件名含用户输入或时间戳,可能引发路径穿越或覆盖。
- 禁止用
date('YmdHis')或microtime(true)直接拼文件名,改用唯一 ID(bin2hex(random_bytes(8)))或哈希 - 缓存目录必须设为非 Web 可访问路径(如
/var/cache/myapp/),且确保open_basedir已启用 - 写入前调用
flock($fp, LOCK_EX),读取后验证文件内容是否完整(如检查 JSON 结构或序列化格式是否合法),防止脏读



















