####################################################################### Luigi Auriemma Application: Source Engine http://source.valvesoftware.com Games: Half-Life 2 http://www.half-life2.com Counter-Strike: Source http://store.steampowered.com/app/240/ OrangeBox / Team Fortress 2 http://store.steampowered.com/app/440/ Left 4 Dead http://www.l4d.com other games and mods Versions: <= build 3933 Platforms: Windows and Linux Bug: format string Exploitation: remote, versus server (in-game) Date: 17 Aug 2009 Author: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduction 2) Bug 3) The Code 4) Fix ####################################################################### =============== 1) Introduction =============== The Source engine is the latest version and rewrite of the original Half-Life engine (GoldSrc) developed by Valve (http://www.valvesoftware.com). It's the engine used for games like Half-Life 2, Counter Strike Source, Team Fortress 2, Left 4 Dead and various others which are also the most played internet multiplayer games in absolute with over 10000 online servers. ####################################################################### ====== 2) Bug ====== engine.dll has a function which handles the players disconnections (player_disconnect) and shows the classical console message "Dropped NICKNAME from server (REASON)" when a player is kicked. This "reason" parameter is usually a server side parameter where is explained the reason of a kick but in my tests seems that also the player can specify this particular field (note that my knowledge of the Source engine is really very limited at the moment so I can't be more detailed). Just at the beginning of the function the input reason string is used with snprintf for generating the final "reason" that will be showed in the consoled message explained previously, but the necessary format argument ("%s") is not specified like the following example: snprintf(output_buffer, 1024, input_reason_string); The effect is that an attacker can exploit this vulnerability to crash the server or even executing malicious code. The vulnerability is exploitable in-game so the attacker must be able to join the target server (no banning, valid Steam credentials, valid password and so on). ####################################################################### =========== 3) The Code =========== For quickly confirming the vulnerability and testing a LAN server it's enough to try the following stand-alone proof-of-concept: http://aluigi.org/poc/sourcefslan.zip For testing the vulnerability in a real environment (internet with Steam) is necessary to use the following proof-of-concept (I'm not aware of other easiet ways to test it at the moment): http://aluigi.org/poc/sourcefs.zip It's a plugin for sudppipe/proxocket which forges the malformed packet (compatible with HL2 and CSS) when the real client sends its first in-game packet. quick usage for proxocket (NOTE that some users report that this method could give problems with VAC): - download proxocket: http://aluigi.org/mytoolz.htm#proxocket - copy ws2_32.dll and the myproxocket.dll of the PoC in the same folder where is located the game executable of the client - start the client and join the server to test quick usage for sudppipe: - download sudppipe: http://aluigi.org/mytoolz.htm#sudppipe - copy myproxocket.dll in the same folder of sudppipe and start it: sudppipe -l myproxocket.dll SERVER PORT 1234 - start the client and join the server on 127.0.0.1:1234 ####################################################################### ====== 4) Fix ====== No fix. #######################################################################