# Enterprise Tech In, Shell Out (Progress Kemp LoadMaster Uninitialized Heap to Pre-Auth RCE CVE-2026-8037)

Uninitialized, non-null-terminated escape_quotes() buffer in Kemp LoadMaster's /accessv2 lets unauthenticated attackers smuggle shell commands into system() for pre-auth RCE.

- Payout: Research
- Severity: critical
- Program: Progress
- Found by (vendor credit): Jacky Yang and Syed Ibrahim Ahmed of TrendAI Research
- Write-up by: Sina Kheirkhah (@SinSinology)
- Disclosed: 2026-06-29
- CVE: CVE-2026-8037
- Write-up quality: 8/10
- Original: https://labs.watchtowr.com/enterprise-tech-in-shell-out-progress-kemp-loadmaster-uninitialized-heap-to-pre-auth-rce-cve-2026-8037/
- Library page: https://bugbountylibrary.com/r/blog%3Alabs-watchtowr-com-enterprise-tech-in-shell-out-progress-kemp-loadmaster-uninitialized-heap-to-pre-auth-rce-cve-2026-803
- Tags: area:devices domain:network impact:rce kind:research platform:research sev:critical tech:rest technique:incomplete-fix technique:source-review vuln:auth-bypass vuln:command-injection vuln:memory-corruption vuln:rce

**Target:** /accessv2 JSON API endpoint (apiuser/apipass)
**Root cause:** escape_quotes() allocates an uninitialized malloc buffer and never null-terminates the escaped string, so __sprintf_chk() reads past the buffer into adjacent heap memory.
**Steps:**
1. Diff 7.2.63.1 vs 7.2.63.2; only escape_quotes() changed (malloc->calloc, added null terminator).
2. Send POST /accessv2 with JSON body `{"cmd": "getall", "apiuser": "''''", "apipass": "BBBBB", "g0": "AAAAAAAAAAAAAAAA'; cat /etc/passwd #", ...}`.
3. Four single quotes expand to 16 bytes, overwriting the first 0x10 bytes (allocator metadata) of the adjacent freed chunk.
4. Spray many JSON keys (g0..g60) with value `AAAAAAAAAAAAAAAA'; cat /etc/passwd #` to land a payload chunk after the escaped apiuser buffer.
5. __sprintf_chk() reads past the unterminated buffer into the sprayed payload, building `validuser -b -u '...' -p '...'` with injected command, executed via system().
**How found:** Patch diff showed only escape_quotes() changed and no new characters were escaped, prompting suspicion. Reading the function revealed malloc without null termination; a small uninitialized-heap demo showed stale allocator metadata and sprayed data leaking into %s reads, leading to the idea of using quote expansion to overwrite metadata and spray a payload.
**Exploitation:** Unauthenticated attacker POSTs to /accessv2 with apiuser set to four single quotes and many sprayed JSON keys containing `'; <command> #`. The quote expansion erases allocator metadata in the adjacent freed chunk, and the missing null terminator causes __sprintf_chk to concatenate the sprayed payload into the command string passed to system(), yielding command execution as the appliance user.
**Insight:** When a patch only adds calloc/null-termination to a string escaper, look for a downstream %s/sprintf that trusts the terminator; quote-expansion (1 char -> 4 bytes) can be weaponized to overwrite adjacent chunk metadata and defeat null-byte truncation.

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

**Normal accessv2 request format**

```
POST /accessv2 HTTP/1.1
Accept-Encoding: gzip, deflate, br
Content-Length: 2986
Host: 192.168.5.30:443
Content-Type: application/json
Accept: */*
Connection: keep-alive

{"cmd": "getall", "apiuser": "AAAAAA", "apipass": "BBBBBB"}
```

