From 555aabebde10eb6df5487f6c0fb2dfea836a5589 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 5 Feb 2020 21:14:26 +0000 Subject: [PATCH] Uppity: option to always send PK_OK / RSA1 challenge. This allows me to deliberately provoke the conditions for the stale-pointer bug in the agent key list parsing. --- ssh1login-server.c | 25 ++++++++++++++++++++++--- ssh2userauth-server.c | 30 ++++++++++++++++++------------ sshserver.h | 2 ++ unix/uxserver.c | 2 ++ 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/ssh1login-server.c b/ssh1login-server.c index 3316a6c3..cf71f5c5 100644 --- a/ssh1login-server.c +++ b/ssh1login-server.c @@ -292,18 +292,34 @@ static void ssh1_login_server_process_queue(PacketProtocolLayer *ppl) mp_int *modulus = get_mp_ssh1(pktin); s->authkey = auth_publickey_ssh1( s->authpolicy, s->username, modulus); + + if (!s->authkey && + s->ssc->stunt_pretend_to_accept_any_pubkey) { + mp_int *zero = mp_from_integer(0); + mp_int *fake_challenge = mp_random_in_range(zero, modulus); + + pktout = ssh_bpp_new_pktout( + s->ppl.bpp, SSH1_SMSG_AUTH_RSA_CHALLENGE); + put_mp_ssh1(pktout, fake_challenge); + pq_push(s->ppl.out_pq, pktout); + + mp_free(zero); + mp_free(fake_challenge); + } + mp_free(modulus); } - if (!s->authkey) + if (!s->authkey && + !s->ssc->stunt_pretend_to_accept_any_pubkey) continue; - if (s->authkey->bytes < 32) { + if (s->authkey && s->authkey->bytes < 32) { ppl_logevent("Auth key far too small"); continue; } - { + if (s->authkey) { unsigned char *rsabuf = snewn(s->authkey->bytes, unsigned char); @@ -343,6 +359,9 @@ static void ssh1_login_server_process_queue(PacketProtocolLayer *ppl) return; } + if (!s->authkey) + continue; + { ptrlen response = get_data(pktin, 16); ptrlen expected = make_ptrlen( diff --git a/ssh2userauth-server.c b/ssh2userauth-server.c index 7e67e557..3ec46ed0 100644 --- a/ssh2userauth-server.c +++ b/ssh2userauth-server.c @@ -203,7 +203,7 @@ static void ssh2_userauth_server_process_queue(PacketProtocolLayer *ppl) goto failure; } } else if (ptrlen_eq_string(s->method, "publickey")) { - bool has_signature, success; + bool has_signature, success, send_pk_ok, key_really_ok; ptrlen algorithm, blob, signature; const ssh_keyalg *keyalg; ssh_key *key; @@ -217,7 +217,23 @@ static void ssh2_userauth_server_process_queue(PacketProtocolLayer *ppl) algorithm = get_string(pktin); blob = get_string(pktin); - if (!auth_publickey(s->authpolicy, s->username, blob)) + key_really_ok = auth_publickey(s->authpolicy, s->username, blob); + send_pk_ok = key_really_ok || + s->ssc->stunt_pretend_to_accept_any_pubkey; + + if (!has_signature) { + if (!send_pk_ok) + goto failure; + + pktout = ssh_bpp_new_pktout( + s->ppl.bpp, SSH2_MSG_USERAUTH_PK_OK); + put_stringpl(pktout, algorithm); + put_stringpl(pktout, blob); + pq_push(s->ppl.out_pq, pktout); + continue; /* skip USERAUTH_{SUCCESS,FAILURE} epilogue */ + } + + if (!key_really_ok) goto failure; keyalg = find_pubkey_alg_len(algorithm); @@ -227,16 +243,6 @@ static void ssh2_userauth_server_process_queue(PacketProtocolLayer *ppl) if (!key) goto failure; - if (!has_signature) { - ssh_key_free(key); - pktout = ssh_bpp_new_pktout( - s->ppl.bpp, SSH2_MSG_USERAUTH_PK_OK); - put_stringpl(pktout, algorithm); - put_stringpl(pktout, blob); - pq_push(s->ppl.out_pq, pktout); - continue; /* skip USERAUTH_{SUCCESS,FAILURE} epilogue */ - } - sigdata = strbuf_new(); ssh2_userauth_server_add_session_id(s, sigdata); put_byte(sigdata, SSH2_MSG_USERAUTH_REQUEST); diff --git a/sshserver.h b/sshserver.h index 129d6fec..349f7010 100644 --- a/sshserver.h +++ b/sshserver.h @@ -16,6 +16,8 @@ struct SshServerConfig { unsigned long ssh1_cipher_mask; bool ssh1_allow_compression; + + bool stunt_pretend_to_accept_any_pubkey; }; Plug *ssh_server_plug( diff --git a/unix/uxserver.c b/unix/uxserver.c index b063e50e..ae29b980 100644 --- a/unix/uxserver.c +++ b/unix/uxserver.c @@ -782,6 +782,8 @@ int main(int argc, char **argv) filename_free(logfile); conf_set_int(conf, CONF_logtype, LGTYP_SSHRAW); conf_set_int(conf, CONF_logxfovr, LGXF_OVR); + } else if (!strcmp(arg, "--pretend-to-accept-any-pubkey")) { + ssc.stunt_pretend_to_accept_any_pubkey = true; } else { fprintf(stderr, "%s: unrecognised option '%s'\n", appname, arg); exit(1);