Full Report
CS:GO is a popular online game from 2012 with many public servers. Mods, textures, 3D models and more all create a great attack surface. The source engine has it's own TCP-like network stack over UDP. Reversing this game is interesting. Debug symbols were accidentally put into the MacOS version in 2017, making it easier to learn about. Additionally, there are many public exploits, cheating communities and more which offer good resources. They found a custom CS:GO server written in Python, which was useful for attacking. The server takes in commands. There are some commands that only work locally and/or with a single user playing. Whether this is the case is controlled by the user controllable value m_nMaxClients. Using this, an attacker can execute privileged commands on the server, such as quit. Source engine servers (what this game was built on) can send additional game files to the client via HTTP. When asking for a file, there is validation done on the end of the file on the type. However, when this is copied into a buffer, it's done by snprintf, which will truncate the string. So, we can bypass the filter! One of the privileged commands con_logfile writes to an arbitrary *.log file. This suffered from the same snprintf truncation issue, but on a write. This gave them an arbitrary file write vulnerability. The service validates DLLs. However, it falls back to an insecure mode so that it can boot if there's an issue. Additionally, this can be replicated with the -insecure flag. Using this flag, DLLs from outside the bin/ directory too. There are several logic vulnerabilities here. How can we take this to code execution? Use the arbitrary file download to download a malicious DLL to be used later. Corrupt one of the DLLs. This will trigger the fallback mode to search for DLLs in a different location. Replace the gameinfo.txt so that the malicious DLL is loaded on start up. All Source Engine games are just add ons to Half Life so this is common. Use the privileged command bypass to reboot the server. On start up, the malicious DLL will be loaded because of the fallback mechanism. Valve requires a real PoC in order to prove impact for RCE. Although they found these bugs individually and quite quickly, it took them a while to chain everything together. Each bug gave them 7.5K, which is quite a bit. Overall, good report on interesting logic bugs.
Analysis Summary
# Vulnerability: Chained Logic Bugs Leading to RCE in CS:GO Client via Malicious Server
## CVE Details
- CVE ID: **Not explicitly mentioned in the summary, but addressed in the 04/28/2021 patch.**
- CVSS Score: **N/A (Not provided in context)**
- CWE: **Multiple, including CWE-20 (Improper Input Validation), CWE-113 (Improper Neutralization of Special Elements in Output Used by a Web Query), and CWE-427 (Uncontrolled Search Path Element)**
## Affected Systems
- Products: **Counter-Strike: Global Offensive (CS:GO)**, running on the **Source Engine**.
- Versions: **Versions prior to the patch dated 04/28/2021.**
- Configurations: The initial attack vector requires a client to connect to a **maliciously controlled CS:GO server** (specifically, a custom server written in Python was used in the research). The RCE chain relies on specific game logic interactions, including server commands and file serving mechanism.
## Vulnerability Description
The research identified a chain of four independent logic bugs that, when chained utilizing a custom attacker-controlled server, lead to Remote Code Execution (RCE) on the connecting client.
**Bug 1: Privileged Command Execution Bypass:** An attacker can execute privileged server commands (e.g., `quit`) by manipulating the user-controllable value `m_nMaxClients` in the custom server implementation.
**Bug 2: Arbitrary File Download (Bypassing Filter):** The Source Engine server's HTTP file serving mechanism validates file types but uses `snprintf` to copy the filename buffer. This function truncates the string, allowing an attacker to bypass the file extension validation filter and trick the client into downloading an arbitrary file.
**Bug 3: Arbitrary File Write:** The `con_logfile` command, which writes to an arbitrary `*.log` file, suffers from the same `snprintf` truncation issue during the file write operation. This results in an **Arbitrary File Write (AFW)** vulnerability on the client system.
**Bug 4: Insecure DLL Loading Fallback:** The client validates DLLs but falls back to an insecure mode to boot if validation fails. Furthermore, using the `-insecure` flag allows loading DLLs from outside the standard `bin/` directory. This fallback can be triggered by corrupting a legitimate DLL (e.g., using the AFW from Bug 3 to overwrite a DLL).
**The RCE Chain:**
1. Use Bug 1 to trigger a server reboot command via the custom server connection.
2. Use Bug 2 to download a malicious DLL payload to the client system.
3. Use Bug 3 (AFW) to corrupt a legitimate client DLL, triggering Bug 4's insecure fallback mode on startup.
4. Modify `gameinfo.txt` (exploiting Source Engine's modular structure) to point to the downloaded malicious DLL location.
5. The server reboot (Step 1) causes the client to restart, loading the malicious DLL via the insecure fallback mechanism, resulting in RCE.
## Exploitation
- Status: **Proof of Concept (PoC) available.** The researchers successfully chained these bugs into a working RCE exploit triggered solely by client connection to a malicious server.
- Complexity: **High.** While individual bugs were found quickly, chaining them together required significant reverse engineering and logic analysis regarding Source Engine startup processes.
- Attack Vector: **Network.** The attack is initiated remotely by connecting the client to a malicious server.
## Impact
- Confidentiality: **Total.** RCE allows access to all data on the compromised client machine.
- Integrity: **Total.** RCE allows arbitrary code execution and modification of system files.
- Availability: **Total.** RCE allows for system disruption or service termination (if the server reboot was targeted at the server, though the focus of the PoC was client RCE).
## Remediation
### Patches
- Valve released a patch addressing several critical vulnerabilities, including these three, on **04/28/2021**. Users must update to this version or newer to mitigate the identified flaws.
### Workarounds
- **Avoid connecting to untrusted community servers.** Since the exploit vector is connection to a malicious server, sticking to trusted environments significantly reduces risk.
- **Do not run CS:GO with the `-insecure` flag** unless absolutely necessary, as this flag explicitly enables a component of the final RCE chain.
## Detection
- **Network Indicators:** Unexpected outbound traffic originating from the CS:GO client or unusual communication patterns with non-standard game servers or unauthenticated HTTP requests for game files.
- **File System Changes:** Look for unexpected modifications or corruption of core game DLL files within the CS:GO installation directory, or suspicious entries in `gameinfo.txt` after a server interaction.
- **Runtime Monitoring:** Detection of unauthorized processes spawned by `csgo.exe` following a connection event.
## References
- Vendor Advisory: [CS:GO Patch Notes - April 28, 2021 (Defanged Blog)](https://blog.counter-strike.net/index.php/2021/04/33895/)
- Research Publication: [Neodyme Blog Post (Defanged)](https://neodyme.io/en/blog/csgo_from_zero_to_0day)