Vulnerability Development mailing list archives

Re: ssh-1.2.27 remote buffer overflow - exploitable


From: jtb () THEO2 PHYSIK UNI-STUTTGART DE (Jochen Bauer)
Date: Tue, 9 Nov 1999 12:42:16 +0100


On Tue, Nov 09, 1999 at 01:48:53AM -0000, Frank wrote:
This is submitted to the Freebsd bug tracking system, although there are 
doubtless other vendors who leave this package, despite the existence of
the ssh-2.X.   While Debian appears to be immune, I was able to crash my
ssh daemon (much to my dismay), and there appears the potential to
execute arbitrary code, as long as you encrypt it first...

Here is the freebsd report.. it describes the method to crash a remote Ssh daemon (lets hope you ran sshd from your 
xinetd, etc).

http://www.freebsd.org/cgi/query-pr.cgi?pr=14749

I've taken a closer look at the problem. Here's my analysis:

In sshd.c, around line 1513 the client-generated session key,
that has been encrypted with the server and host public keys, 
is received from the client as a multiple precision integer.

/* Get the encrypted integer. */
  mpz_init(&session_key_int);
  packet_get_mp_int(&session_key_int);

The encrypted session key is then (around line 1525) passed 
to rsa_private_decrypt to do the first part of the decryption,
which is either decryption using the server private key or
decryption using the host private key, depending on which key
has the larger modulus.  

rsa_private_decrypt(&session_key_int, &session_key_int,
                          &sensitive_data.private_key);

If RSAREF is used (i.e. RSAREF is defined in the code), the 
rsa_private_decrypt function in rsaglue.c (around line 162) 
looks like:

void rsa_private_decrypt(MP_INT *output, MP_INT *input, RSAPrivateKey *key)
{
  unsigned char input_data[MAX_RSA_MODULUS_LEN];
  unsigned char output_data[MAX_RSA_MODULUS_LEN]
  unsigned int input_len, output_len, input_bits;
  [...]
  input_bits = mpz_sizeinbase(input, 2);
  input_len = (input_bits + 7) / 8;
  gmp_to_rsaref(input_data, input_len, input);
  [...] 
}   

The trouble spot is the fixed length buffer 
input_data[MAX_RSA_MODULUS_LEN]. A pointer to this buffer is
passed to the conversion function gmp_to_rsaref along with a 
pointer to the encrypted session key and the length (input_len) 
of the encrypted session key, which may be greater than 
[MAX_RSA_MODULUS_LEN]. gmp_to_rsaref (located around line 79 of
rsaglue.c) simply calls mp_linearize_msb_first(buf, len, value).

void gmp_to_rsaref(unsigned char *buf, unsigned int len, MP_INT *value)
{
  mp_linearize_msb_first(buf, len, value);
}

mp_linearize_msb_first is contained in mpaux.c around line 41. 
The function looks like:

void mp_linearize_msb_first(unsigned char *buf, unsigned int len, 
                            MP_INT *value)
{
  unsigned int i;
  MP_INT aux;
  mpz_init_set(&aux, value);
  for (i = len; i >= 4; i -= 4)   <-------     
    {
      unsigned long limb = mpz_get_ui(&aux);
      PUT_32BIT(buf + i - 4, limb);   <-------
      mpz_div_2exp(&aux, &aux, 32);
    }
  [...]
}
    
There's the overflow! len is the length of the encrypted session 
key, while buf is a pointer to the fixed length buffer
input_data[MAX_RSA_MODULUS_LEN] and no check wether len is 
greater than MAX_RSA_MODULUS_LEN is performed. The fix should be
obvious!

About the possible exploit: 

In this particular overflow, the encrypted, client generated session
key has to be taken as the exploit buffer. I.e. the shellcode, NOPs 
and jump address has to sent to the server instead of the encrypted 
session key. To make that clear: The shellcode, NOPs and jump address
don't have to be encrypted as they are taken as the ENCRYPTED session 
key.

However, the data that is finally written into the buffer are the 
limbs of the multiple precision integer that session_key_int is 
assumed to be. The exploit buffer code therefore must be converted 
into a multiple precision integer, which upon extraction of the limbs 
into the buffer yields the correct exploit buffer code. The best way 
would probably be to start from the exploit buffer as it should finally 
be to overflow the target buffer and use the functions of the GNU 
multiple precision integer library to reverse the procedure happening 
to the encrypted session key in the sshd code step be step, leading to 
the exploit buffer that has to be sent instead of the encrypted session 
key. 

That may be difficult, be it think it's possible.    

-- 
Jochen Bauer

************************************************************
*Network Security Team                                     *
*Computer Center of the University of Stuttgart            *
*Germany                                                   *
*                                                          *
*Email: jtb () theo2 physik uni-stuttgart de                  *
*       jochen.bauer () rus uni-stuttgart de                  *
*                                                          *
*PGP Public Key:                                           *
*   http://www.theo2.physik.uni-stuttgart.de/jtb/jtb.html  *
************************************************************ 

<!-- attachment="bin0a02906" -->
<HR>
<UL>
<LI>application/pgp-signature attachment: stored
</UL>



Current thread: