Remote
vulnerability in SSH daemon crc32 compensation attack detector
Issue Date: February 8, 2001
Author: Michal Zalewski
Contact: Scott Blake
CVE: CAN-2001-0144
Topic:
Remotely exploitable vulnerability
condition exists in most ssh daemon installations
(F-SECURE, OpenSSH, SSH from ssh.com,
OSSH).
Tested
against:
**
Vulnerable:
SSH 1.2.x (ssh.com) -- all recent
releases
F-SECURE SSH 1.3.x -- all recent
releases
OpenSSH prior to 2.3.0 (unless SSH
protocol 1 support is disabled)
OSSH 1.5.7 (by Bjoern
Groenvall) and other ssh1/OpenSSH derived daemons
** Not vulnerable:
SSH2 (ssh.com): all
2.x releases NOTE: SSH2 installations with SSH1 fallback support are
vulnerable
OpenSSH 2.3.0 (problem fixed)
SSH1
releases prior to 1.2.24 (vulnerable to crc attacks)
Cisco SSH (own implementation)
LSH (SSH
protocol 1 not supported)
** Other SSH daemons:
not tested
Overview:
An integer-overflow problem is present in
common code of recent ssh daemons, deattack.c,
which was developed by CORE SDI to protect against cryptographic
attacks on SSH protocol.
Impact:
Insufficient range control calculations (16-bit
unsigned variable is used instead of 32-bit,
which causes integer overflow) in the detect_attack() function
leads to table index overflow
bug. This effectively allows an attacker to overwrite arbitrary portions
of memory. The
altered memory
locations affect code that is executed by the daemon with uid 0, and this
can
be leveraged to obtain
general root access to the system.
Details:
When
the condition described above occurs, a 32-bit local variable, which is set to
65536
for large input buffers,
is assigned to a 16-bit local variable, effectively causing it to
be set to 0. Due to specific malloc(0)
behavior, memory allocation routine will be passed,
creating buffer of size
(malloc_usable_size) 12. Next:
for (i = HASH(c) &
(n - 1); h[i] != HASH_UNUSED;
We can see n-1 here, and
n is equal to 0. Because i is an unsigned 32-bit integer, it would
cause integer overflow. This code will be
equal to i = HASH(c) & 0xffffffff. Binary AND
operator reduces this to i = HASH(c).
Pointer 'c' is referencing client-provided
cryptographic packet, and HASH function is simply responsible
for changing byte order in
input
stream.
Then, detect_attack() routine is trying to
access h[i], causing segmentation fault due to
table index overflow bug.
To reproduce
this condition, run your sshd server on localhost under gdb with '-d'
switch
(to avoid forking). Then
try (using OpenSSH client - ssh.com client software crops the login
name):
$ ssh -v -l
`perl -e '{print "A"x88000}'` localhost
Program received signal SIGSEGV,
Segmentation fault.
0x806cfbd in detect_attack ( ..., len=88016, IV=0x0)
at deattack.c:138
136
for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
We can inspect the table index (SEGV
happened during h[i] != HASH_UNSIGNED comparsion):
(gdb) printf "%x\n",i
Results may vary with
every connection, depending on the entropy seed used by the client,
crypto keys, etc. You can easily produce a
wide 32-bit range of indexes by changing client
parameters or simply reconnecting. It is obvious there wouldn't
be a problem to specify very
large index that would point outside our table, but will cause address
space wrap to point
accessible
memory (stack or another segment). Then, few lines below, in the same loop,
we
can find following
statement:
h[i] = j;
...where j is
a simple block counter.
Conclusion
By carefully preparing encrypted data, an
attacker can point used, accessible memory (that
would pass check in line 136 without SEGV),
and then, he will able to alter dword at chosen
address, replacing it with value of j. The attacker can alter
stack variables, alter malloc
structures, etc, and attack later due to improper execution of daemon
code. This condition
is
relatively difficult to exploit, but there are no technical reasons that would
make this
impossible.
Currently, we are not aware of working exploits for this
vulnerability.
Note that the attacker needs to make a TCP
connection from an IP address for which sshd will
enter into a key-exchange dialogue. If the
attacker's packets have a source IP address that
is disallowed by (for example) DenyHosts in
the sshd configuration file, the key exchange
will not happen and the attacker will not have an opportunity to
compose the required
exploit
data.
Solution
Included are a few patches for various
versions/implementations of SSH. This is not meant to
be an all-inclusive list, as there are a
number of implementers of SSH daemons that are not
open source. If you *do* have the source
code for SSH, it should be fairly simply to study
the patches below, see what has been done,
and patch your own code. Note that this is a fix
for the one issue that we've found, and
should not be construed as the results of a complete
audit of the code.
SSH1 software:
8<---------------------patch
for ssh-1.2.31---------------------------
--- deattack.c.orig Wed Feb
7 13:53:47 2001
+++ deattack.c
Wed Feb 7 13:54:24 2001
@@
-79,7 +79,7 @@
detect_attack(unsigned char *buf, word32 len, unsigned char
*IV)
{
static word16 *h = (word16 *) NULL;
-
static word16 n = HASH_MINSIZE
/ HASH_ENTRYSIZE;
+ static
word32 n = HASH_MINSIZE /
HASH_ENTRYSIZE;
register word32
i, j;
word32 l;
register unsigned char *c;
8<---------------------patch
for ssh-1.2.31---------------------------
Bjoern Groenvall's ossh
(ftp://ftp.pdc.kth.se/pub/krypto/ossh/):
8<---------------------patch
for ossh-1.5.7---------------------------
--- deattack.c.orig Wed Feb
7 14:11:23 2001
+++ deattack.c
Wed Feb 7 14:11:46 2001
@@
-91,7 +91,7 @@
detect_attack(const
unsigned char *buf, word32 len)
{
static u_int16_t
*h = (u_int16_t *) NULL;
- static
u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
+ static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
register word32 i, j;
word32 l;
const unsigned char *c, *d;
8<---------------------patch
for ossh-1.5.7---------------------------
OpenSSH:
Upgrade to
2.3.0 or above. If you have 2.2.0:
8<-------------------patch for
openssh-2.2.0--------------------------
--- deattack.c.orig Wed Feb
7 14:18:23 2001
+++ deattack.c
Wed Feb 7 14:19:33 2001
@@
-84,7 +84,7 @@
detect_attack(unsigned
char *buf, u_int32_t len, unsigned char *IV)
{
static
u_int16_t *h = (u_int16_t *) NULL;
-
static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
+ static u_int32_t n = HASH_MINSIZE /
HASH_ENTRYSIZE;
register
u_int32_t i, j;
u_int32_t
l;
register unsigned char
*c;
8<-------------------patch for
openssh-2.2.0--------------------------
Vendor Response:
CORE SDI has issued their own advisory
detailing fix information and has also pointed out
that SSH1 clients are also
vulnerable.
Bjorn Gronvall - OSSH
Fixed in version ossh-1.5.8
AppGate
The default
configuration of the AppGate server is not vulnerable since it has SSH-1
support
disabled. However
customers who need ssh1-support can contact support@appgate.com to get
patches.
Mindbright
The MindTerm client does not have this
vulnerability.
SSH
Current release 2.4.0 is not vulnerable. Previous versions of SSH1 are
not supported but a
fix has been
commited to the source tree. SSH recommends customers upgrade to SSH2.
F-Secure
Unfortunately,
after many attempts to contact F-Secure via email and telephone no
response
has been
received.
Thanks:
Special thanks to Mark Loveless for his
significant contributions to the Fix section. Thanks
to RAZOR team members Todd Sabin, Scott
Blake, and Steve Manzuik for their assistance with
this issue. Thanks also to Ivan Arce of
CORE SDI for his patience with us.
Contact:
info@razor.bindview.com | Fax: 508-485-0737 | Bindview Home