[19297] in bugtraq
Re: SSH1 key recovery patch
daemon@ATHENA.MIT.EDU (Johannes Geiger)
Tue Feb 20 13:44:47 2001
Mail-Followup-To: BUGTRAQ@SECURITYFOCUS.COM
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
Message-Id: <20010220124809.G4017@mailspies>
Date: Tue, 20 Feb 2001 12:48:09 +0100
Reply-To: Johannes Geiger <geiger@SUNSPIES8.INFORMATIK.TU-MUENCHEN.DE>
From: Johannes Geiger <geiger@SUNSPIES8.INFORMATIK.TU-MUENCHEN.DE>
To: BUGTRAQ@SECURITYFOCUS.COM
In-Reply-To: <108a01c0961a$52872ac0$2e58a8c0@ffornicario>; from
core.lists.bugtraq@CORE-SDI.COM on Wed, Feb 14,
2001 at 05:35:13AM +0100
Hello!
On Wed, Feb 14, 2001 at 05:35:13AM +0100, Ivan 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. */