sshnet / SSH.NET

SSH.NET is a Secure Shell (SSH) library for .NET, optimized for parallelism.
http://sshnet.github.io/SSH.NET/
MIT License
3.88k stars 919 forks source link

Remove SHA-1 Signature Support #1306

Open jacobslusser opened 4 months ago

jacobslusser commented 4 months ago

Problem Statement

This item is to track the removal of SHA-1 as a cryptographic signature (HMAC) option from SSH.NET. Nist formally deprecated SHA-1 in 2011 (source). The OpenSSH project also officially dropped support for SHA-1 in 2020 (source).

TL;DR: SHA-1 is considered insecure and we should remove it as a supported signature.

Proposal

The following would be removed from the codebase:

Key Exhange Methods

Host Key Algorithms

Impact

I don't see a compatibility concern with this change because even very old servers would still support more modern algorithms than those being removed. So, it would really only affect someone connecting to a really, really old SSH server (i.e. running pre-2010s era algorithms). Those who have that need should 1) realize that their connection is not secure and stop doing that immediately, and 2) can continue to use one of our older library versions.

Additional Considerations

The SHA-1 (and MD5) algorithms are also used in message authentication codes, however, those are not listed above because they play a much lesser role in security and are used only after a secure connection has been established. However, if we think those should be in scope also, that's fine too.

Feedback welcome.

WojciechNagorski commented 4 months ago

I agree with your proposal.

Rob-Hague commented 4 months ago

AFAIK OpenSSH dropped SHA-1 algorithms from its default server config, but not from the client.

For reference, with:

ssh -V

OpenSSH_9.3p1 Ubuntu-1ubuntu3.2, OpenSSL 3.0.10 1 Aug 2023
```bash ssh -Q sig ssh-ed25519 sk-ssh-ed25519@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 sk-ecdsa-sha2-nistp256@openssh.com webauthn-sk-ecdsa-sha2-nistp256@openssh.com ssh-dss ssh-rsa rsa-sha2-256 rsa-sha2-512 ``` ```bash ssh -Q kex diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group14-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 curve25519-sha256 curve25519-sha256@libssh.org sntrup761x25519-sha512@openssh.com ``` ```bash ssh -Q cipher 3des-cbc aes128-cbc aes192-cbc aes256-cbc aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com chacha20-poly1305@openssh.com ``` ```bash ssh -Q mac hmac-sha1 hmac-sha1-96 hmac-sha2-256 hmac-sha2-512 hmac-md5 hmac-md5-96 umac-64@openssh.com umac-128@openssh.com hmac-sha1-etm@openssh.com hmac-sha1-96-etm@openssh.com hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com hmac-md5-etm@openssh.com hmac-md5-96-etm@openssh.com umac-64-etm@openssh.com umac-128-etm@openssh.com ```

And here is what PuTTY 0.79 sends:

(I took the message bytes from a packet capture and deserialized them into a KeyExchangeInitMessage, then dumped as HTML with LINQPad)
KeyExchangeInitMessage
SSH_MSG_KEXINIT
CompressionAlgorithmsClientToServer
String[3] 
none
zlib
zlib@openssh.com
CompressionAlgorithmsServerToClient
String[3] 
none
zlib
zlib@openssh.com
CookieD3 EB CA 3B F0 5E 12 EE 7E 33 0A 76 3C AA 19 F8
EncryptionAlgorithmsClientToServer
String[16] 
aes256-ctr
aes256-cbc
rijndael-cbc@lysator.liu.se
aes192-ctr
aes192-cbc
aes128-ctr
aes128-cbc
chacha20-poly1305@openssh.com
aes128-gcm@openssh.com
aes256-gcm@openssh.com
3des-ctr
3des-cbc
blowfish-ctr
blowfish-cbc
arcfour256
arcfour128
EncryptionAlgorithmsServerToClient
String[16] 
aes256-ctr
aes256-cbc
rijndael-cbc@lysator.liu.se
aes192-ctr
aes192-cbc
aes128-ctr
aes128-cbc
chacha20-poly1305@openssh.com
aes128-gcm@openssh.com
aes256-gcm@openssh.com
3des-ctr
3des-cbc
blowfish-ctr
blowfish-cbc
arcfour256
arcfour128
FirstKexPacketFollowsFalse
KeyExchangeAlgorithms
String[19] 
sntrup761x25519-sha512@openssh.com
curve448-sha512
curve25519-sha256
curve25519-sha256@libssh.org
ecdh-sha2-nistp256
ecdh-sha2-nistp384
ecdh-sha2-nistp521
diffie-hellman-group-exchange-sha256
diffie-hellman-group-exchange-sha1
diffie-hellman-group18-sha512
diffie-hellman-group17-sha512
diffie-hellman-group16-sha512
diffie-hellman-group15-sha512
diffie-hellman-group14-sha256
diffie-hellman-group14-sha1
rsa2048-sha256
rsa1024-sha1
diffie-hellman-group1-sha1
ext-info-c
LanguagesClientToServer
String[1] 
 
