# CC-Tweaked has an SSRF Protection Bypass with NAT64

CC-Tweaked's HTTP SSRF filter misses the NAT64 well-known prefix, letting Lua code reach internal IPv4 services via 64:ff9b:: addresses on NAT64 networks.

- Payout: Research
- Severity: high
- Program: CC-Tweaked
- Found by: JLLeitschuh
- Disclosed: 2026-05-29
- CVE: CVE-2026-47695
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-5jh9-2h63-pw4q
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-5jh9-2h63-pw4q
- Tags: area:oss domain:oss impact:internal-access kind:research platform:ghsa sev:high tech:java technique:incomplete-fix technique:source-review vuln:ssrf

**Target:** Java HTTP API IP filter (http.request/http.websocket) in CC-Tweaked core
**Root cause:** PrivatePattern.matches() relies on Java InetAddress classification methods that return false for NAT64 64:ff9b::/96 addresses, and the existing 6to4 (2002::/16) mitigation doesn't cover the NAT64 prefix.
**Steps:**
1. Confirm server has IPv6, a NAT gateway, and route `64:ff9b::/96 → NAT Gateway`
2. Encode target internal IPv4 a.b.c.d as `64:ff9b::<hex(a)><hex(b)>:<hex(c)><hex(d)>`
3. Run Lua: `local res = http.request("http://[64:ff9b::0a00:0111]:8888/")`
4. Read response via `res.readAll()` — filter passes, NAT64 translates to 10.0.1.17:8888
**How found:** Code review of the IP filter: noticed it depends on Java's built-in InetAddress classifiers, then checked whether IPv6 transition prefixes embedding IPv4 (NAT64 64:ff9b::/96) are recognized — they aren't, and only 6to4 was previously mitigated.
**Exploitation:** Attacker with Lua execution on a CC-Tweaked computer issues http.request to a NAT64-encoded internal IPv4 address; the filter accepts the Inet6Address, the network's NAT64 gateway extracts the embedded IPv4 and forwards the TCP connection to the internal service, returning its response to the attacker.
**Escalation:** On cloud IPv6-only subnets (AWS/GCP/Azure) with NAT64, reach other VPC instances, internal databases, and cloud management APIs.
**Insight:** When an SSRF filter delegates to language-runtime address classifiers, enumerate IPv4-embedding IPv6 transition prefixes (NAT64 64:ff9b::/96, 6to4, Teredo, IPv4-mapped) — each is a separate bypass unless explicitly blocked.

## Proof of concept (copied exactly from the original report)

**Lua http.request to NAT64-encoded internal IP**

```
local res = http.request("http://[64:ff9b::0a00:0111]:8888/")
if res then print(res.readAll()) end
```

