Bugtraq mailing list archives
Re: SSH1 key recovery patch
From: Johannes Geiger <geiger () SUNSPIES8 INFORMATIK TU-MUENCHEN DE>
Date: Tue, 20 Feb 2001 12:48:09 +0100
Hello! On Wed, Feb 14, 2001 at 05:35:13AM +0100, Iván Arce wrote:
In light of the recent posts to bugtraq concerning the CORE SDI advisory that describes the SSH1 session key recovery vulnerability a few things needs to be noted:
(...)
The rationale for the above fix is to regenerate the key whenever a RSA operation failed - a symptom of an attacker trying to execute the key recovery attack- this does not close the information leakage in the ssh server (namely the existence of an oracle that can be used to infer a session key) but it does make IMPOSSIBLE to exploit it. The patch intends to limit the key regeneration rate to at most one regeneration per minute, in order to prevent a DoS.
(...) Wouldn't it be much easier and less error prone to actually disable the oracle, which is the real problem leading to the attack, instead of all this key regeneration stuff? quote from the original attack description:
Notice that the calls to the function fatal() can be used as the needed oracle. Successful negotiation of a session key will end with the reception of a SSH_SMSG_SUCCESS packet at the client. A failure will end with the connection being shutdown due to the calls to the fatal() function from within the rash_private_decrypt() function.
So all you have to do is to always do both RSA operations, record a failure of the first but call fatal() only after the second. Or did I miss something? Regards Johannes The following patch is UNTESTED and supplied only to make myself clear. --- rsaglue.c.orig Tue Feb 20 11:20:21 2001 +++ rsaglue.c Tue Feb 20 11:23:21 2001 @@ -238,11 +238,12 @@ /* Decrypt input using the private key. Output will become a 256 bit value. */ -void rsa_private_decrypt(MP_INT *output, MP_INT *input, RSAPrivateKey *key) +int rsa_private_decrypt(MP_INT *output, MP_INT *input, RSAPrivateKey *key) { MP_INT aux; unsigned int len, i; unsigned char *value; + int success; rsa_private(output, input, key); @@ -263,8 +264,7 @@ } mpz_clear(&aux); - if (value[0] != 0 || value[1] != 2) - fatal("Bad result from rsa_private_decrypt"); + success == (value[0] == 0 && value[1] == 2); for (i = 2; i < len && value[i]; i++) ; @@ -272,6 +272,9 @@ xfree(value); mpz_mod_2exp(output, output, 8 * (len - i - 1)); + + return success; + } #endif /* RSAREF */ --- rsa.h.orig Tue Feb 20 11:38:04 2001 +++ rsa.h Tue Feb 20 12:21:50 2001 @@ -111,6 +111,6 @@ RandomState *state); /* Performs a private key decrypt operation. */ -void rsa_private_decrypt(MP_INT *output, MP_INT *input, RSAPrivateKey *key); +int rsa_private_decrypt(MP_INT *output, MP_INT *input, RSAPrivateKey *key); #endif /* RSA_H */ --- sshd.c.orig Tue Feb 20 11:20:12 2001 +++ sshd.c Tue Feb 20 12:43:54 2001 @@ -1553,23 +1553,29 @@ larger modulus first). */ if (mpz_cmp(&sensitive_data.private_key.n, &sensitive_data.host_key.n) > 0) { + int rok1, rok2; /* Private key has bigger modulus. */ assert(sensitive_data.private_key.bits >= sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED); - rsa_private_decrypt(&session_key_int, &session_key_int, - &sensitive_data.private_key); - rsa_private_decrypt(&session_key_int, &session_key_int, - &sensitive_data.host_key); + rok1 = rsa_private_decrypt(&session_key_int, &session_key_int, + &sensitive_data.private_key); + rok2 = rsa_private_decrypt(&session_key_int, &session_key_int, + &sensitive_data.host_key); + if (!(rok1 && rok2)) + fatal("Bad result from rsa_private_decrypt"); } else { + int rok1, rok2; /* Host key has bigger modulus (or they are equal). */ assert(sensitive_data.host_key.bits >= sensitive_data.private_key.bits + SSH_KEY_BITS_RESERVED); - rsa_private_decrypt(&session_key_int, &session_key_int, - &sensitive_data.host_key); - rsa_private_decrypt(&session_key_int, &session_key_int, - &sensitive_data.private_key); + rok1 = rsa_private_decrypt(&session_key_int, &session_key_int, + &sensitive_data.host_key); + rok2 = rsa_private_decrypt(&session_key_int, &session_key_int, + &sensitive_data.private_key); + if (!(rok1 && rok2)) + fatal("Bad result from rsa_private_decrypt"); } /* Compute session id for this session. */
Current thread:
- SSH1 key recovery patch Iván Arce (Feb 13)
- Re: SSH1 key recovery patch Andrew Brown (Feb 15)
- Re: SSH1 key recovery patch Pavel Machek (Feb 19)
- Re: SSH1 key recovery patch Johannes Geiger (Feb 20)
- Re: SSH1 key recovery patch Johannes Geiger (Feb 21)
- Re: SSH1 key recovery patch Markus Friedl (Feb 21)
- Message not available
- Re: SSH1 key recovery patch Markus Friedl (Feb 22)