[Tutorial] Interested in increasing the security of your server? Read this. (sshd hardening)
This topic applies to the OpenSSH software in particular, which is distributed with Redhat and CentOS Linux.
Requirements:
[LIST]
ability to log into the shell via ssh
ability to work from the command line to edit files, restart services
BEGINNER
What is ssh?
ssh stands for Secure Shell, and is primarily used for acquiring interactive shell access on servers. Data transmitted via ssh is encrypted. This protects sensitive information from eavesdropping, such as the transmission of your username and password information upon logging in, and commands issued throughout the duration of your session. Secure Shell supercedes older protocols such as telnet, which sent information over the network unencrypted.
With shell access, users and system administrators can run a wide variety of commands. This makes the sshd service a prime target of spammers, bots, and the like.
By default, sshd:
[LIST]
does not restrict which IP addresses can connect to it
does not restrict which users can authenticate (including the root user)
uses password authentication instead of public key auth
This means that:
[LIST]
vulnerabilities in sshd could allow someone to remotely gain access to your server by exploiting a bug in the software
brute force attempts against sshd could allow someone to gain access to your server through a weak password
aggressive, prolonged brute force attempts against sshd can cause server stability issues
This tutorial will explore preventive measures that can be put in place by the server admistrator for the purpose of mitigating these issues.
All that is required is the ability to issue very basic commands, such as editing a file. Additionally, each of these measures should be applied. Selecting only a few is not as beneficial as applying each.
Managing shell access
You can restrict who can log into the shell via WHM >> Manage Shell Access. Information on this feature can be found here:
INTERMEDIATE
Changing the sshd port
While not a security measure, changing the port that sshd listens on can provide a few benefits. For one, it requires more effort for someone to locate the port that sshd listens on. Secondly, it prevents the server from being overwhelmed by brute force attacks that rely on using the default sshd port of 22. Both of these things can be prevented by filtering access, but this is still helpful in cases where the filter is either not enabled, or misapplied.
Keep in mind that local users can use utilities such as "ss" or "netstat" or other means to determine which ports that services listen on.
NOTE: Anyone on the server can bind to ports 1024 and above. Only root can bind to ports below 1024. As such, it is imperative to use an available port below 1024.
To find a free port, start by looking for used ports:
The command works as follows:
All of these commands have man pages that explain their usage. The following is a list of commonly used ports. These should not be used since they are used by other services:
Any other unused port below 1024 is fine. Restrict host access There are various ways in which access can be restricted to sshd. By restricting which users and hosts/networks that can log in, the impact of stolen credentials may be minimized. You can restrict which hosts/networks can access sshd via proper firewalling. Linux provides firewall software called "iptables". What follows is an example of allowing just 1 particular IPv4 address to connect to sshd while denying all others:
An explanation of the first command is as follows:
An explanation of the second command is as follows:
In order to make the rules persist across reboots, the ruleset must be saved:
An explanation of the command is as follows:
Restrict root access By default, root can log into the shell. It is a very common practice to log into the shell directly as root, but is a very bad idea to do so for the following reasons: [LIST] If sshd is trojaned to record usernames and passwords, your root password has now been compromised (though it could be trivially compromised in other ways)
If sshd is logged into from a hacked machine that is recording credentials, your root password has now been compromised
The first example is very common. Imagine this scenario: a remote attacker exploits a vulnerability in a user's PHP script (e.g., a popular CMS, or a WordPress plugin). Then they upload a kernel or other exploit to the server and execute it, which provides them with root access.
Now root access has been obtained, but the attacker still does not know the server's root password, or the passwords of any other accounts for that matter. There are a number of ways in which that information could be obtained, and a popular method is to replace the existing ssh daemon with one that records the username and password information of users as they log in. This information is especially useful to an attacker when passwords are reused, which will be discussed in further detail later.
Preventing the root user from logging in can be done by setting this line in /etc/ssh/sshd_config:
then restarting the sshd service. NOTE: Before doing this, be sure that you have an account that can obtain root access (such as via su or sudo). Restrict user access Another method that can be used to restrict logins via sshd is with the "AllowUsers" option in /etc/ssh/sshd_config . This option allows you to specify a list of users that can log into the shell. Only these users will be able to log in, and no one else. To permit only the user "alice", you'll need to edit /etc/ssh/sshd_config and add the following line:
then restart sshd. NOTE: Before doing this, be sure that the alice account can obtain root access (such as via su or sudo) if it will be the account you intend to use for escalating to root. ADVANCED Before we discuss using ssh keys instead of passwords, let's cover why password authentication contains inherent weaknesses. Password reuse This is the practice of using the same password for more than one resource, such as having 5 servers with the same root password. This is temporarily convenient for admins, but potentially devastating if someone obtains the password for just one of the servers. Do not use the same password for any account - not just root. All passwords should be unique, and never used again after being changed. Consider the potential consequences if your root password is the same as that of your Gmail account, or bank, etc. Use a "password safe" type of application. This allows you to store all of your passwords in a central location, which you only need 1 password to access. A Google search will provide a number of results for freely available password safe software, including Password Safe, KeePass, and ccrypt. Poor passwords Poor passwords greatly contribute to compromised accounts and compromised servers. Poor passwords are those which can be guessed easily, or brute forced in a reasonable amount of time. Every botnet in existence that attempts to brute force sshd is going to try the password "123456". Inevitably, some users on your server(s) will use (or try to use) that and other equally poor password choices. You can prevent users from using poor passwords for a number of services via WHM >> Password Strength Configuration. This feature is documented here: ~/.ssh/id_rsa.pub = public key ~/.ssh/id_rsa = private key
2) On the server that you want to ssh into, create a file at ~/.ssh/authorized_keys and place the contents of id_rsa.pub inside. You may need to create the ~/.ssh directory first. Give it permissions of 0700. Give the permissions of the authorized_keys file 0600. Now attempt to log into the server via the ssh key. On the server that you want to ssh from:
You should be prompted to enter the password for the key, and then be logged into the shell. If that works, and your user has the ability to obtain root access via su or sudo, you can now disable password authentication for sshd:
sshd best practices summary [LIST] deny all, permit by exception (iptables or tcpwrappers, AllowUsers)
never log into sshd as root (PermitRootLogin no)
use strongly passworded ssh keys instead of password auth (PasswordAuthentication no)
remove temporary accounts, such as those used by 3rd party support companies
change any passwords used by 3rd party support users
never reuse passwords
rotate passwords periodically, if you use them
rotate ssh keys periodically
use WHM >> Configure Security Policies
configure a remote syslog server. that way if you do get hacked, you still have logs safely stored at another location
Questions? Comments? Corrections? Let us know your thoughts!
# netstat -ntl | awk '{print $4}' | grep -v ^127.0.0.1: | cut -d : -f 2 | grep ^[0-9] | sort -n | uniq | awk '$1 < 1024'
The command works as follows:
netstat -ntl : show listening (-l) TCP (-t) ports, and do not convert port numbers into service names (-n)
awk '{print $4}' : display the 4th field of output
grep -v ^127.0.0.1: : do not display information about the loopback IP address (127.0.0.1) in the output
cut -d : -f 2 : using ':' as the delimiter, print the second field of output
grep ^[0-9] : show only lines that begin (^) with the numbers 0 through 9
sort -n : sort the output numerically
uniq : do not display duplicate lines
awk '$1 < 1024' : print only numbers that are less than 1024
All of these commands have man pages that explain their usage. The following is a list of commonly used ports. These should not be used since they are used by other services:
21 (ftp)
22 (ssh)
25 (smtp)
26 (alternate smtp port)
53 (dns)
80 (http)
110 (pop)
143 (imap)
443 (ssl)
465 (smtps)
587 (smtp)
993 (imaps)
995 (pop3s)
Any other unused port below 1024 is fine. Restrict host access There are various ways in which access can be restricted to sshd. By restricting which users and hosts/networks that can log in, the impact of stolen credentials may be minimized. You can restrict which hosts/networks can access sshd via proper firewalling. Linux provides firewall software called "iptables". What follows is an example of allowing just 1 particular IPv4 address to connect to sshd while denying all others:
# iptables -I INPUT -p tcp -s 1.2.3.4 --dport 22 -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j DROP
An explanation of the first command is as follows:
iptables : this is the iptables utility
-I : insert a rule...
INPUT : ...into the INPUT table
-p : specify the protcol...
tcp : ...as the TCP protocol
-s : specify the source IP address...
1.2.3.4 : ...as 1.2.3.4
--dport : specify the destination port...
22 : ...as 22
-j : jump to...
ACCEPT : the ACCEPT target
An explanation of the second command is as follows:
iptables : this is the iptables utility
-A : append a rule...
INPUT : ...to the INPUT table
-p : specify the protcol...
tcp : ...as the TCP protocol
--dport : specify the destination port...
22 : ...as 22
-j : jump to...
DROP : ...the DROP target
In order to make the rules persist across reboots, the ruleset must be saved:
# service iptables save
An explanation of the command is as follows:
service : this is the "service" command
iptables : this is the "iptables" service
save : this saves the current state of the iptables service
Restrict root access By default, root can log into the shell. It is a very common practice to log into the shell directly as root, but is a very bad idea to do so for the following reasons: [LIST]
PermitRootLogin no
then restarting the sshd service. NOTE: Before doing this, be sure that you have an account that can obtain root access (such as via su or sudo). Restrict user access Another method that can be used to restrict logins via sshd is with the "AllowUsers" option in /etc/ssh/sshd_config . This option allows you to specify a list of users that can log into the shell. Only these users will be able to log in, and no one else. To permit only the user "alice", you'll need to edit /etc/ssh/sshd_config and add the following line:
AllowUsers alice
then restart sshd. NOTE: Before doing this, be sure that the alice account can obtain root access (such as via su or sudo) if it will be the account you intend to use for escalating to root. ADVANCED Before we discuss using ssh keys instead of passwords, let's cover why password authentication contains inherent weaknesses. Password reuse This is the practice of using the same password for more than one resource, such as having 5 servers with the same root password. This is temporarily convenient for admins, but potentially devastating if someone obtains the password for just one of the servers. Do not use the same password for any account - not just root. All passwords should be unique, and never used again after being changed. Consider the potential consequences if your root password is the same as that of your Gmail account, or bank, etc. Use a "password safe" type of application. This allows you to store all of your passwords in a central location, which you only need 1 password to access. A Google search will provide a number of results for freely available password safe software, including Password Safe, KeePass, and ccrypt. Poor passwords Poor passwords greatly contribute to compromised accounts and compromised servers. Poor passwords are those which can be guessed easily, or brute forced in a reasonable amount of time. Every botnet in existence that attempts to brute force sshd is going to try the password "123456". Inevitably, some users on your server(s) will use (or try to use) that and other equally poor password choices. You can prevent users from using poor passwords for a number of services via WHM >> Password Strength Configuration. This feature is documented here: ~/.ssh/id_rsa.pub = public key ~/.ssh/id_rsa = private key
2) On the server that you want to ssh into, create a file at ~/.ssh/authorized_keys and place the contents of id_rsa.pub inside. You may need to create the ~/.ssh directory first. Give it permissions of 0700. Give the permissions of the authorized_keys file 0600. Now attempt to log into the server via the ssh key. On the server that you want to ssh from:
$ ssh -i ~/.ssh/id_rsa user1@example.com
You should be prompted to enter the password for the key, and then be logged into the shell. If that works, and your user has the ability to obtain root access via su or sudo, you can now disable password authentication for sshd:
- ]
- Log into WHM as root
- Click "SSH Password Authorization Tweak"
- Click "Disable Password Auth"
PermitRootLogin no # disallow direct root logins
PasswordAuthentication no # disallow password auth (use ssh keys instead)
AllowUsers alice # deny all users by default, permit by exception
Port 75 # an unused port that is < 1024. access to this port should be restricted
ListenAddress x.x.x.x # by default, sshd listens on all IPv4 and IPv6 interfaces. limit which interface is used with the LimitAddress directive
sshd best practices summary [LIST]
-
[quote="cPanelJeff, post: 1622851"> NOTE: If you accidentally misconfigure your SSH configuration file, you can access the following link to run a script on your server:
I am more paranoid than you are and make the sshd_config file write protect and check any user IP (at the login time, just in case that somebody hacked in) and lock down the server if the Ip if is not for my list. But this is just me :)0 -
Hey jeff, thanks very much man for the wonderful post :) 0 -
Hi there, thanks for the tutorial. About this: # iptables -I INPUT -p tcp -s 1.2.3.4 --dport 22 -j ACCEPT # iptables -A INPUT -p tcp --dport 22 -j DROP
An explanation of the first command is as follows:INPUT : ...into the INPUT table
I think the explanation relation to INPUT (into the INPUT table ) is unclear, should be: INPUT = is a chain or rule handles all packets that are addressed to your server - incoming traffic filter: This is the default table (if no -t option is passed)0
Please sign in to leave a comment.
Comments
3 comments