briandfoy / net-ssh-perl

Development on the Net::SSH::Perl module to support latest ciphers, key exchange mechanisms, etc.
Other
4 stars 1 forks source link

Net::SSH::Perl ignores host key mismatch #26

Open briandfoy opened 1 year ago

briandfoy commented 1 year ago

This ticket was imported from rt.cpan.org 54161

Distribution name and version: Net-SSH-Perl-1.34 Perl version: v5.10.0 built for i486-linux-gnu-thread-multi Operating System vendor and version: Debian GNU/Linux 5.0.3 (Linux 2.6.24)

Most SSH clients check the change of the host key for security reason. These checks protect connections against the Man-in-the-middle attacks. But, as for Net::SSH::Perl, this check doesn't work well. This library silently accepts the changed key and connects to the host.

Alice, connects to bob.example.org by the code like:

use Net::SSH::Perl; my $ssh = Net::SSH::Perl->new("bob.example.org") or die; ...

Bob, the owner of the SSH host bob.example.org. Mallory, an attacker.

(1) Before the change of the host key.

alice% cat ~/.ssh/known_hosts2 bob.example.org ssh-dss AAAA...(The key of Bob)

(2) Someday the host key of bob.example.org changed (e.g. cracked by the attacker Mallory).

Net::SSH::Perl ignores this change, and silently adds a new entry.

alice% cat ~/.ssh/known_hosts2 bob.example.org ssh-dss AAAA...(The key of Bob) bob.example.org ssh-dss AAAA...(The key of Mallory)

If Alice tries to connect to bbb.example.org with OpenSSH client 5.1p1 (instead of Net::SSH::Perl), she will be warned:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)!

In Net::SSH::Perl::check_host_key ,

my $status = _check_host_in_hostfile($host, $u_hostfile, $key); unless (defined $status && $status == HOST_OK) { $status = _check_host_in_hostfile($host, $s_hostfile, $key); }

The first call of _check_host_in_hostfile($host, $u_hostfile, $key) returns HOST_CHANGED, but second call of _check_host_in_hostfile($host, $s_hostfile, $key) overwrite it by HOST_NEW.

if ($status == HOST_OK) { $ssh->debug("Host '$host' is known and matches the host key."); } elsif ($status == HOST_NEW) { if ($ssh->{config}->get('interactive')) { (snip) } $ssh->debug("Permanently added '$host' to the list of known hosts."); _add_host_to_hostfile($host, $u_hostfile, $key); } else { croak "Host key for '$host' has changed!"; }

So the second case is selected, silently added the changed key to $u_hostfile if not "interactive" setting.

In Net::SSH::Perl::check_host_key , my $status = _check_host_in_hostfile($host, $u_hostfile, $key);

I think the default behavior for HOST_NEW (silently adding a new key) is very insecure.