Protecting SSH from brute force attacks
http://www.h-online.com/security/Protecting-SSH-from-brute-force-attacks...
24 July 2009, 09:21
Introduction DenyHosts fail2ban Recent
Protecting SSH from brute force attacks
Quick and simple protection from login attacks for SSH
Shield and hammer
by Daniel Bachfeld
Using just open source tools and a few tweaks, it is possible to detect and block suspicious login attempts.
Many people who run servers with SSH access and password authentication get butterflies when it comes to security. If a glance at the server logs shows high volumes of failed logins by automated scripts, it's natural to wonder whether a carefully selected password is going to be adequate to fend off future brute force attacks. Recent attacks on a number of security sites illustrate that the people who run them don't always take their own advice.
Simple measures can repel repeated cracking attempts. There are tools available which count failed logins from specific IP addresses and block further access once a set threshold is reached. These tools utilise a range of approaches for dealing with unwanted attention.
Principles
Access controls for TCP connections can be implemented on Unix and BSD systems using TCP wrappers. These switch between the TCP/IP stack and the actual service. Traditionally, this occurs in conjunction with the (x)inetd super-server daemon, which first passes incoming connections to the TCP wrapper. The former can, for example, log connections or block connection attempts from individual IP addresses. Which addresses are allowed and which are blocked is specified in the /etc/hosts.allow and /etc/hosts.deny files. Only if all the relevant boxes are ticked does the wrapper launch the service program and pass it the open connection. Some services, such as OpenSSH, are already linked against the libwrap wrapper library, which performs this same function, and do not therefore require an intermediary. You can test whether your OpenSSH daemon is linked against the libwrap library and therefore evaluates hosts.deny using ldd /usr/sbin/sshd.
A server log overflowing with messages like this will have many administrators sweating.
ZoomA server log overflowing with messages like this will have many administrators sweating.
Another approach to blocking unwanted access in Linux is the netfilter firewall, the rules/tables for which are configured using the iptables userland tool. Applications are also able to add rules in order to help keep attackers at bay. Tools differ in the way they collect information on suspicious login attempts. Some search the log files at regular intervals for information on failed authentication attempts, others simply count the number of connection attempts from a given IP address.
All blocking tools which evaluate log files at regular intervals suffer from the problem of not being able to react to attacks in real time. As long as an attacker is running through names and passwords manually they are able to keep up, but as soon as automated scripts for conducting high-speed assaults come into play, they tend to be too slow and respond too late. In tests we observed attacks in which dozens of failed login attempts appeared in the log within just a few seconds – it took the tools around 40 seconds before they sprang into action. It is possible to reduce the intervals at which log files are evaluated, but doing so can cause the tools to hog resources.
They are also susceptible to crafted log entries – attackers can insert specific entries into the log remotely using crafted user names or other calls to trick the tools into blocking legitimate IP addresses (details on this can be found in Attacking Log analysis tools).
Next: DenyHosts
Read comments (3 comments)
or you can use single packet authorization
How about SSHGUARD?
Port knocking...
DenyHosts
By default the DenyHosts Python script, which is available as an Ubuntu package, checks the /var/log/auth.log syslog fie every 30 seconds for suspicious-looking SSH login attempts (DAEMON_SLEEP = 30s) and adds any dodgy IP addresses it finds to the /etc/hosts.deny file. The number of failed login attempts required before an IP address is added to the file is set in /etc/denyhosts.conf. This file allows users to set separate thresholds for failed logins with non-existent user names (DENY_THRESHOLD_INVALID) and for logins with a valid user name, but the wrong password (DENY_THRESHOLD_VALID). This allows the script to react more quickly to an attacker trying out user names (legitimate users rarely enter the wrong user name) than to a user entering the wrong password.
Users can add results from other people's systems to the list of blocked IP addresses determined from auth.log. This cloud service, which has long been a DenyHosts feature, is based on a central record of data gathered by other DenyHosts clients (SYNC_DOWNLOAD = yes). Users may also, if they wish, forward data collected on their own systems to the DenyHost server (SYNC_UPLOAD = yes). In tests, the server transferred 50 IP addresses after each (user-specified) 15 minute interval for the client to add to /etc/hosts.deny.
The current version 2.6 is quick to install using sudo apt-get install denyhosts. DenyHosts runs straight away as a daemon in the background and starts automatically whenever the system is restarted. Users can safely stick with the default configuration – the only change we made was to reduce the number of failed login attempts permitted for valid accounts to 4. DenyHosts is not limited to SSH, in principle it can also protect other services which require a login or authentication such as FTP, Telnet and SMTP. In this case the service must either be started via (x)inetd or be linked against libwrap.
With the default settings, the deny-hosts file will grow continuously, which is of course highly undesirable, particularly where the cloud service is being used. DenyHosts can, however, be configured so that IP addresses which find their way into the list are deleted after a set interval and can once more attempt to establish a connection. The option PURGE_DENY = 1d, for example, sets this interval to one day. The option DAEMON_PURGE = 1d causes DenyHosts to automatically empty the list once a day. Alternatively, DenyHosts can be stopped and all existing entries purged manually using sudo denyhosts --purge. Just don't forget to restart DenyHosts afterwards.
Users wanting to try out DenyHosts on older (Ubuntu) systems should be aware that the /etc/hosts.allow and /etc/hosts.deny files are not always present on the system by default, which can cause errors when DenyHosts is run. It is simple enough to create them (with root privileges): touch /etc/hosts.deny.
Next: fail2ban
Fail2ban
Fail2ban, which is also written in Python, uses iptables, a Linux firewall tool, to block undesirable IP addresses. To do so it adds a new rule to the INPUT chain and creates a new chain with a DROP rule for each blocked host. The tool also has native support for wrappers and ipfw. As well as being able to protect SSH from large failed login volumes, it can also protect FTP and mail servers. Under Ubuntu, it can be installed using sudo apt-get install fail2ban. By default, only the rules for SSH are activated. The configuration file jail.conf in the /etc/fail2ban folder contains predefined rules for other services – they merely need to be activated as required.
fail2ban has problems determining the right number of login attempts from the log entry "messages repeated x times".
Zoomfail2ban has problems determining the right number of login attempts from the log entry "messages repeated x times".
Like DenyHosts, fail2ban searches for signs of failed login attempts in /var/log/auth.log using regular expressions. Unfortunately, on Ubuntu systems the syslog daemon throws a spanner in the works by, in most cases, writing failed login attempts to the login file in full only once, and after that simply writing "last message repeated x times". fail2ban does not know what to do with this message and consequently only counts the first attempt. This means that attackers can try their luck much more frequently than the default of six failed logins set in the configuration file would suggest.
This Ubuntu problem is well known. Deactivating syslog compression, which is responsible for collating repeated log entries into a single line, is one remedy for this problem. The standard syslog service does not, however, offer this option. DenyHosts does not suffer from this problem as it uses more sophisticated regular expressions.
At a pinch, users can reduce the maximum number of failed logins to, say, 2 in the SSH daemon's configuration options and likewise reduce the maximum number of repeats in the fail2ban settings to 2. Following two unsuccessful logins, the SSH service then drops the connection, with the result that the next attempt to connect does instance a new line in the log file, which fail2ban then recognises as a second login attempt. This means that the attacker has just four goes before being blocked by the firewall.
Compared to DenyHosts, fail2ban nonetheless has the advantage of being able to automatically unblock blocked hosts. Setting the option bantime = 600 deletes the iptables blocking rule automatically after 10 minutes.
Next: Recent
Recent
'Recent', an iptables module, is able to count TCP connection attempts to services at the packet level in real time and to block further attacks from a given IP address once a set threshold has been exceeded. This module is part of the Linux kernel and is loaded at runtime.
Recent is, however, unable to distinguish between successful and failed logins. Since real users do not repeatedly login and then log straight back out, a window of three attempts to establish an SSH connection within 60 seconds is a reasonable threshold, above which a brute force attack can be assumed. Individual settings will depend on the risk posed by targeted attacks on the server in question. With just two attempts per minute, an attacker can still try out 2880 passwords per day. A daily limit of, say, 30 can be useful in this kind of situation.
In our tests, setting the option MaxAuthTries 3 in /etc/ssh/sshd_config and defining the following iptables rules (suitable for a system with no existing iptables rules) worked well:
iptables -A INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -i eth0 -m state --state ESTABLISHED -m recent --update --seconds 60 --hitcount 2 -j REJECT --reject-with tcp-reset
The first rule uses the option --set to write and time stamp the IP address of a new connection on port 22 to the proc file /proc/net/ipt_recent/DEFAULT. The second rule uses --update to add a further time stamp and checks whether there are two time stamps within the previous 60 seconds. If this is the case, the connection is dropped. Access to the SSH server is then blocked for one minute, after which three further login attempts are permitted. In contrast to the wrapper method, these rules block SSH access only, leaving all other services accessible to attackers.
Packets registered by the 'recent' module can be viewed (with timestamps) in the /proc file system.
ZoomPackets registered by the 'recent' module can be viewed (with timestamps) in the /proc file system.
The combination of NEW and ESTABLISHED reduces the risk of spoofing attacks, in which some 'funster' fills the recent list with fake IP addresses, which may include legitimate addresses which are then blocked by the firewall. cat /proc/net/ipt_recent/DEFAULT can be used to see what addresses the firewall has seen and how often. The entire list can be deleted using echo clear > proc/net/ipt_recent/DEFAULT. Individual addresses can be removed using echo - > proc/net/ipt_recent/DEFAULT]. These functions can be combined with log analysis.
Summary
Although running DenyHosts on a system over a period of several months did not reduce the number of attempted intrusions, it did reduce their duration to less than a minute. The attackers presumably then moved on to the next system. There were no stability problems and DenyHosts offers excellent quick protection. Blocker implementation with the iptables module Recent is, however, more deterministic and more reliable. It can, however, sometimes be tricky to integrate into existing firewall rule sets.
Attackers are increasingly getting round the limit for logins from individual IP addresses by using botnets to carry out brute force attacks. In this case, each bot gets to try out the maximum permitted number of failed logins before being blocked by the system. Individual bots are able to try out passwords for one or more accounts either in parallel or sequentially. A botnet consisting of 10,000 PCs would, for example, be able to try out 30,000 passwords on a system which allowed three login attempts. The importance of selecting a password which is difficult to guess therefore remains.
The MaxStartups sshd parameter allows limiting the number of parallel connections, which at least prevents large numbers of simultaneous login attempts. This offers no help where bots try their luck sequentially, but doing so does require a much larger investment of time on the part of the attacker
Alternatively, users can move their SSH servers out of the line of fire by switching them from the standard TCP port 22 to an unusual port such as 54321. The switch to authentication by public key eliminates the risk posed by brute force attacks entirely and this is by far the most secure method of authentication. It is also, of course, the least flexible, as it requires a user always to have their key with them. One-time passwords may offer a middle way. The article One-time passwords for home users describes how to set up a server to use one-time passwords.
- jlquesada's blog
- Login to post comments