LanguagesServerToClient
String[1] 
 
MacAlgorithmsClientToServer
String[8] 
hmac-sha2-256
hmac-sha1
hmac-sha1-96
hmac-md5
hmac-sha2-256-etm@openssh.com
hmac-sha1-etm@openssh.com
hmac-sha1-96-etm@openssh.com
hmac-md5-etm@openssh.com
MacAlgorithmsServerToClient
String[8] 
hmac-sha2-256
hmac-sha1
hmac-sha1-96
hmac-md5
hmac-sha2-256-etm@openssh.com
hmac-sha1-etm@openssh.com
hmac-sha1-96-etm@openssh.com
hmac-md5-etm@openssh.com
MessageNameSSH_MSG_KEXINIT
MessageNumber20
Reserved0
ServerHostKeyAlgorithms
String[9] 
ssh-ed25519
ssh-ed448
ecdsa-sha2-nistp256
ecdsa-sha2-nistp384
ecdsa-sha2-nistp521
rsa-sha2-512
rsa-sha2-256
ssh-rsa
ssh-dss

Based on this I think we could add a few missing diffie-hellman-group KEX algorithms, should remove some ciphers e.g. twofish, arcfour, cast. And I'd be in favour of removing hmac-ripemd160 (so we can drop the dependency on SshNet.Cryptography). But as for dropping SHA-1 from the client, I'm not convinced.

scott-xu commented 4 months ago

BTW, I think we can delete hmac-ripemd160 and hmac-ripemd160@openssh.com from SSH.NET

BoronBGP commented 4 months ago

I've been using SSH.net to help connect to old routers where I work for (SHA-1/ssh-rsa support is one of the reasons I chose it). I would be very sad to see this go as im actively using this functionality for hundreds of client routers and would have to stay running an old version of the library which is unideal. I think it would be far better to disable SHA-1/ssh-rsa by default but optionally enable it like in the OpenSSH client

jacobslusser commented 4 months ago

I've been using SSH.net to help connect to old routers where I work for (SHA-1/ssh-rsa support is one of the reasons I chose it). I would be very sad to see this go as im actively using this functionality for hundreds of client routers and would have to stay running an old version of the library which is unideal. I think it would be far better to disable SHA-1/ssh-rsa by default but optionally enable it like in the OpenSSH client

Thank you for letting us know that.

jscarle commented 4 months ago

Perhaps we could add an obsolete or deprecated warning? Or make it opt-in in a very intentional manner? Ideas?

WojciechNagorski commented 4 months ago

We can use .Net switch to enable or disable SHA1: https://learn.microsoft.com/en-us/dotnet/api/system.appcontext.setswitch?view=net-8.0

The AppContext class enables library writers to provide a uniform opt-out mechanism for new functionality for their users. It establishes a loosely coupled contract between components in order to communicate an opt-out request. This capability is typically important when a change is made to existing functionality. Conversely, there is already an implicit opt-in for new functionality.

jscarle commented 4 months ago

I like that idea, but two things. There are quirks for testing that must be taken into account and there should be a conscious naming convention for all switches that may be included in the future.

Rob-Hague commented 4 months ago

I don't think we should disable anything by default that OpenSSH doesn't. I would much rather follow their lead on this.

We have already seen problems relating to not doing SHA-1 by default: #1283

If there is motivation to tighten the security, we should rather remove md5, arcfour and the other non-standard algorithms we have defined.