SSH 1.2.27 is vulnerable to a remote buffer overflow (RSAREF)
16 Nov. 1999
Summary
It is possible to overflow one of the internal buffers of SSH 1.2.27, causing the program to crash and possible execute arbitrary code. Since this is a no longer a supported version (the supported versions are 2.0 and above) this will probably not be fixed.
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.
The problematic 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).
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);
}
[...]
}
That is the buffer 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 whether len is greater than MAX_RSA_MODULUS_LEN is performed.
A 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 have to send to the server instead of the encrypted session key; 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 is 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.