bitbcybr/way2poc_cve-2026-34475
GitHub: bitbcybr/way2poc_cve-2026-34475
针对 Varnish Cache CVE-2026-34475 的两阶段 Nuclei 检测模板,通过被动指纹识别和主动行为验证判断目标是否受影响,无需触发漏洞即可完成评估。
Stars: 0 | Forks: 0
# way2poc_cve-2026-34475
CVE-2026-34475 — Nuclei 检测模板
## **正如一些人试图表现得超级聪明一样。VSV00018 · Varnish Cache req.url 处理不当 · CVSS 5.4 (中危)**
## 概述
如果有人能写出真正的漏洞利用脚本那就太好了,但其潜在攻击面仅限于路径为 `/` 的“根”URL,例如 megacorpexample.com/ —— 而不是 megacorpexample.com/whatever。这是一个非常狭窄的条件。CISA 将该漏洞评估为当前未被利用、不可自动化,且仅具有部分技术影响。
本仓库包含用于对可能受 CVE-2026-34475 影响的系统进行**被动检测和主动验证**的 [Nuclei](https://github.com/projectdiscovery/nuclei) 模板。
### 什么是 CVE-2026-34475?
在某些配置中,当 HTTP/1.1 请求以根路径(`/`)到达时,Varnish Cache 会对内部变量 `req.url` 处理不当。具体来说:如果 `req.url` 在未经检查的情况下被传递给接受*绝对形式 URI* 的后端(例如,使用 `GET https://example.com/ HTTP/1.1` 而不是 `GET / HTTP/1.1`),攻击者可以利用这一点进行**缓存投毒**或**身份验证绕过**。
攻击面仅限于根 URL —— 像 `/api/users` 这样的路径**不受**影响。
**官方参考:**
- [VSV00018 — varnish-cache.org](https://varnish-cache.org/security/VSV00018.html)
- [VSV00018 — docs.varnish-software.com](https://docs.varnish-software.com/security/VSV00018/)
- [CVE-2026-34475 — cve.org](https://www.cve.org/CVERecord?id=CVE-2026-34475)
## 受影响版本
| 产品 | 受影响 | 已修复 |
|---|---|---|
| Varnish Cache (开源版) | ≤ 8.0.0 (所有版本) | 8.0.1 |
| Varnish Cache 6.0 LTS | ≤ 6.0.16 | 6.0.17 |
| Varnish Enterprise | 6.0.x ≤ 6.0.16r11 | 6.0.16r12 |
## 检测模板的工作原理
检测模板仅发送**标准的原点形式(origin-form)HTTP 请求** —— 不会触发任何漏洞,不会发送任何被篡改的请求,也不会尝试进行任何利用。检测纯粹基于被动的 Header 分析。
### 第一步 Varnish 指纹识别
```
method: GET
path:
- "{{BaseURL}}/"
```
向目标发送一个普通的原点形式 `GET /` 请求 —— 与任何浏览器或 HTTP 客户端发送的完全一致。与常规流量无异。
### 第二步 匹配器:Varnish 是否正在运行?
```
matchers:
- type: status
status: [200, 301, 302, 403, 404]
- type: regex
part: header
regex:
- "(?i)X-Varnish:\\s*[0-9]+"
```
第一个匹配器仅检查目标是否响应。关键的匹配器是第二个:它会在响应中寻找 `X-Varnish` Header。
**为什么 `X-Varnish` 是可靠的:** Varnish 在每个传出的响应上都设置此 Header —— 它包含内部事务 ID (VXP)。这是一个可靠的指纹信号,因为它通常只由 Varnish 自身设置,除非完全将其移除,否则很难被伪造。
只有当两个匹配器都命中时,即响应存在**且**设置了 `X-Varnish` 时,模板才会触发。这可将误报率降至最低。
### 第三步 — 提取器:读取版本和缓存状态
模板从响应 Header 中提取七个值:
```
extractors:
- name: x_varnish # Transaction IDs — confirms Varnish is running
- name: server_header # May contain explicit version string
- name: via_header # Often: "1.1 varnish (Varnish/6.0)" — version info
- name: varnish_version # Regex extracts "6.0", "8.0.0" etc. directly
- name: cache_age # Age > 0 → response served from cache
- name: cache_control # Cache directives of the target
- name: x_cache # HIT/MISS status if present
```
#### `Via` Header 作为版本来源
根据 RFC 7230 规定,代理必须设置 `Via` Header,这通常包括协议和代理名称。Varnish 将其设置为以下形式:
```
Via: 1.1 varnish (Varnish/6.0)
```
正则表达式 `(?i)Varnish/([0-9]+\.[0-9]+\.?[0-9]*)` 提取版本字符串,可以直接将其与上述受影响版本表进行匹配比对。
#### `Server` Header 作为备用方案
某些 Varnish 部署会显式地将 `Server` Header 设置为 `Varnish`,或者包含版本字符串。提取器会捕获其完整值,例如:
```
Server: Varnish/8.0.0
```
#### `Age` Header 作为缓存指示器
`Age` 表示缓存响应已在缓存中保存了多少秒。值 > 0 表明 Varnish 正在积极缓存响应 —— 这与缓存投毒攻击向量相关。
## 解读结果
### 场景 A 版本清晰可读
提取器返回具体的版本字符串(例如,通过 `Via` Header 获取的 `6.0.14`):
- 版本在受影响范围内? → **存在漏洞,需要立即采取行动**
- 版本高于已修复版本? → **不受影响**
### 场景 B 检测到 Varnish,但版本不可读
存在 `X-Varnish` Header,但 `Via` 和 `Server` 都未能提供版本信息。这在经过加固的部署中很常见(通过自定义 VCL 规则剥离 Header)。
在这种情况下:**将其视为可能受影响**,并直接在服务器上检查版本:
```
varnishd -V
```
### 场景 C 无匹配
模板未触发。这要么意味着目标上没有运行 Varnish,要么 `X-Varnish` 已从响应中被完全移除。后者比较少见,因为该 Header 是由 Varnish 在内部设置的,移除它需要显式的 VCL 配置。
## 三阶段工作流
检测被有意划分为两个具有不同精度级别和活动特征的模板,随后是一个手动的白盒步骤。
```
┌─────────────────────────────┐
│ Stage 1: detect.yaml │ Passive. Header analysis only.
│ Detects: Varnish present │ No unusual traffic generated.
│ + version if readable │
└────────────┬────────────────┘
│ Match → Varnish running, version potentially affected
▼
┌─────────────────────────────┐
│ Stage 2: verify.yaml │ Active. Sends absolute-form request.
│ Checks: cache-key collision│ Visible in server logs.
│ between origin-form and │ Authorized targets only.
│ absolute-form request │
└────────────┬────────────────┘
│ Match → strong indicator of exploitable configuration
▼
Stage 3: Whitebox VCL inspection
(bereq.url = req.url without sanitization?)
```
### 为什么需要两个模板?
仅靠 HTTP Header 无法可靠地确定某个实例是否真的可被利用。该漏洞需要同时满足两个条件:
1. **受影响的版本**(< 8.0.1) —— 如果未加固,可从 Header 中读取
2. **VCL 未经检查地将 `req.url` 传递给后端** —— 无法从外部直接观察
检测模板尽可能地处理条件 1。验证模板通过检查 Varnish 是否将绝对形式和原点形式的请求映射到相同的缓存键来近似判断条件 2 —— 这是缺少 `req.url` 规范化的强烈指标。最终确认需要对 VCL 配置进行白盒访问。
## 用法
### 阶段 1 检测(被动)
```
# 单一目标
nuclei -t cve-2026-34475-detect.yaml -u https://target.example.com
# 目标列表
nuclei -t cve-2026-34475-detect.yaml -l targets.txt
# 带有 extractor 输出(版本信息可见)
nuclei -t cve-2026-34475-detect.yaml -u https://target.example.com -v
# JSON 输出
nuclei -t cve-2026-34475-detect.yaml -l targets.txt -json -o results.json
```
### 阶段 2 行为比较(主动,仅限授权目标)
```
# 单一目标 — 仅在检测到阳性结果之后
nuclei -t cve-2026-34475-verify.yaml -u https://target.example.com -v
# 按顺序执行两个 templates
nuclei -t cve-2026-34475-detect.yaml -t cve-2026-34475-verify.yaml \
-u https://target.example.com -v
```
## 阶段 3 白盒 VCL 评估
在验证结果为阳性后,直接在服务器上检查 VCL 配置。必须同时满足以下三个条件,实例才能真正被利用。
### 条件 1 `req.url` 未经清理即被传递
```
# VULNERABLE:在使用 req.url 前未进行前缀检查
sub vcl_recv {
set req.http.X-Forwarded-Path = req.url;
}
sub vcl_backend_fetch {
set bereq.url = req.url; # absolute-form reaches the backend
}
```
```
# SAFE:官方变通方案拒绝 absolute-form requests
sub vsv18 {
if (req.method == "CONNECT") { return; }
if (req.url == "*" && req.method == "OPTIONS") { return; }
if (req.url !~ "^/") { return (synth(400)); }
}
sub vcl_recv { call vsv18; }
```
**需要寻找的内容:** `vcl_recv` 或 `vcl_backend_fetch` 中任何设置 `req.url` 或 `bereq.url`,或者将其作为路由基础的位置 —— 并且之前没有 `!~ "^/"` 检查。
### 条件 2 后端接受绝对形式 URI
仅靠 Varnish 是不够的 —— 后端也必须处理绝对形式的 URI。各后端的典型风险概况:
| 后端 | 风险 | 备注 |
|---|---|---|
| Apache (ProxyPass) | 高 | 在许多配置中接受绝对形式 |
| Node.js / Express | 高 | 直接解析 `req.url`,无自动检查 |
| Java (Jetty, Tomcat) | 中 | 历史上对绝对形式比较宽容 |
| nginx | 低 | 默认拒绝绝对形式 |
**验证方法:** 向后端端口发送直接的绝对形式请求(绕过 Varnish) —— 如果后端返回 200 而不是 400,则说明它接受绝对形式 URI。
### 条件 3 缓存键未规范化 `req.url`
```
# VULNERABLE:应用了 Varnish default key,req.url 未标准化
# → absolute-form 和 origin-form 可能生成不同的 key
# 或 — 取决于 Varnish 版本 — 在同一个 key 上发生冲突
# SAFE:从 req.url 中剥离 schema+host 的显式 cache key
sub vcl_hash {
hash_data(regsub(req.url, "^https?://[^/]+", ""));
hash_data(req.http.host);
return (lookup);
}
```
**需要寻找的内容:** `vcl_hash` 是否包含可规范化 `req.url` 的显式 `hash_data()` 调用?如果没有,则适用 Varnish 的默认设置 —— 而该默认设置在受影响版本中是存在漏洞的。
### VCL 检查清单
| 检查项 | 子项 | 漏洞条件... |
|---|---|---|
| `req.url` 使用 | `vcl_recv` | 不存在 `!~ "^/"` 检查 |
| `bereq.url` 赋值 | `vcl_backend_fetch` | 直接从 `req.url` 赋值而未作转换 |
| Hash 基础 | `vcl_hash` | `req.url` 在未规范化的情况下用于 `hash_data()` |
| 基于 Host 的路由 | `vcl_recv` | 路由决策基于 `req.url` 而不是 `req.http.host` |
| 内置 VCL 版本 | — | 修复前的内置 VCL 不包含 `^/` 检查 |
### 可利用性矩阵
```
Condition 1 (req.url unchecked)
+
Condition 2 (backend accepts absolute-form)
+
Condition 3 (cache key not normalized)
= Cache Poisoning exploitable
Condition 1 (req.url unchecked)
+
Condition 2 (backend makes auth decisions based on host in req.url)
= Authentication Bypass exploitable
```
一旦确认了所有相关条件,即可确立可利用性 —— 而无需执行主动漏洞利用。这是授权评估在方法论上最严谨的结论。
## 资源
- [Nuclei 文档](https://docs.projectdiscovery.io/tools/nuclei/overview)
- [Varnish VCL 参考](https://varnish-cache.org/docs/trunk/reference/vcl.html)
- [CWE-180:不正确的行为顺序 — 在规范化之前进行验证](https://cwe.mitre.org/data/definitions/180.html)
- [RFC 7230 — HTTP/1.1 消息语法(绝对形式)](https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.2)
标签:C2日志可视化, CISA项目, CVE-2026-34475, HTTP/1.1, Nuclei模板, Varnish Cache, VCL配置检查, VSV00018, Web缓存欺骗, 主动侦察, 加密, 密码管理, 指纹识别, 插件系统, 漏洞扫描器, 缓存中毒, 缓存键碰撞, 网络安全, 认证绕过, 隐私保护