/* traceroute local root advisory */ /* by: bazarr */ /* bazrar@hotmail.com */ /* bazarr episode #* */ ------------------ PREFACE its me bazarr. i dont use ziplip anymore. resend any emails sent to bazarr@ziplip to bazrar@hotmail.com if i dident respond to them. this is a local root vulnerability in the traceroute shipped with alot of distros and operating systems. and ya its really the real bazarr. lets take a look at the vendor info: /* * traceroute host - trace the route ip packets follow going to "host". * * Attempt to trace the route an ip packet would follow to some * internet host. We find out intermediate hops by launching probe * packets with a small ttl (time to live) then listening for an * icmp "time exceeded" reply from a gateway. We start our probes * with a ttl of one and increase by one until we get an icmp "port * unreachable" (which means we got to "host") or hit a max (which * defaults to 30 hops & can be changed with the -m flag). Three * probes (change with -q flag) are sent at each ttl setting and a * line is printed showing the ttl, address of the gateway and * round trip time of each probe. If the probe answers come from * different gateways, the address of each responding system will * be printed. If there is no response within a 5 sec. timeout * interval (changed with the -w flag), a "*" is printed for that * probe. */ around the time of the get_origin() bug found by Carl Livitt, debian released a patch for that bug and a few other little problems in traceroute which noone really bothered to talk about i guess. but uh lets take a look at the source code for a second. this is after applying the patch by debian to secure traceroute from buffer overflows. #define SPRAYMAX 256 /* We'll only do up to 256 TTLs at once */ struct { u_long dport; /* check for matching dport */ u_char ttl; /* ttl we sent it to */ u_char type; /* icmp response type */ struct timeval out; /* time packet left */ struct timeval rtn; /* time packet arrived */ struct sockaddr_in from; /* whom from */ } spray[SPRAYMAX]; int *spray_rtn[SPRAYMAX]; /* See which TTLs have responded */ ... case 'S': argc--, AbortIfNull((++av)[0]); min_ttl = atoi(av[0]); if ((min_ttl < 0) || (min_ttl > max_ttl)) { Fprintf(stderr, "min ttl must be >=%d%s and >0",max_ttl,terminator); exit(1); } goto nextarg; case 'm': argc--, AbortIfNull((++av)[0]); max_ttl = atoi(av[0]); if (max_ttl < min_ttl) { Fprintf(stderr, "max ttl must be >%d%s",min_ttl,terminator); exit(1); } goto nextarg; ... case 'P': spray_mode = 1; break; case 'f': argc--, AbortIfNull((++av)[0]); sport = atoi(av[0]); goto nextarg; case 'q': argc--, AbortIfNull((++av)[0]); nprobes = atoi(av[0]); if (nprobes < 1) { Fprintf(stderr, "nprobes must be >0%s",terminator); exit(1); } goto nextarg; ... /* Prevent overflow of spray[] array */ if (spray_mode && (nprobes*max_ttl > SPRAYMAX)) { Fprintf(stderr, "too many spray packets\n"); exit(1); } now what is the first thing we see here. we can control 'nprobes' , 'min_ttl' and 'max_ttl' with any values we want. now debian added this code at the end here with their patch trying to prevent overflow of the spray[] array i guess. well lets take a look bazarr:traceroute-nanog-6.1.1$ ./traceroute -P -q 256 -m 2147483648 google.com traceroute to google.com (216.239.33.100), 2147483647 hops max, 40 byte packets Segmentation fault bazarr:traceroute-nanog-6.1.1$ since we can control max_ttl and nprobes all we have to do is make sure that the equation "nprobes * max_ttl" will result in an int wrap around and become < SPRAYMAX (256) which is really easy since its not checking that the value is not < 0 it can just be negative. now lets take a look at some of our options after we bypass its little check we go back to the land of source code once again: if (!spray_mode) { /* For all TTL do */ ... } else { /* * Enter Spray mode */ spray_target = spray_max = spray_total = 0; spray_min = SPRAYMAX+1; /* For all TTL do */ for (ttl = min_ttl; ttl <= max_ttl; ++ttl) { spray_rtn[ttl] = (int *)malloc(sizeof(int)*nprobes + 1); for (probe = 0; probe < nprobes; ++probe) { spray_rtn[ttl][probe]=0; send_probe(++seq, ttl); } } what we can see here is multiple possibliltys. spray_rtn[ttl] = (int *)malloc(sizeof(int)*nprobes + 1); since we can control 'ttl' this tells us we can write a 4 byte ptr anywhere we want. only thing is that it will be to a 4 byte aligned address so modifying parts of a ret address is out of the question. and we cannot control the data at the ptr we are able to write so putting shellcode their is out of the question. so this line tells us we can write a 4 byte ptr returned by malloc anywhere we want , but we can also force the malloc call to fail and write a 4 byte NULL anywhere we want easily since we can control nprobes we can make it a pretty big number , bigger then the system can alloc so malloc will fail and return NULL. this line also tells us since we can control nprobes we can force malloc to alloc too low by supplying a big value to nprobes , this isnt that great of an option though. also if we write a NULL then spray_rtn[ttl][probe] = 0; is bound to fail with an access violation. so with that line we can either write a really big number or a really small number anywhere we want on a 4 byte align. since we cant control the data at the addr we can write its kind of useless. but what about writing a big number somewhere which would cause another bug? or a small number? lets take a look at the send_probe() function for a sec: send_probe(seq, ttl) int ttl; int seq; { struct opacket *op = outpacket; struct ip *ip = &op->ip; struct udphdr *up = &op->udp; int i; retry: if (mtudisc) { ip->ip_off = (short) IP_DF; } else { ip->ip_off = 0; } ip->ip_p = IPPROTO_UDP; #ifndef BYTESWAP_IP_LEN ip->ip_len = ((u_short)datalen-_optlen); /* The OS inserts options */ #else /* BYTESWAP_IP_LEN */ ip->ip_len = htons((u_short)datalen-_optlen); /* The OS inserts options */ #endif /* BYTESWAP_IP_LEN */ ip->ip_ttl = ttl; ip->ip_v = IP_VERSION; ip->ip_hl = sizeof(*ip) >> 2; up->uh_sport = htons(ident); up->uh_dport = htons(port+seq); up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip) - _optlen)); up->uh_sum = 0; op->seq = seq; op->ttl = ttl; #ifndef __linux__ (void) gettimeofday(&op->tv, NULL); #else /* __linux__ */ (void) gettimeofday(&op->tv, &tz); #endif /* __linux__ */ #ifdef SPRAY if (spray_mode) { spray[seq].dport = up->uh_dport; spray[seq].ttl = ttl; bcopy(&op->tv, &spray[seq].out, sizeof(struct timeval)); } .... now we can write past spray[] essentially because 'seq' will be bigger then its sposed to be cuz we can control the value of 'nrpobes'. but we cant write all that much data we want to or even where we want to really. so we can write our 4 byte ptr from above to 'outpacket' which will point outpacket to a spot in the heap and then we can make 'nprobes' a low number like 4 forcing it to malloc pretty low. then it will be writing a shit load of data on the heap in spots its not sposed to. if your gunna try and xploit this bug you probly know your options anyways and i probly missed alot. but as you can see there are alot of possibilitys to xploiting this bug. if you do manage to xploit this bug it probly will be a combination of things inside traceroute to lead to code exec. ------------------ PATCH :`( ------------------ XPLOIT :`( ------------------ ADVANCE WARNING nothing is comming for you anymore. ------------------ GREETS sad cow - hi sad cow. dethy - hehe :) #!FHAB - im all by myself in there on ircs somtimes puppy of the rain forest - why dont you return my friendly email ? :( dave aitel - for sending 2 nice emails to me :) archim - hi morgan - for telling me he dont really care about anything i do , and refusing to be a big brother twards me , why morgan why JUST GIMMIE A REASON! spender - for nice conversation with lonely young boy. bighawk - for taking out cryptome.org i sent alot of emails to various people saying 'hi' and noone responded accept 2 people. thank you hendy. thank you anonymous p59_9 author. ------------------ BYE what in the fuck was i thinking doing somthing like this. i cant even belive i actually went through with all this. you aint gunna be seeing bazarr around for long time. sorry for disruptence. no hard feelings. farewell. -bazarr