Securing and Hardening SSH servers
SSH is the tool that many users use to manage and interact with their Unix systems. It is a vital protocol that must be protected, as SSH being compromised can be detrimental. Thankfully there are many tools and guides to help people secure their SSH servers. The tool that we will be focusing on today is ssh-audit. It is a tool that can analyze both SSH clients and servers to show insecurities and places that SSH could be stronger. For publicly accessable servers, they even have a tool on their website that will grade your SSH server security.
Most of the knowledge in this post comes from Özgür Konstantin Kazanççı’s website, and really is just re-stating it for my own memory and use.
FreeBSD
Start with making sure the system is updated (and please upgrade to FreeBSD 14.0 if you have not already done so. Here is a guide if one is needed).
pkg update
pkg upgrade
pkg install ssh-audit
Running ssh-audit localhost
will likely make you feel
bad about deploying a server in such a state. That’s okay, that is what
we are currently in the process of trying to fix. The first step is to
regenerate SSH host identification keys for higher security keys:
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
Then we need to generate our own moduli. The ones that come with most operating systems are often too short, and are vulnerable to attack. In some cases, they are just re-used and are even vulnerable to a pre-computation attack, so regenerating them is vital. Keep in mind, this process can take a very long time depending on the hardware that is generating the moduli (it took over an our on the test VM for the next section).
ssh-keygen -M generate -O bits=3072 moduli
ssh-keygen -M screen -f moduli moduli-final
mv moduli-final /etc/ssh/
Next we need to set some configuration options by putting the
following lines into our sshd_config file (located at either
/etc/ssh/sshd_config
or
/usr/local/etc/ssh/sshd_config
depending on whether you are
using the built in SSH daemon or downloaded another one from
pkg
or ports).
HostKeyAlgorithms rsa-sha2-512,rsa-sha2-256,ssh-ed25519
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com
These options restrict which kind of key exchange alrogithms and encryption algorithms can be used for our SSH host.
Finally, restart the SSH server for the changes to take effect, however, if you are managing the machine from an SSH session, do not close it until you verify that the new settings work correctly by attampting to connect from another SSH session.
service sshd restart
Void Linux
The process for hardening Void Linux’s SSH server is very similar to the previous section, however, it is worth documenting the process in my opinion.
We start by making sure our operating system and all of our binary packages are up-to-date, as well as downloading ssh-audit to see how well or how poorly SSH is currently configured.
xbps-install -Syuv
xbps-install -Sy ssh-audit
Now we run ssh-audit to see whether our SSH server is configured well
or not. Note that the IP address of the SSH server I used for this was
192.168.122.27; also the -n
flag was to turn off color
output to paste into this article better, and will not necessarily be
needed for all cases.
ssh-audit -n 192.168.122.27
# general
(gen) banner: SSH-2.0-OpenSSH_9.6
(gen) software: OpenSSH 9.6
(gen) compatibility: OpenSSH 8.5+, Dropbear SSH 2018.76+
(gen) compression: enabled (zlib@openssh.com)
# key exchange algorithms
(kex) sntrup761x25519-sha512@openssh.com -- [info] available since OpenSSH 8.5
(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76
`- [info] default key exchange since OpenSSH 6.4
(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.4, Dropbear SSH 2013.62
`- [info] default key exchange since OpenSSH 6.4
(kex) ecdh-sha2-nistp256 -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
(kex) ecdh-sha2-nistp384 -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
(kex) ecdh-sha2-nistp521 -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
(kex) diffie-hellman-group-exchange-sha256 (3072-bit) -- [info] available since OpenSSH 4.4
`- [info] OpenSSH's GEX fallback mechanism was triggered during testing. Very old SSH clients will still be able to create connections using a 2048-bit modulus, though modern clients will use 3072. This can only be disabled by recompiling the code (see https://github.com/openssh/openssh-portable/blob/V_9_4/dh.c#L477).
(kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
(kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3
(kex) diffie-hellman-group14-sha256 -- [warn] 2048-bit modulus only provides 112-bits of symmetric strength
`- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
(kex) ext-info-s -- [info] pseudo-algorithm that denotes the peer supports RFC8308 extensions
(kex) kex-strict-s-v00@openssh.com -- [info] pseudo-algorithm that denotes the peer supports a stricter key exchange method as a counter-measure to the Terrapin attack (CVE-2023-48795)
# host-key algorithms
(key) rsa-sha2-512 (3072-bit) -- [info] available since OpenSSH 7.2
(key) rsa-sha2-256 (3072-bit) -- [info] available since OpenSSH 7.2
(key) ecdsa-sha2-nistp256 -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency
`- [warn] using weak random number generator could reveal the key
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
(key) ssh-ed25519 -- [info] available since OpenSSH 6.5
# encryption algorithms (ciphers)
(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5
`- [info] default cipher since OpenSSH 6.9
(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
(enc) aes192-ctr -- [info] available since OpenSSH 3.7
(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2
(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2
# message authentication code algorithms
(mac) umac-64-etm@openssh.com -- [warn] using small 64-bit tag size
`- [info] available since OpenSSH 6.2
(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2
(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2
(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2
(mac) hmac-sha1-etm@openssh.com -- [fail] using broken SHA-1 hash algorithm
`- [info] available since OpenSSH 6.2
(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode
`- [warn] using small 64-bit tag size
`- [info] available since OpenSSH 4.7
(mac) umac-128@openssh.com -- [warn] using encrypt-and-MAC mode
`- [info] available since OpenSSH 6.2
(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode
`- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
(mac) hmac-sha2-512 -- [warn] using encrypt-and-MAC mode
`- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
(mac) hmac-sha1 -- [fail] using broken SHA-1 hash algorithm
`- [warn] using encrypt-and-MAC mode
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
# fingerprints
(fin) ssh-ed25519: SHA256:0etkEayA+4dGscclMee05Z18EDlB4TH3lyRZ8zD1ORs
(fin) ssh-rsa: SHA256:brHIQBb1RqGrM//hj7PKVjzMlCV/eoCHbloyyx5srMs
# algorithm recommendations (for OpenSSH 9.6)
(rec) -diffie-hellman-group14-sha256 -- kex algorithm to remove
(rec) -ecdh-sha2-nistp256 -- kex algorithm to remove
(rec) -ecdh-sha2-nistp384 -- kex algorithm to remove
(rec) -ecdh-sha2-nistp521 -- kex algorithm to remove
(rec) -ecdsa-sha2-nistp256 -- key algorithm to remove
(rec) -hmac-sha1 -- mac algorithm to remove
(rec) -hmac-sha1-etm@openssh.com -- mac algorithm to remove
(rec) -hmac-sha2-256 -- mac algorithm to remove
(rec) -hmac-sha2-512 -- mac algorithm to remove
(rec) -umac-128@openssh.com -- mac algorithm to remove
(rec) -umac-64-etm@openssh.com -- mac algorithm to remove
(rec) -umac-64@openssh.com -- mac algorithm to remove
# additional info
(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>
(nfo) Be aware that, while this target properly supports the strict key exchange method (via the kex-strict-?-v00@openssh.com marker) needed to protect against the Terrapin vulnerability (CVE-2023-48795), all peers must also support this feature as well, otherwise the vulnerability will still be present. The following algorithms would allow an unpatched peer to create vulnerable SSH channels with this target: chacha20-poly1305@openssh.com. If any CBC ciphers are in this list, you may remove them while leaving the *-etm@openssh.com MACs in place; these MACs are fine while paired with non-CBC cipher types.
Much like FreeBSD, there is a lot of red and yellow in the default configuration. That was to be expected, however, can be fixed by running a few commands.
First we need to change the host identification key. The following commands will change the SSH server’s remote identification, and SSH will give you an error saying “IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!” This error is occuring because we are removing the weak host identification key in favor of generating a stronger one.
cd /etc/ssh/
# Removes weak host keys
rm -f ssh_host_*
# Generates stronger RSA host key
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key -N ""
# Generates stronger ed25519 key
ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N ""
Next, we will generate our own SSH moduli; this is a critical SSH hardening step as many operating systems ship pre-computed moduli that is too short and potentially vulnerable to attacks. A minimum of 3072-bit modulus is needed for providing 128 bits of security.
This process will potentially take a while depending on the specs of the computer it is running on.
ssh-keygen -M generate -O bits=3072 moduli
ssh-keygen -M screen -f moduli moduli-final
mv moduli-final /etc/ssh
Finally add the following lines to /etc/ssh/sshd_config
HostKeyAlgorithms rsa-sha2-512,rsa-sha2-256,ssh-ed25519
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com
and restart the sshd service by running:
sv restart sshd
Now, re-running ssh-audit:
ssh-audit -n 192.168.122.27
# general
(gen) banner: SSH-2.0-OpenSSH_9.6
(gen) software: OpenSSH 9.6
(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+
(gen) compression: enabled (zlib@openssh.com)
# key exchange algorithms
(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76
`- [info] default key exchange since OpenSSH 6.4
(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.4, Dropbear SSH 2013.62
`- [info] default key exchange since OpenSSH 6.4
(kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
(kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3
(kex) diffie-hellman-group-exchange-sha256 -- [info] available since OpenSSH 4.4
(kex) ext-info-s -- [info] pseudo-algorithm that denotes the peer supports RFC8308 extensions
(kex) kex-strict-s-v00@openssh.com -- [info] pseudo-algorithm that denotes the peer supports a stricter key exchange method as a counter-measure to the Terrapin attack (CVE-2023-48795)
# host-key algorithms
(key) rsa-sha2-512 (4096-bit) -- [info] available since OpenSSH 7.2
(key) rsa-sha2-256 (4096-bit) -- [info] available since OpenSSH 7.2
(key) ssh-ed25519 -- [info] available since OpenSSH 6.5
# encryption algorithms (ciphers)
(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5
`- [info] default cipher since OpenSSH 6.9
(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2
(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2
(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
(enc) aes192-ctr -- [info] available since OpenSSH 3.7
(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
# message authentication code algorithms
(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2
(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2
(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2
# fingerprints
(fin) ssh-ed25519: SHA256:Q2qtOTp16c67r2gUCwQoft08Ze2c/hWZU3lBedWK3pY
(fin) ssh-rsa: SHA256:eAQoG/aPar0Eyy5II0/YrPx89bYGJL9hQouZ5JA7KP8
# algorithm recommendations (for OpenSSH 9.6)
(rec) +sntrup761x25519-sha512@openssh.com -- kex algorithm to append
# additional info
(nfo) Be aware that, while this target properly supports the strict key exchange method (via the kex-strict-?-v00@openssh.com marker) needed to protect against the Terrapin vulnerability (CVE-2023-48795), all peers must also support this feature as well, otherwise the vulnerability will still be present. The following algorithms would allow an unpatched peer to create vulnerable SSH channels with this target: chacha20-poly1305@openssh.com. If any CBC ciphers are in this list, you may remove them while leaving the *-etm@openssh.com MACs in place; these MACs are fine while paired with non-CBC cipher types.
Now if running with color enabled, we see a lot more green and no red with only one yellow entry that is just reminding us that both the SSH client and server must be secured to fully protect our servers.
Hardening SSH clients
Unfortunately, hardening the SSH server is not enough to mitigate all attack vectors. Some attacks only need the SSH server or SSH client to be improperly configured to be vulnerable to some attack. Thankfully hardening your SSH client for your current user can be done with the following command:
printf "\nHost *\n Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr\n KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256\n MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com\n HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com\n" > ~/.ssh/config
This command works both on FreeBSD and Void Linux; I imagine it would work on many other Unix-like operating systems as well.