Two OOB Reads in Source Engine resulting in Full-Chain RCE

We discussed this vulnerability during Episode 76 on 11 May 2021

Interesting post that covers a bit about the meta of bug-hunting in Source Engine games and some how-to information. There are two OOB read vulnerabilities used in the chain.

First vulnerability is an OOB read which allows you to return a pointer for an IClientNetworkable object. This is just due to an unchecked (checked by asserts that are compiled out in prod builds) user-provided index. A function is called based on this pointer for eip control.

The next step is to create a fake object, which is done using a ConVar which just allows the server to set arbitrary variables on the client with whatever content they want. This is also in the globals section so it doesn’t move around.

In order to fully exploit this and build a ROP chain without depending on a dll that has no ASLR (xinput) so it will impact all source games an infoleakwas also necessary. There was a bug in the handling of pakfiles. First pakfiles (zip) can be provided by the server (as part of a map as I understand it) and act as a sort of overlay. Its zip. When a file is request, the game will check if it exists inside the pakfile and retrieve it from there if it does.

The vulnerability is that when the server requests the client upload a file, it will also respect the pakfile, which is noted as somewhat odd behavior since the pakfile comes from the server. The game will determine if the file it too large to send by reading the signed size out of the zip header, and doing a signed comparison. So a negative size will pass the check, but when actually reading the file will result in an over-read.