Allows you to crash any Windows user in any CSGO match.
- No longer works if
cl_invites_only_friends
is set to1
- No longer works in game if
cl_invites_only_mainmenu
is set to1
- Download this script including the
protobufs
folder or rungit clone --recursive https://github.com/BeepFelix/csgo-crash-exploit.git
- Generate a Steam account from here
- Rename
config.json.example
intoconfig.json
and fill it in with the generated account details - Install NodeJS
- Open a command prompt in the
csgo-crash-exploit
folder and enternpm install
- Enter
node index.js
- Follow the onscreen instructions
Panorama is a framework devloped by Valve that is heavily influenced by the modern day front-end development stack with technologies such as HTML, JS, and CSS. The Panorama framework was originally developed for DOTA 2, but later ported to CS:GO in an effort to renew the game's UI.
On top of all this, the framework's source code can be easily viewed by unzipping the csgo/panorama/code.pbin
file. With this knowledge, exploitation is as easy as looking for vulnerable lines of code also known as a whitebox audit.
Counter-Strike's lobby system is built off of an ancient technology that would not be acceptable to today's standards. This ancient system not so long ago, allowed you to join anyone's lobby, even if you were not friends. It also allows the lobby owner full permission over the lobby metadata such as players in lobby, the lobby type, the lobby location, and even player ranks. This metadata never gets sanitized on the server-side and the client is expected to handle all sanitization.
Merging the ancient lobby system and the vulnerable Panorama UI together, one can start having fun.
This exploit relies on the game:loc
metadata key, which when set to a length greater than 2^15
or 32768
and a client is invited, an out of bounds memory write is triggered, leading to an Access Violation/Segmentation Fault which ultimately crashes the CS:GO client.
Once a CS:GO user is invited in-game, the panorama/layout/friendlobby.xml
file is loaded.
This XML file includes a Javascript file (panorama/scripts/friendlobby.js
) that populates the fields such as the lobby members' avatars, the gamemode, the average lobby rank, and most importantly, the lobby location.
var _SetFlag = function ( elTile )
{
var countryCode = PartyBrowserAPI.GetPartySessionSetting( _m_xuid, 'game/loc' );
var elFlagImg = elTile.FindChildTraverse( 'JsFriendLobbyFlag' );
if ( countryCode )
{
elFlagImg.SetImage( 'file://{images}/flags/'+ countryCode +'.png' );
elFlagImg.RemoveClass( 'hidden' );
}
else
{
elFlagImg.AddClass( 'hidden' );
}
};
This code snippet highlights how the unsanitized game:loc
metadata key is handled.
When first auditing this code snippet, I was originally testing for a way to truncate the .png
file extension and load another arbitrary file of my choosing.
Through this testing, I had attempted to fill the game:loc
with a massive amount of characters, in the hopes that the parser would completely ignore characters after some power of 2 and throw away the file extension, loading my arbitrary file.
Instead of a file being loaded, my client instantly crashed.
After attaching a debugger to analyze the crash, it was revealed that that when the file://
URI handler was being parsed by the client, one of the intermediary functions that generated a hash of the file path triggered an Access Violation.
The hash function attempted to call the Clang memset
function and write the parsed filepath to another area of memory without validating the size of the source data. This is called an Out-of-bounds Write
.
Initially, I had attempted to escalate this vulnerability to an RCE or remote code execution since the Valve bug bounty program would consider a client crasher out of scope. After contacting many friends who were much better than I was at reverse engineering, it was concluded that the most that could be achieved with this exploit was Denial of Service.
- Thanks to @shayhelman for finding the crash method
- Thanks to the countless streamers for being our test subjects