Audit and harden your SSH configuration

Audit and harden your SSH configuration

SSH (Secure SHell) is a commonly used protocol for secure data communications between systems. It is rare to find systems not having this service running. As this opens up a potential gateway into the system, hardening the configuration of the SSH server is an important step in server hardening. In this guide we will focus on several common configuration options of SSH and improve it.

Client and Server

SSH has two parts: the client used for connecting to a server, and the server daemon itself. This latter one is usually the most important part in deciding how “secure” a connection may be. One example is that the server can decide if normal password based logins are allowed or denied. Even if the client has a preference, it is the server to make the final call.

The client configuration settings can be found in /etc/ssh/ssh_config (system wide) or ~/.ssh/config (per user). For the server configuration file: /etc/ssh/sshd_config. Let’s start with the SSH server itself.

Securing SSH server

Before we start making changes to our configuration, it is a good idea to make a backup.

cp /etc/ssh/sshd_config /root/sshd_config

A lesser known tip to find the value of a setting, is by querying the SSH daemon directory. This is especially useful for finding default values which may not be available in your configuration file.

sshd -T

Screenshot of output from sshd -T command to show active SSH settings

Show active and default settings of SSH daemon

Note: configuration settings and values are displayed with lowercase characters.

1. Use of X11Forwarding

The display server on the client might have a higher exposure to be attacked with X11 traffic forwarded. If forwarding of X11 traffic is not needed, disable it:

X11Forwarding no

Why disabling X11Forwarding matters: the X11 protocol was never built with security in mind. As it opens up channel back to the client, the server could send malicious commands back to the client. To protect clients, disable X11Forwarding when it is not needed.

2. Disable rhosts

While not common anymore, rhosts were a weak way to authenticate systems. By default the use of rhosts is already disabled. Make sure to check if it really is.

IgnoreRhosts yes

3. DNS hostname checking

By default, the SSH server can check if the client connecting maps back to the same combination of hostname and IP address. Use the option UseDNS to perform this basic check.

UseDNS yes

Note: this option may not work properly in all situations, or result in waiting for a timeout during the initial connection. Only use this when you are sure your internal DNS is properly configured.

4. Empty passwords

Accounts should be protected and users should be accountable. The usage of empty passwords should never be allowed for this reason. This can be disabled with the PermitEmptyPasswords option.

PermitEmptyPasswords no

5. Maximum authentication attempts

To protect against brute-force attacks on the password of a user, limit the number of attempts. Also enable monitoring for authentication failures, which starts at the half the number of maximum attempts. Use these authentication failures together with your SIEM solution, or forward them to your security administrator.

MaxAuthTries 6

Setting this value to a lower limit makes sense. By increasing the MaxAuthTries option a little bit, you can filter out more traffic that is automated, so you can block it later.

6. Public key authentication

Instead of using a normal password based login, one might opt for using public key authentication instead. Keys are considered much safer and less prone to brute-force attacks. Disable password authentication to force using keys.

PubkeyAuthentication yes

PasswordAuthentication no

7. Disable root login

It is best practice not to log in as the root user. Use a normal user account to initiate your connection instead, together with sudo. Direct root logins may result in bad accountability of the actions performed by this user account.

PermitRootLogin no

Newer versions of OpenSSH also support the value without-password. This value refers to methods like public key authentication. If your installation comes with this value, there is no reason to change it.

8. Set SSH protocol

If you are running an older system, version 1 of the SSH protocol might still be available. This version has weaknesses and should no longer be used. Therefore only enable version 2.

Protocol 2

Since version 7.0 of OpenSSH protocol 1 is automatically disabled during compile time. If your version is older than that, enforce the protocol:

9. Usage of AllowUsers and DenyUsers

When not all users should have access to the system, limit the amount of people who can actually log in. One way is to create a group (e.g. sshusers) and add people to this group. Next set the AllowGroups option to define that only these users can log in.

Other possibilities include to only allow a few users with the AllowUsers, or specifically deny users and groups with the DenyUsers, or DenyGroups. Whitelisting access, using the ‘default deny’ principle, is usually better. So when possible, use the AllowUsers or AllowGroups option.

Good to know: SSH applies the following order to determine if one can log in: DenyUsers, AllowUsers, DenyGroups, finally AllowGroups.

10. Use HashKnownHosts

Each time the SSH client connects to a server, it will store a related signature (a key) of the server. This information is stored in a file names named known_hosts. The known_hosts file itself is available in the .ssh subdirectory of the related user (on the client). In the case the signature of the server changes, SSH will protect the user by notifying about this chance. This option is useful but also has a risk. Previously it was common to store the hostname related with the key. This made it easy for worms and other malicious scripts to use this information and spread to other systems, once they had a single system compromised. To counter this, the HashKnownHosts will hash each host, so it’s not readable anymore. While being unreadable for the human eye, it still allows SSH to check for the next time you connect to the same system, as the results in the same hash.

Example output:

|1|XV5CFMH8LLIQPq7PxdBhGX7I9PA=|VKNLdODsQlJ/j4cvTZncqs9vgh0= ecdsa-sha2-nistp256 AAAAE2VjZHNhLX….dJ/RzzZLH8Hs0UgroC0=

SSH configuration test

Before restarting your daemon, test if the new configuration is correct.

sshd -t

This command should not return any text or errors. Here is an example when something does not look good:

Screenshot of sshd -t command to test SSH configuration

Make sure to test your settings first.

Read the man page

A good resource for SSH configuration settings is the man page. While this sounds like an easy tip, it is actually useful to know the man page is strong and well-maintained. With all the minor differences between releases, you should never assume what a setting does. Instead, read about the setting and see if it has recent additions. Your configuration of two years ago might already be outdated. Combine this knowledge with the output of sshd -T and you should be able to select the right option for your situation.

Do you have other SSH settings that we should cover? Let it know it in the comments!

Lynis Enterprise

Lynis Enterprise screenshot to help with system hardening

This blog post is part of our Linux security series and the mission to get Linux and Unix-based systems more secure.

Does system hardening take a lot of time, or do you have any compliance in your company? Have a look at Lynis Enterprise.

Or start today with the open source security scanner Lynis (GitHub)