1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

Add an option to disable the dynamic host key policy.

This mitigates CVE-2020-14002: if you're in the habit of clicking OK
to unknown host keys (the TOFU policy - trust on first use), then an
active attacker looking to exploit that policy to substitute their own
host key in your first connection to a server can use the host key
algorithm order in your KEXINIT to (not wholly reliably) detect
whether you have a key already stored for this host, and if so, abort
their attack to avoid giving themself away.

However, for users who _don't_ use the TOFU policy and instead check
new host keys out of band, the dynamic policy is more useful. So it's
provided as a configurable option.
This commit is contained in:
Simon Tatham 2020-06-11 15:57:18 +01:00
parent 555aabebde
commit 08f1e2a506
6 changed files with 35 additions and 4 deletions

View File

@ -2486,6 +2486,10 @@ void setup_config_box(struct controlbox *b, bool midsession,
HELPCTX(ssh_hklist),
hklist_handler, P(NULL));
c->listbox.height = 5;
ctrl_checkbox(s, "Prefer algorithms for which a host key is known",
'p', HELPCTX(ssh_hk_known), conf_checkbox_handler,
I(CONF_ssh_prefer_known_hostkeys));
}
/*

View File

@ -2544,6 +2544,27 @@ If the first key type PuTTY finds is below the \q{warn below here}
line, you will see a warning box when you make the connection, similar
to that for cipher selection (see \k{config-ssh-encryption}).
\S{config-ssh-prefer-known-hostkeys} Preferring known host keys
By default, PuTTY will adjust the preference order for host key
algorithms so that any host keys it already knows are moved to the top
of the list.
This prevents you from having to check and confirm a new host key for
a server you already had one for (e.g. because the server has
generated an alternative key of a type higher in PuTTY's preference
order, or because you changed the preference order itself).
However, on the other hand, it can leak information to a listener in
the network about \e{whether} you already know a host key for this
server.
For this reason, this policy is configurable. By turning this checkbox
off, you can reset PuTTY to always use the exact order of host key
algorithms configured in the preference list described in
\k{config-ssh-hostkey-order}, so that a listener will find out nothing
about what keys you had stored.
\S{config-ssh-kex-manual-hostkeys} \ii{Manually configuring host keys}
In some situations, if PuTTY's automated host key management is not

View File

@ -1256,6 +1256,7 @@ NORETURN void cleanup_exit(int);
X(BOOL, NONE, compression) \
X(INT, INT, ssh_kexlist) \
X(INT, INT, ssh_hklist) \
X(BOOL, NONE, ssh_prefer_known_hostkeys) \
X(INT, NONE, ssh_rekey_time) /* in minutes */ \
X(STR, NONE, ssh_rekey_data) /* string encoding e.g. "100K", "2M", "1G" */ \
X(BOOL, NONE, tryagent) \

View File

@ -598,6 +598,7 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);
wprefs(sesskey, "KEX", kexnames, KEX_MAX, conf, CONF_ssh_kexlist);
wprefs(sesskey, "HostKey", hknames, HK_MAX, conf, CONF_ssh_hklist);
write_setting_b(sesskey, "PreferKnownHostKeys", conf_get_bool(conf, CONF_ssh_prefer_known_hostkeys));
write_setting_i(sesskey, "RekeyTime", conf_get_int(conf, CONF_ssh_rekey_time));
#ifndef NO_GSSAPI
write_setting_i(sesskey, "GssapiRekey", conf_get_int(conf, CONF_gssapirekey));
@ -994,6 +995,7 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
}
gprefs(sesskey, "HostKey", "ed25519,ecdsa,rsa,dsa,WARN",
hknames, HK_MAX, conf, CONF_ssh_hklist);
gppb(sesskey, "PreferKnownHostKeys", true, conf, CONF_ssh_prefer_known_hostkeys);
gppi(sesskey, "RekeyTime", 60, conf, CONF_ssh_rekey_time);
#ifndef NO_GSSAPI
gppi(sesskey, "GssapiRekey", GSS_DEF_REKEY_MINS, conf, CONF_gssapirekey);

View File

@ -571,9 +571,10 @@ static void ssh2_write_kexinit_lists(
}
} else if (first_time) {
/*
* In the first key exchange, we list all the algorithms
* we're prepared to cope with, but prefer those algorithms
* for which we have a host key for this host.
* In the first key exchange, we list all the algorithms we're
* prepared to cope with, but (if configured to) we prefer
* those algorithms for which we have a host key for this
* host.
*
* If the host key algorithm is below the warning
* threshold, we warn even if we did already have a key
@ -589,7 +590,8 @@ static void ssh2_write_kexinit_lists(
for (j = 0; j < lenof(ssh2_hostkey_algs); j++) {
if (ssh2_hostkey_algs[j].id != preferred_hk[i])
continue;
if (have_ssh_host_key(hk_host, hk_port,
if (conf_get_bool(conf, CONF_ssh_prefer_known_hostkeys) &&
have_ssh_host_key(hk_host, hk_port,
ssh2_hostkey_algs[j].alg->cache_id)) {
alg = ssh2_kexinit_addalg(kexlists[KEXLIST_HOSTKEY],
ssh2_hostkey_algs[j].alg->ssh_id);

View File

@ -102,6 +102,7 @@
#define WINHELP_CTX_ssh_share "config-ssh-sharing"
#define WINHELP_CTX_ssh_kexlist "config-ssh-kex-order"
#define WINHELP_CTX_ssh_hklist "config-ssh-hostkey-order"
#define WINHELP_CTX_ssh_hk_known "config-ssh-prefer-known-hostkeys"
#define WINHELP_CTX_ssh_gssapi_kex_delegation "config-ssh-kex-gssapi-delegation"
#define WINHELP_CTX_ssh_kex_repeat "config-ssh-kex-rekey"
#define WINHELP_CTX_ssh_kex_manual_hostkeys "config-ssh-kex-manual-hostkeys"