Skip to content

Commit

Permalink
Partially mitigate StrictHostKeyChecking=no issue
Browse files Browse the repository at this point in the history
From issue #696:

  The hardcoded -o StrictHostKeyChecking=no everywhere is a big SecOps
  no-no. It's quite feasible an attacker could wind up with an IP
  address you neglect to change after relinquishing, and have an entire
  host config hand-delivered to him to inspect for vulnerabilities. He
  wouldn't be able to MITM the the deployment, but obtaining what is
  essentially a dump of the host's whole filesystem is still pretty
  disastrous, from a defensive standpoint.

I by myself have been guilty of using this (added this to the Hetzner
backend), because I did actually misunderstand the meaning of setting
this option to no. My understanding was that it will refuse to connect
whenever an existing host key is different from that in known hosts.

However, this turns out to be only true for keyboard interactive or
password authentication and if we're using pubkey auth, OpenSSH will
happily connect.

Now the real fix for this (already deploying with a pre-generated host
key) is a bit more involved, but we can mitigate this for now, because
since OpenSSH 7.5 there is the "accept-new" option to
StrictHostKeyChecking, which does exactly what I thought "no" would do:

  If this flag is set to ``accept-new'' then ssh will automatically add
  new host keys to the user known hosts files, but will not permit
  connections to hosts with changed host keys.

Signed-off-by: aszlig <aszlig@nix.build>
  • Loading branch information
aszlig committed Oct 20, 2018
1 parent 72f8770 commit 4917e40
Show file tree
Hide file tree
Showing 5 changed files with 6 additions and 6 deletions.
2 changes: 1 addition & 1 deletion nix/ssh-tunnel.nix
Expand Up @@ -87,7 +87,7 @@ with lib;
remoteCommand = mkAddrConf v.remoteTunnel v.remoteIPv4 v.localIPv4;

in "ssh -i ${v.privateKey} -x"
+ " -o StrictHostKeyChecking=no"
+ " -o StrictHostKeyChecking=accept-new"
+ " -o PermitLocalCommand=yes"
+ " -o ServerAliveInterval=20"
+ " -o LocalCommand='${localCommand}'"
Expand Down
2 changes: 1 addition & 1 deletion nixops/backends/digital_ocean.py
Expand Up @@ -76,7 +76,7 @@ def get_ssh_flags(self, *args, **kwargs):
super_flags = super(DigitalOceanState, self).get_ssh_flags(*args, **kwargs)
return super_flags + [
'-o', 'UserKnownHostsFile=/dev/null',
'-o', 'StrictHostKeyChecking=no',
'-o', 'StrictHostKeyChecking=accept-new',
'-i', self.get_ssh_private_key_file(),
]

Expand Down
4 changes: 2 additions & 2 deletions nixops/backends/hetzner.py
Expand Up @@ -170,14 +170,14 @@ def get_ssh_flags(self, *args, **kwargs):
["-o", "LogLevel=quiet",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "GlobalKnownHostsFile=/dev/null",
"-o", "StrictHostKeyChecking=no"]
"-o", "StrictHostKeyChecking=accept-new"]
if self.state == self.RESCUE else
# XXX: Disabling strict host key checking will only impact the
# behaviour on *new* keys, so it should be "reasonably" safe to do
# this until we have a better way of managing host keys in
# ssh_util. So far this at least avoids to accept every damn host
# key on a large deployment.
["-o", "StrictHostKeyChecking=no",
["-o", "StrictHostKeyChecking=accept-new",
"-i", self.get_ssh_private_key_file()]
)

Expand Down
2 changes: 1 addition & 1 deletion nixops/backends/libvirtd.py
Expand Up @@ -92,7 +92,7 @@ def get_ssh_private_key_file(self):

def get_ssh_flags(self, *args, **kwargs):
super_flags = super(LibvirtdState, self).get_ssh_flags(*args, **kwargs)
return super_flags + ["-o", "StrictHostKeyChecking=no",
return super_flags + ["-o", "StrictHostKeyChecking=accept-new",
"-i", self.get_ssh_private_key_file()]

def get_physical_spec(self):
Expand Down
2 changes: 1 addition & 1 deletion nixops/backends/none.py
Expand Up @@ -80,7 +80,7 @@ def get_ssh_private_key_file(self):
def get_ssh_flags(self, *args, **kwargs):
super_state_flags = super(NoneState, self).get_ssh_flags(*args, **kwargs)
if self.vm_id and self.cur_toplevel and self._ssh_public_key_deployed:
return super_state_flags + ["-o", "StrictHostKeyChecking=no", "-i", self.get_ssh_private_key_file()]
return super_state_flags + ["-o", "StrictHostKeyChecking=accept-new", "-i", self.get_ssh_private_key_file()]
return super_state_flags

def _check(self, res):
Expand Down

0 comments on commit 4917e40

Please sign in to comment.