Re: traceroute as a flooder

From: Curt Sampson (cjsat_private)
Date: Tue Feb 16 1999 - 15:30:13 PST

  • Next message: Dildog: "L0pht Security Advisory: Windows NT"

    I've appended the set of patches for the traceroute bugs that I
    just commited to NetBSD. (It should work for other BSDs, and perhaps
    Linux too, if it's using the 4.4BSD traceroute.) This fixes two
    problems:
    
        1. If uid != 0 (you're not superuser), it checks to see that
        the source address it's going to use is an address from a local
        interface that's up and not marked loopback.
    
        2. It checks the return value from select() and, if select
        fails, exits.
    
    I believe that my solution for #2 is better than the one recently
    committed to FreeBSD because mine exits on all select() errors,
    not just EINVAL. So if you could somehow convince select() to fail
    with, for example, EINTR, you still can't utilise this to get around
    the inter-packet delay. (I don't believe you can do this as it
    stands, but if someone later adds a signal handler to this program
    that doesn't exit when a signal is caught, you'd probably be able
    to do it by sending a rapid stream of that signal to the program.)
    Also, I don't arbitrarially limit the timeout to a day, though I
    doubt that makes much difference to anyone.
    
    cjs
    --
    Curt Sampson  <cjsat_private>   604 801 5335   De gustibus, aut bene aut nihil.
    The most widely ported operating system in the world: http://www.netbsd.org
    
    
    Index: traceroute.c
    ===================================================================
    RCS file: /cvsroot/src/usr.sbin/traceroute/traceroute.c,v
    retrieving revision 1.26
    retrieving revision 1.28
    diff -u -r1.26 -r1.28
    --- traceroute.c	1998/12/09 22:53:29	1.26
    +++ traceroute.c	1999/02/16 23:18:40	1.28
    @@ -378,7 +379,7 @@
     	int tos = 0, settos = 0, ttl_flag = 0;
     	register int lsrr = 0;
     	register u_short off = 0;
    -	struct ifaddrlist *al;
    +	struct ifaddrlist *al, *al2;
     	char errbuf[132];
    
     	if ((cp = strrchr(argv[0], '/')) != NULL)
    @@ -699,6 +700,7 @@
    
     	/* Get the interface address list */
     	n = ifaddrlist(&al, errbuf, sizeof errbuf);
    +	al2 = al;
     	if (n < 0) {
     		Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
     		exit(1);
    @@ -711,8 +713,8 @@
    
     	/* Look for a specific device */
     	if (device != NULL) {
    -		for (i = n; i > 0; --i, ++al)
    -			if (strcmp(device, al->device) == 0)
    +		for (i = n; i > 0; --i, ++al2)
    +			if (strcmp(device, al2->device) == 0)
     				break;
     		if (i <= 0) {
     			Fprintf(stderr, "%s: Can't find interface %s\n",
    @@ -728,11 +730,11 @@
     		 * Otherwise, use the first interface found.
     		 * Warn if there are more than one.
     		 */
    -		setsin(from, al->addr);
    +		setsin(from, al2->addr);
     		if (n > 1 && device == NULL && !find_local_ip(from, to)) {
     			Fprintf(stderr,
     		    "%s: Warning: Multiple interfaces found; using %s @ %s\n",
    -			    prog, inet_ntoa(from->sin_addr), al->device);
    +			    prog, inet_ntoa(from->sin_addr), al2->device);
     		}
     	} else {
     		hi = gethostinfo(source);
    @@ -754,7 +756,7 @@
     			 * interface address.
     			 */
     			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
    -				if (*ap == al->addr)
    +				if (*ap == al2->addr)
     					break;
     			if (i <= 0) {
     				Fprintf(stderr,
    @@ -766,6 +768,25 @@
     		}
     		freehostinfo(hi);
     	}
    +
    +	/*
    +	 * If not root, make sure source address matches a local interface.
    +	 * (The list of addresses produced by ifaddrlist() automatically
    +	 * excludes interfaces that are marked down and/or loopback.)
    +	 */
    +	if (getuid())  {
    +		al2 = al;
    +		for (i = n; i > 0; --i, ++al2)
    +			if (from->sin_addr.s_addr == al2->addr)
    +			    break;
    +		if (i <= 0) {
    +			Fprintf(stderr, "%s: %s is not a valid local address "
    +			    "and you are not superuser.\n", prog,
    +			    inet_ntoa(from->sin_addr));
    +			exit(1);
    +		}
    +	}
    +
     	outip->ip_src = from->sin_addr;
     #ifndef IP_HDRINCL
     	if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
    @@ -911,6 +932,7 @@
     	struct timezone tz;
     	register int cc = 0;
     	int fromlen = sizeof(*fromp);
    +	int retval;
    
     	FD_ZERO(&fds);
     	FD_SET(sock, &fds);
    @@ -920,9 +942,16 @@
     	(void)gettimeofday(&now, &tz);
     	tvsub(&wait, &now);
    
    -	if (select(sock + 1, &fds, NULL, NULL, &wait) > 0)
    +	retval = select(sock + 1, &fds, NULL, NULL, &wait);
    +	if (retval < 0)  {
    +		/* If we continue, we probably just flood the remote host. */
    +		Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno));
    +		exit(1);
    +	}
    +	if (retval > 0)  {
     		cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
     			    (struct sockaddr *)fromp, &fromlen);
    +	}
    
     	return(cc);
     }
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:35:34 PDT