nginx缓存安全风险源于请求头干扰缓存决策逻辑,而非请求头本身被缓存;攻击者通过篡改host、cache-control等头或伪造自定义头污染缓存key、绕过缓存控制、破坏租户隔离,需禁用易伪造变量参与key构造、白名单校验业务头、显式配置缓存策略。

请求头本身不会被“缓存”,但请求头会直接影响 Nginx 缓存是否命中、如何生成 key、是否跳过缓存——这正是所谓“缓存规则注入”的实际发生位置。问题本质不是“缓存了 Host 或 User-Agent”,而是攻击者通过构造恶意请求头,干扰 Nginx 的缓存决策逻辑,从而导致缓存污染、内容覆盖或权限越界。
Host 头注入直接污染缓存 key
当 Nginx 配置中使用了包含 $host 或 $http_host 的 proxy_cache_key(例如:proxy_cache_key "$host$request_uri$args";),攻击者篡改 Host 头就能让完全不同的域名共享同一缓存条目。
- 正常请求:Host: api.example.com → 缓存 key 包含 api.example.com → 存入正确响应
- 恶意请求:Host: evil.com → 同一 key 被复用 → 缓存被覆盖为 evil.com 的响应
- 后果:后续所有访问 api.example.com 的用户,可能收到 evil.com 的 HTML、JS 或重定向
Cache-Control / Set-Cookie 头绕过缓存控制
Nginx 默认遵循后端返回的缓存响应头。若后端未严格校验请求来源,就根据 Host 或 Referer 动态返回 Cache-Control: public, max-age=3600,攻击者可诱导其为恶意路径生成“可缓存”响应。
- 后端逻辑缺陷:对 Host: attacker.com 返回带 public 的响应头,而该响应本应仅限内部调用
- Nginx 默认行为:
proxy_ignore_headers Cache-Control未启用 → 该响应被缓存 - 风险点:敏感接口(如登录态检查、管理页)若被错误标记为 public,将进入共享缓存
自定义头参与 key 计算时的风险放大
为支持多租户或灰度发布,常把 $http_x_tenant_id 或 $http_x_version 加入 cache key。一旦这些 header 可被客户端伪造且服务端未做白名单校验,缓存隔离即失效。
- 安全做法:只信任经 Nginx 自身设置或可信上游注入的 header(如 via auth_request 模块注入)
- 危险做法:直接使用
$http_x_user_role作为 key 组成部分,而该 header 完全由前端 JavaScript 添加 - 后果:普通用户发送
X-User-Role: admin,可能命中并缓存管理员页面,泄露给他人
防御关键:缓存逻辑与请求头解耦
真正稳固的缓存策略,应让缓存 key 和缓存决策尽量脱离不可信输入。
- 禁用
$host、$http_host、$http_user_agent等易伪造变量参与 key 构造 - 对必须使用的业务 header(如租户 ID),在 location 块中用 map 指令做白名单映射,非法值统一转为 default
- 显式配置
proxy_ignore_headers Cache-Control Expires Set-Cookie,由 Nginx 统一控制缓存生命周期 - 所有对外暴露的缓存入口,强制设置
proxy_cache_valid 200 201 301 302 10m,不依赖后端响应头











