## https://sploitus.com/exploit?id=9F947F43-03EA-5E83-B3B9-710D394C95E2
# CVE-2026-20660 PoC Bundle
This folder packages a standalone proof-of-concept for:
- CVE-2026-20660
- CFNetwork `NSGZipDecoder` path traversal via gzip FNAME
- Impact on vulnerable macOS Safari with auto-open enabled
## 1. Directory Layout
- `server.py`: Main PoC server with configurable traversal depth and target name
- `server_overwrite.py`: Focused variant writing `../../pwn.sh`
- `README.md`: Reproduction notes and operation log
## 2. Preconditions
1. Target is vulnerable macOS Safari (before 26.3 patch line).
2. Safari setting enabled:
- Preferences -> General -> Open safe files after downloading
3. You can access this host from the target browser.
## 3. Root Cause Summary
Patch diff shows `-[NSGZipDecoder filenameWithOriginalFilename:]` changed behavior:
- Old behavior: return gzip FNAME-derived name directly.
- New behavior: apply `lastPathComponent` before returning.
This blocks directory components such as `../` and absolute paths in FNAME.
## 4. Why Content-Disposition Is Not the Vector
The HTTP filename can be clean and still exploit succeeds.
- HTTP `Content-Disposition` filename: clean (example: `report.gz`)
- gzip header FNAME: malicious (example: `../../proof.txt`)
Safari-side sanitization primarily applies to HTTP-layer names, not the embedded gzip FNAME consumed by `NSGZipDecoder` in the vulnerable flow.
## 5. Quick Start
From repo root:
```bash
python3 exploit/cve-2026-20660/server.py --port 8888 --depth 2
```
Open in vulnerable Safari:
```text
http://:8888/
```
Click `Trigger depth=2`.
## 6. Validation
After triggering, verify write result on target machine:
```bash
ls -la ~/cve-2026-20660-proof.txt
cat ~/cve-2026-20660-proof.txt
```
For overwrite variant:
```bash
python3 exploit/cve-2026-20660/server_overwrite.py --port 9999
```
Then open:
```text
http://:9999/
```
Check:
```bash
ls -la ~/pwn.sh
cat ~/pwn.sh
```
## 7. Parameter Notes (`server.py`)
- `--bind`, `-b`: bind address (default `0.0.0.0`)
- `--port`, `-p`: listening port (default `8888`)
- `--depth`, `-d`: traversal depth (`../` repeat count, default `2`)
- `--name`, `-n`: target output file name
Examples:
```bash
# write to ~/proof.txt when depth matches runtime directory nesting
python3 exploit/cve-2026-20660/server.py -p 8888 -d 2 -n proof.txt
# explicit absolute path test (if resolver permits)
python3 exploit/cve-2026-20660/server.py -p 8888
# then use: /download?depth=0&fname=/tmp/proof.txt
```
## 8. Observed Behavior (Current Notes)
1. Decompression may occur in a temp directory under `~/Downloads`, so depth often needs to be >= 2 to escape into `~/`.
2. Existing target files may not be overwritten; download stack can auto-rename to avoid collisions.
3. Script payloads may appear with executable bits in observed runs; validate per build/config.
## 9. Troubleshooting
1. No write observed:
- Confirm Safari auto-open setting is enabled.
- Increase depth (`2`, `3`, `4`) and re-test.
2. File stays in Downloads:
- Depth too shallow for current decompression directory nesting.
3. Connection fails:
- Confirm host firewall and LAN reachability.
4. Target path unchanged:
- Existing filename conflict may cause renamed output.
## 10. Safety and Scope
Use only in authorized testing environments.
- Do not target systems without explicit permission.
- Keep payloads non-destructive for reproducibility.
- Store screenshots/logs for assessment evidence.
## 11. Suggested Evidence Collection
1. Safari version and OS build screenshot.
2. PoC server console logs (request + FNAME).
3. Filesystem verification commands and output.
4. Before/after directory listing for target path.
## 12. Related Documents in Repo
- `blog.cve-2026-20660.md`: full analysis and root cause narrative
- `log.md`: ongoing research timeline and checkpoints