## https://sploitus.com/exploit?id=638CA901-49ED-594C-BD8A-656389B1155C
# way2poc_cve-2026-34475
CVE-2026-34475 β Nuclei Detection Templates
> Two-stage Nuclei detection for CVE-2026-34475: fingerprint vulnerable Varnish instances, verify cache-key collision behavior, and confirm exploitability via VCL inspection β without triggering the bug.
**As some tried to make themselves super-smart. VSV00018 Β· Varnish Cache req.url Mishandling Β· CVSS 5.4 (Medium)**
** It would be nice if someone gets to a real exploit script but the potential attack surface is limited to "root" URLs with a path of /, such as https://megacorpexample.com/ β but not https://megacorpexample.com/whatever. That is a very narrow condition. CISA rates the vulnerability as currently not exploited, not automatable, and with only partial technical impact.**
---
## Overview
This repository contains [Nuclei](https://github.com/projectdiscovery/nuclei) templates for **passive detection and active verification** of systems potentially affected by CVE-2026-34475.
### What is CVE-2026-34475?
In certain configurations, Varnish Cache mishandles the internal variable `req.url` when HTTP/1.1 requests arrive with a root path (`/`). Specifically: if `req.url` is passed unchecked to a backend that accepts *absolute-form URIs* (e.g. `GET https://example.com/ HTTP/1.1` instead of `GET / HTTP/1.1`), an attacker can leverage this for **cache poisoning** or **authentication bypass**.
The attack surface is limited to root URLs β paths like `/api/users` are **not** affected.
**Official references:**
- [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://vulners.com/cve/CVE-2026-34475)
---
## Affected Versions
| Product | Affected | Fixed |
|---|---|---|
| Varnish Cache (Open Source) | β€ 8.0.0 (all releases) | 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 |
---
## How the Detection Template Works
The detect template sends only **standard origin-form HTTP requests** β no vulnerability is triggered, no manipulated request is sent, no exploitation is attempted. Detection is based purely on passive header analysis.
### Step 1 β Varnish Fingerprinting
```yaml
method: GET
path:
- "{{BaseURL}}/"
```
A plain `GET /` request is sent to the target in origin-form β exactly as any browser or HTTP client would send it. Indistinguishable from regular traffic.
### Step 2 β Matcher: Is Varnish Running?
```yaml
matchers:
- type: status
status: [200, 301, 302, 403, 404]
- type: regex
part: header
regex:
- "(?i)X-Varnish:\\s*[0-9]+"
```
The first matcher simply checks that the target responds. The key matcher is the second: it looks for the `X-Varnish` header in the response.
**Why `X-Varnish` is reliable:** Varnish sets this header on every outgoing response β it contains the internal transaction ID (VXP). It is a dependable fingerprint signal since it is typically only set by Varnish itself and cannot easily be spoofed without removing it entirely.
The template only fires when both matchers hit β response present **and** `X-Varnish` set. This keeps false positives to a minimum.
### Step 3 β Extractors: Reading Version and Cache State
The template extracts seven values from response headers:
```yaml
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 as Version Source
Per RFC 7230, proxies are required to set the `Via` header, which typically includes the protocol and proxy name. Varnish sets it in the form:
```
Via: 1.1 varnish (Varnish/6.0)
```
The regex `(?i)Varnish/([0-9]+\.[0-9]+\.?[0-9]*)` extracts the version string, which can be matched directly against the affected versions table above.
#### `Server` Header as Fallback
Some Varnish deployments explicitly set the `Server` header to `Varnish` or include a version string. The extractor captures the full value, e.g.:
```
Server: Varnish/8.0.0
```
#### `Age` Header as Caching Indicator
`Age` indicates how many seconds a cached response has been in the cache. A value > 0 confirms that Varnish is actively caching responses β relevant to the cache poisoning attack vector.
---
## Interpreting Results
### Scenario A β Version Clearly Readable
Extractors return a concrete version string (e.g. `6.0.14` via the `Via` header):
- Version in the affected range? β **Vulnerable, immediate action required**
- Version above the fixed releases? β **Not affected**
### Scenario B β Varnish Detected, Version Not Readable
`X-Varnish` header is present, but neither `Via` nor `Server` yield a version. This is common in hardened deployments (header stripping via custom VCL rules).
In this case: **treat as potentially affected** and check the version directly on the server:
```bash
varnishd -V
```
### Scenario C β No Match
The template does not fire. Either Varnish is not running on the target, or `X-Varnish` has been fully removed from responses. The latter is uncommon since the header is set internally by Varnish and removing it requires explicit VCL configuration.
---
## Three-Stage Workflow
Detection is intentionally split across two templates with different precision levels and activity footprints, followed by a manual whitebox step.
```
βββββββββββββββββββββββββββββββ
β 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?)
```
### Why Two Templates?
HTTP headers alone cannot reliably determine whether an instance is actually exploitable. The vulnerability requires two conditions to be true simultaneously:
1. **Affected version** ( **Notice:** Both templates must only be used against systems for which explicit written authorization exists. The verify template generates traffic that will be visible in server logs.
---
## Stage 3 β Whitebox VCL Assessment
After a positive verify result, inspect the VCL configuration directly on the server. Three conditions must all be true for an instance to be actually exploitable.
### Condition 1 β `req.url` is Passed Without Sanitization
```vcl
# VULNERABLE: no prefix check before using 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
}
```
```vcl
# SAFE: official workaround rejects 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; }
```
**What to look for:** Any location in `vcl_recv` or `vcl_backend_fetch` where `req.url` or `bereq.url` is set or used as a routing basis β without a prior `!~ "^/"` check.
### Condition 2 β The Backend Accepts Absolute-Form URIs
Varnish alone is not sufficient β the backend must also process the absolute-form URI. Typical risk profile by backend:
| Backend | Risk | Notes |
|---|---|---|
| Apache (ProxyPass) | High | Accepts absolute-form in many configurations |
| Node.js / Express | High | Parses `req.url` directly, no automatic check |
| Java (Jetty, Tomcat) | Medium | Historically tolerant of absolute-form |
| nginx | Low | Rejects absolute-form by default |
**Verification method:** Send a direct absolute-form request to the backend port (bypassing Varnish) β if the backend responds with 200 instead of 400, it accepts absolute-form URIs.
### Condition 3 β Cache Key Does Not Normalize `req.url`
```vcl
# VULNERABLE: Varnish default key applies, req.url not normalized
# β absolute-form and origin-form may produce different keys
# or β depending on Varnish version β collide on the same key
# SAFE: explicit cache key that strips schema+host from req.url
sub vcl_hash {
hash_data(regsub(req.url, "^https?://[^/]+", ""));
hash_data(req.http.host);
return (lookup);
}
```
**What to look for:** Does `vcl_hash` contain an explicit `hash_data()` call that normalizes `req.url`? If not, the Varnish default applies β and that default is vulnerable in affected versions.
### VCL Inspection Checklist
| Check | Sub | Vulnerable if... |
|---|---|---|
| `req.url` usage | `vcl_recv` | No `!~ "^/"` check present |
| `bereq.url` assignment | `vcl_backend_fetch` | Assigned directly from `req.url` without transformation |
| Hash basis | `vcl_hash` | `req.url` used in `hash_data()` without normalization |
| Host-based routing | `vcl_recv` | Routing decisions based on `req.url` instead of `req.http.host` |
| Built-in VCL version | β | Pre-fix built-in VCL contained no `^/` check |
### Exploitability Matrix
```
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
```
Once all relevant conditions are confirmed, exploitability is established β without executing an active exploit. This is the methodologically clean conclusion of an authorized assessment.
---
## Mitigation
### Option 1 β Upgrade (recommended)
Upgrade to a fixed version per the affected versions table above.
### Option 2 β VCL Workaround
If an immediate upgrade is not possible, the following VCL snippet provides protection:
```vcl
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;
}
```
This snippet rejects all requests where `req.url` does not begin with `/` β i.e. all absolute-form URIs. It must be placed at the top of the VCL so it runs before any other `vcl_recv` logic.
The workaround is confirmed safe by the official advisory and has since been incorporated into the built-in VCL as a forward-looking precaution.
---
## Template Limitations
### detect.yaml
- **No version β no certainty:** If `Via` and `Server` headers contain no version information, the template only establishes: *Varnish is running here.* Check the version directly on the server (`varnishd -V`).
- **Header stripping:** Deployments that remove `X-Varnish` via VCL (`unset resp.http.X-Varnish`) will not be detected β even if Varnish is active. These setups typically have additional hardening measures in place.
### verify.yaml
- **Nuclei cannot compare cross-request values natively:** The cache HIT indicator (two IDs in `X-Varnish`) only works if the baseline request was actually cached before the absolute-form request arrives. Very short TTLs or `no-store` policies will prevent the comparison from firing.
- **Not proof of exploitability:** Even a cache key collision does not prove that an attacker can inject malicious content. That requires confirming that `req.url` is passed to a backend that accepts absolute-form β which requires whitebox access.
- **Timing-dependent:** Cache entries may expire between request 1 and request 2. With very short TTL values, consider using `-rate-limit 1` and manually checking the time delta.
---
## Files
| File | Stage | Type | Description |
|---|---|---|---|
| `cve-2026-34475-detect.yaml` | 1 | Passive | Varnish fingerprint + version check |
| `cve-2026-34475-verify.yaml` | 2 | Active | Cache-key collision test via absolute-form |
| `README.md` | 3 | Whitebox | VCL inspection checklist for manual assessment |
---
## Resources
- [Nuclei Documentation](https://docs.projectdiscovery.io/tools/nuclei/overview)
- [Varnish VCL Reference](https://varnish-cache.org/docs/trunk/reference/vcl.html)
- [CWE-180: Incorrect Behavior Order β Validate Before Canonicalize](https://cwe.mitre.org/data/definitions/180.html)
- [RFC 7230 β HTTP/1.1 Message Syntax (absolute-form)](https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.2)