# A Crash, Not a Shell: SolarWinds Serv-U CVE-2026-28318

Unauthenticated POST with Content-Encoding: deflate reaches Serv-U's decompressor, triggering invalid free() and process abort; heap corruption proven non-exploitable for RCE.

- Payout: Research
- Severity: high
- Program: SolarWinds
- Write-up by: Bishop Fox
- Disclosed: 2026-06-16
- CVE: CVE-2026-28318
- Write-up quality: 8/10
- Original: https://bishopfox.com/blog/a-crash-not-a-shell-solarwinds-serv-u-cve-2026-28318
- Library page: https://bugbountylibrary.com/r/blog%3Abishopfox-com-blog-a-crash-not-a-shell-solarwinds-serv-u-cve-2026-28318
- Tags: area:cloud domain:infra impact:dos kind:research platform:research sev:high tech:windows technique:reverse-engineering technique:source-review vuln:dos vuln:memory-corruption

**Target:** Serv-U web interface HTTP request handler / in-memory decompressor
**Root cause:** The deflate-rejection check only runs when HTTP compression is disabled, but compression is enabled by default, so deflate bodies reach the decompressor. Its buffer management performs an invalid free(), and the hardened allocator aborts the process.
**Steps:**
1. Send an unauthenticated `POST` to the Serv-U web interface with header `Content-Encoding: deflate` and any non-empty body (need not be valid compressed data).
2. The deflate-rejection check is skipped because compression is enabled by default.
3. Body is fed to the in-memory decompressor, which frees a pointer it should not.
4. Hardened allocator detects corruption and aborts the Serv-U process.
**How found:** Reverse engineered vulnerable and patched builds to confirm root cause; noted SolarWinds' hint that the feature 'is not required by the service,' then examined the HF1 fix and found it adds a universal 415 gate for any body with non-empty Content-Encoding rather than repairing the decompressor.
**Exploitation:** Single unauthenticated request kills the service reliably; no RCE achieved. Three RCE paths (arbitrary-address free, fake adjacent block, counter overflow) were tested against a live server and all dead-ended due to an impossibly large size value and a counter that drives both allocation and copy.
**Insight:** When a vendor fix adds a blanket rejection gate instead of patching the vulnerable component, that gate's differential response (415 vs normal handling) is a safe, non-crashing fingerprint for detection; also, a counter that drives both allocation size and copy length will always fail together, killing overflow-based RCE.

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

**Unauthenticated deflate POST crash trigger**

```
A POST request with Content-Encoding: deflate feeds its body content into an in-memory decompressor whose buffer management performs an invalid free(), and the hardened system allocator responds by aborting the whole process. A body must be present, but it does not have to be valid compressed data.
```

**Safe detection probe using identity encoding**

```
Send a POST with a body and a harmless encoding such as identity, and a patched server answers 415 while a vulnerable server handles the request normally and stays up. Because the probe never sends deflate, it never reaches the decompressor and never risks the crash. That single behavioral difference is what our detection check keys on.
```

