Server implementation does not check for auth before serving later requests #1175
What follows is a direct paste from a private gist used to workshop the issue a bit late last week; have completed tests/impl (from 1.17+) and will be pushing those shortly. (wanted the issue number set in stone first...:D)
We have a CVE for this issue: CVE-2018-7750.
Email from one Matthijs Kooijman (@matthijskooijman) dated 2018.03.02 notes that Paramiko's server implementation may be connected to by clients that do not implement the auth step, and happily serves up commands/etc to such un-authed clients. He found that AsyncSSH (another Python lib that does not use Paramiko) has the same issue. Finally, he states the RFC is unclear as to whether this is purposeful.
Let's double check both the RFCs and then our favorite reference implementation, OpenSSH.
Should neither provide a useful clue, my gut says the server implementation should track whether we've sent
tl;dr it is indeed kinda vague, there are two kinda-disagreeing undercurrents, neither of which are ironclad:
My old friend and the only C codebase I have any familiarity with whatsoever, openssh-portable...
After all the below, the tl;dr seems to be:
Testing with live OpenSSH server
Proving this with a live install is interesting:
Doing nothing certainly seems like a bad idea: this is clearly a massive security flaw, and the only reason I did all the above investigation is because software has an irritating history of "but I was relying on that bug / looseness in the spec / whatever!". Given the main reference implementation disallows it, I'm inclined to assume nobody could possibly rely on this.
So there's two obvious fixes for Paramiko:
My gut says to take a quick stab at the 1st approach but to fall back to the
Either way, re: the actual action to take seems poorly defined, but esp given OpenSSH simply spits out a bunch of question marks and not a "useful" error; the RFCs (4250, 4254) list only 4 default 'error' types, of which
The text was updated successfully, but these errors were encountered:
A later note for testing: in addition to responding to
Those are just responded to with
Also also, I am finding that there are some Travis-level issues outstanding for most recent branches, orthogonal to this ticket (python 3.7-dev is exploding for no good reason) so this will not appear to go green there until I tackle that afterwards.
More notes: in addition to writing the about-to-be-pushed tests, I also executed a standalone set of scripts provided by Matthijs, with the same net effect & result ("succeeds", as in the channel opens, without the fix; "fails", with the correct exception, with the fix.)
This is now on PyPI as Paramiko versions 1.17.6, 1.18.5, 2.0.8, 2.1.5, 2.2.3, 2.3.2, and 2.4.1.
Side note: I cannot bloody imagine doing this level of back and forth branch-wankery on Subversion. Very glad git has been my friend the last decade or so.
@six8 I probably didn't share it inline before due to sensitivity reasons but at this point with the patch out, I don't see why not. It's pretty innocuous either way:
#!/usr/bin/env python import paramiko import logging hostname = "localhost" port = 2200 skip_auth = True try: logging.basicConfig(level=logging.DEBUG) client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.WarningPolicy()) # Override the _auth method to let Paramiko skip the auth step if skip_auth: client._auth = lambda *args, **kwargs: None client.connect(hostname, port=port) client.exec_command('ls') finally: client.close()