Valve · Report #584603
RCE on CS:GO client using unsanitized entity ID in EntityMsg message
Summary
Title: RCE on CS:GO client using unsanitized entity ID in EntityMsg message Scope: csgo.exe Weakness: Out-of-bounds Read Severity: Critical (9.6) Link: https://hackerone.com/reports/584603 Date: 2019-05-19 17:49:21 +0000 By: @chaynik
Details: Vulnerability
CSVCMsg_EntityMsg message is used by server to notify client about generic actions regarding entities. The message is described using the following Protocol Buffer:
message CSVCMsg_EntityMsg {
optional int32 ent_index = 1;
optional int32 class_id = 2;
optional bytes ent_data = 3;
}
The pseudocode of function handling this message:
void ProcessEntityMessage(CSVCMsg_EntityMsg *msg) {
IClientNetworkable *entity = entitylist->GetClientNetworkable(msg->ent_index);
if (entity) {
...
entity->ReceiveMessage(...);
...
}
...
}
Neither handler nor GetClientNetworkable check if entity index is valid - an arbitrary integer can be passed. This can lead to memory access outside of entity list and then to virtual function call on invalid object. By careful manipulation it can be used to divert control flow to attacker's payload.
Exploitation
The exploit is based on assumption that client_panorama.dll base address is known to the attacker. It can be procured using additional memory disclousure vulnerability, like #581774. Alternatively, in case of distributed attack guessing address may be viable (32-bit ASLR has low entropy).
The first stage is to find a variable with known address that can be controlled by server. For example, I chose to use map name because its copy is stored in a global variable somewhere in client_panorama.dll. Note that it's expected behavior and not a vulnerability.
Then I crafted a payload containing ROP chain and fake IClientNetworkable object. The payload is sent to server as map name. Obviously, map name is a string and cannot contain null characters, but there's easy way to bypass this limitation by overwriting it several times.
The final step is to use the vulnerability to trick client into executing virtual function on the fake object. Entity list is a statically allocated array inside client_panorama.dll, so the offset to the payload is constant. An appropriate entity index is calculated from the offset and message is sent.
The ROP chain goal is to run Calculator app. Luckily, client_panorama.dll imports IProcessUtils interface from tier0.dll which can be used to start processes. It simplifies ROP chain considerably.
Proof of Concept
The PoC script is demonstrating RCE capability on CS:GO client for Windows (version 13696, 2019-05-16 stable release).
- Download attached script: F492694
- Start CS:GO client
- Use a debugger to get the base address of
client_panorama.dlland setCLIENT_BASEvariable in downloaded script - Run attached Python 3 script (possibly on another host)
Note: If you run this script on the same host as client you might need to change the defaultPORT(because for some reason CS:GO client uses it). - Connect to the malicious server and wait for
calc.exeto pop up
{F492696}
Similarly as in #470520, Steam browser protocol can be used to launch an attack from web browser:
- Follow steps 1-4 as above
- Download attached HTML file (F492697) and set IP in iframe URL to malicious server
- Open downloaded HTML file and wait for
calc.exeto pop up
{F492695}
Impact
An attacker can execute arbitrary code on the computer of anyone who attempts to connect to the server. After succesful exploitation an attacker can gain control over victim's computer and do whatever they want.
The connection to the server can be initiated manually by the victim or automatically using Steam browser protocol on malicious web site.
The likelihood of victim joining the server via in-game server browser can be greatly improved by faking high player count and further social engineering. Many players sort server list by player amount.
In case of an attack from web browser many users don't need to click Open steam and this method requires no further interaction from user - connection will be initiated without confirmation (even CS:GO client will be started if it's not running).
How it was found
The write-up for this report has not been downloaded yet, or the program disclosed it without one. Read it on HackerOne.