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:
parent
555aabebde
commit
08f1e2a506
4
config.c
4
config.c
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
1
putty.h
1
putty.h
@ -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) \
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user