paramiko / paramiko

The leading native Python SSHv2 protocol library.
http://paramiko.org
GNU Lesser General Public License v2.1
9.13k stars 2k forks source link

error: "sha1 is not supported by this backend for RSA signing" #2259

Open pghmcfc opened 1 year ago

pghmcfc commented 1 year ago

This issue was originally reported in Red Hat Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2214984

When connecting to an ssh server that provides an rsa host key and the host key is known (either by a known_hosts file or by previous connection attempts), paramiko fails with "cryptography.exceptions.UnsupportedAlgorithm: sha1 is not supported by this backend for RSA signing", giving the following traceback:

  File "/usr/lib/python3.9/site-packages/paramiko/client.py", line 421, in connect
    t.start_client(timeout=timeout)
  File "/usr/lib/python3.9/site-packages/paramiko/transport.py", line 699, in start_client
    raise e
  File "/usr/lib/python3.9/site-packages/paramiko/transport.py", line 2130, in run
    self.kex_engine.parse_next(ptype, m)
  File "/usr/lib/python3.9/site-packages/paramiko/kex_curve25519.py", line 64, in parse_next
    return self._parse_kexecdh_reply(m)
  File "/usr/lib/python3.9/site-packages/paramiko/kex_curve25519.py", line 130, in _parse_kexecdh_reply
    self.transport._verify_key(peer_host_key_bytes, sig)
  File "/usr/lib/python3.9/site-packages/paramiko/transport.py", line 1941, in _verify_key
    if not key.verify_ssh_sig(self.H, Message(sig)):
  File "/usr/lib/python3.9/site-packages/paramiko/rsakey.py", line 152, in verify_ssh_sig
    key.verify(
  File "/usr/lib64/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 571, in verify
    return _rsa_sig_verify(
  File "/usr/lib64/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 270, in _rsa_sig_verify
    pkey_ctx = _rsa_sig_setup(
  File "/usr/lib64/python3.9/site-packages/cryptography/hazmat/backends/openssl/rsa.py", line 213, in _rsa_sig_setup
    raise UnsupportedAlgorithm(
cryptography.exceptions.UnsupportedAlgorithm: sha1 is not supported by this backend for RSA signing.

This is with paramiko 2.12.0 on Red Hat Enterprise Linux 9 (or a clone thereof), where sha1 is not supported for cryptographic operations.

Steps to Reproduce:

  1. setup an ssh server with an rsa host key
  2. clear this host key from any known_hosts files
  3. connect twice

Actual results: the first connect succeeds, the second connect fails with the trace above.

Expected results: both connects successful

The original reporter provided a couple of attachments to help reproduce this issue, running an ssh server in a container. I can attach those and the accompanying instructions here if it's helpful.

My initial thought is that paramiko should trap this exception and treat the case the same as if the host key was not found, possibly providing some warning that that had happened so that users would understand why an existing key was ignored.

bskinn commented 1 year ago

Thanks for transferring this report over here, we never would have seen it otherwise.

If I understand correctly what's going on, this error occurs because a server is crafting its host keys with an obsolete, insecure hashing algorithm, in SHA1.

Isn't.... the best solution here to upgrade the server so that it can use a modern, secure algorithm? Instead of changing paramiko to blithely ignore a security-relevant error raised out of cryptography?

I recognize that a server host key isn't on the same level of importance as an SSL key pair, since server host keys aren't usually backed by third-party CA certs and such, but this seems like an imprudent way to handle the situation.

Rather than accepting this connection by default and warning about an obsolete key being ignored, it seems to me a better solution would be an 'opt in' flag that a user would have to specify... a skip_host_key_verification boolean or something.

What do you think?

pghmcfc commented 1 year ago

@bskinn, I've updated the bugzilla ticket with your comment so we can get the original reporter's response. I personally would be happy enough with an option to ignore this issue. Regarding updating the server, that may be very tricky in some cases, such as for an embedded device with a server that doesn't support anything more modern in terms of key algorithms.

bskinn commented 1 year ago

I've updated the bugzilla ticket with your comment so we can get the original reporter's response.

Great, thanks!

I personally would be happy enough with an option to ignore this issue.

:+1:, it seems to me that's the best approach for the 2.x maintenance line. We'd welcome a PR from anyone interested in working on it.

Do you know, would the new experimental auth strategy features allow user-side handling of this hitch? (3.2 CHANGELOG, scroll down to the first red callout.) One of the big goals of that new machinery (including some as-yet-unimplemented pieces) is to allow users to cope with their hardware weirdness themselves, instead of fixes needed upstream.

We'd also welcome help here, again from anyone interested, testing those new experimental features to see if they can resolve this.

Regarding updating the server, that may be very tricky in some cases, such as for an embedded device with a server that doesn't support anything more modern in terms of key algorithms.

I know, cognitively, that this is a problem, but I've never dealt with it myself and so I keep forgetting to consider it.

Can you help me out by providing some concrete examples of embedded devices like this? Control hardware for chemical process industry? Manufacturing equipment? IoT? Controllers in cars? The specificity will help the category stick in mind.

pghmcfc commented 1 year ago

Can you help me out by providing some concrete examples of embedded devices like this? Control hardware for chemical process industry? Manufacturing equipment? IoT? Controllers in cars? The specificity will help the category stick in mind.

I don't have anything that I use paramiko with. However, I have a couple of Ubiquity WiFi access points (which get regular updates by the way, unusual for this sort of device I think) and I can access them via openssh but I need entries like these in my ~/.ssh/config:

Host front.ap-ac-lr
  HostName front.ap-ac-lr.intranet.example.com
  User paul
  IdentityFile ~/.ssh/id_rsa
  PubkeyAcceptedAlgorithms +ssh-rsa
  RequiredRSASize 1024

Host rear.ap-ac-lr
  HostName rear.ap-ac-lr.intranet.example.com
  User paul
  IdentityFile ~/.ssh/id_rsa
  PubkeyAcceptedAlgorithms +ssh-rsa
  RequiredRSASize 1024
pghmcfc commented 1 year ago

Feedback from reporter:

Of course the best solution is to upgrade the server, but sometimes this isn't a valid option. Either because the server is a proprietary blackbox or it must be kept at a specific stable version, or, simply because noone cared to provide an update to the software to support other algorithms yet. In my case it's about jenkins, it seems only to support rsa sha1 hostkeys for the ssh configuration interface.

Sure, I'm fine with a "skip_host_key_verification" flag if this covers outdated algorithms as well (and not only stuff like mismatching fingerprints).

Thanks!

bskinn commented 1 year ago

Ok, sounds like a 'skip' option would be viable for everyone in the conversation here.

And yes, I would expect a skip flag would skip the verification entirely. Certainly that's the first implementation I'd recommend, and we would consider more granular skip-or-not controls once we determined they're not YAGNI.

I'm going to flag this for bitprophet to review at whatever point in the future he does a pass on the flag, so he can weigh in.

But, I'm confident enough in the feature to request anyone interested prepare a PR to implement this.

bskinn commented 1 year ago

@gubenkoved -- I think you're looking at the wrong part of the codebase.

id_* keys are for client authentication, confirming to the server the identity of the client seeking a connection.

The issue here is host validation -- confirming to the client that the server is who they are expecting to be connecting to.

Also, if the underlying cryptography library in the relevant context doesn't support SHA1, then I don't think it really matters if paramiko still does. OP's exception is being raised from within cryptography.

gubenkoved commented 1 year ago

Thank you for your answer, @bskinn! I've removed my comment before you replied as I realised sources of my own confusion here.

In my particular case I was able to work around this issue supplying ssh-rsa algorithm as disabled_algorithms to SSHClient.connect methods.

Additionally, I beleive similar issue can appear for the "client authentication" part of the paramiko as well. Here is the sample traceback. I also want to mention FIPS OpenSSL provider as a reason of SHA1 not being available as RSA digest algorithm in my case.

80BBFC66117F0000:error:1C8000AE:Provider routines:rsa_setup_md:digest not allowed:../../source/openssl-3.0.8-provider/providers/implementations/signature/rsa_sig.c:304:digest=sha1
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/paramiko/transport.py", line 2164, in run
    handler(self.auth_handler, m)
  File "/usr/local/lib/python3.10/dist-packages/paramiko/auth_handler.py", line 395, in _parse_service_accept
    sig = self.private_key.sign_ssh_data(blob, algorithm)
  File "/usr/local/lib/python3.10/dist-packages/paramiko/rsakey.py", line 126, in sign_ssh_data
    sig = self.key.sign(
  File "/usr/local/lib/python3.10/dist-packages/cryptography/hazmat/backends/openssl/rsa.py", line 513, in sign
    return _rsa_sig_sign(self._backend, padding, algorithm, self, data)
  File "/usr/local/lib/python3.10/dist-packages/cryptography/hazmat/backends/openssl/rsa.py", line 275, in _rsa_sig_sign
    pkey_ctx = _rsa_sig_setup(
  File "/usr/local/lib/python3.10/dist-packages/cryptography/hazmat/backends/openssl/rsa.py", line 236, in _rsa_sig_setup
    raise UnsupportedAlgorithm(
cryptography.exceptions.UnsupportedAlgorithm: sha1 is not supported by this backend for RSA signing.