OpenSSH BlowfishSEC is an amazingly powerful yet simple tool. It works best when coupled with centralized logging, such as a syslog server. It lets you correlate events from multiple hosts and take actions based on those events.

Why Attempt to Detect SSH Break-Ins?

SSH Bruteforce attacks are incredibly common, and have just been on the increase over the years. For more details on ssh brute forcing and how to mitigate it, check out what what the SANS Internet Storm Center says about SSH brute forcing.

But some organizations cannot implement all these steps, and even after you've taken the steps recommended by SANS ISC, you might still need to be worried about attacks. I'm sure it's not uncommon for larger organizations to get millions of break-in attempts daily.

How to Detect SSH Break-Ins with SEC

I've implemented this "detection" in 3 rules which use contexts to connect them. The first rule creates the context that stores all the ssh break-in attempts. After the break-in threshold has been reached, the first rule also keeps the time window for the intrusion detection rule "sliding". Otherwise, an attack that takes a very long time or pauses before a successful break-in may not be reported.

The second rule is the threshold rule which is triggered after 1000 attempts. 1000 is arguably too low, set this as high as you'd like. A successful login by the user after the second rule has been activated will trigger an alert

The third rule is the detection of a successful login. The context ensures that it is only used after the second rule is triggered.

Because many ssh break-ins are attempted from multiple hosts (eg a botnet) we do not base thresholding on originating IP. This could lead to false positives when a bot-net attacks and then that user legitimately logs in from a non-malicious system.

These rules only look for break-ins attempts with publickey, keyboard-interactive, and password authentication. If you use eg RSA, GSSAPI Authentication, you'll need to modify the regular expression accordingly. Also, if you use IPv6 you'll need to modify the regular expression.

# create the context on the initial triggering cluster of events type=Single ptype=RegExp pattern=[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+\tsshd\[\d+\]:\s+Failed (publickey|keyboard-.+|password) for (\S+) from (\d+\.\d+\.\d+\.\d+) desc=Possible $1 brute force ssh attack on user $2 from $3 action=add SSH_BRUTE_AGAINST_$2 $0; set SSH_BRUTE_AGAINST_$2 86400; set SSH_BRUTE_AGAINST_$2_LIMIT_EXCEEDED 3600 continue=TakeNext type=SingleWithThreshold window=86400 thresh=1000 ptype=RegExp pattern=[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+\tsshd\[\d+\]:\s+Failed (publickey|keyboard-.+|password) for (\S+) from (\d+\.\d+\.\d+\.\d+) desc=Additional brute force attempt against $2 context=SSH_BRUTE_AGAINST_$2 action=add SSH_BRUTE_AGAINST_$2_LIMIT_EXCEEDED $0; set SSH_BRUTE_AGAINST_$2_LIMIT_EXCEEDED 3600; logonly "SSH brute force monitor activated for user $2" #Report Successful login after brute force attempts type=Single ptype=RegExp pattern=[^\t]+\t([^\t]+)\t[^\t]+\t[^\t]+\t[^\t]+\tsshd\[\d+\]:\s+Accepted (publickey|keyboard-.+|password) for (\S+) from (\d+\.\d+\.\d+\.\d+) desc=Investigate Possible Successful break-in against user: $3 to host: $1 using method: $2 from ip: $4 context=SSH_BRUTE_AGAINST_$3_LIMIT_EXCEEDED action=report SSH_BRUTE_AGAINST_$3 /path/to/notify/script --subject="%s" --recipient=''; delete SSH_BRUTE_AGAINST_$3; delete SSH_BRUTE_AGAINST_$3_LIMIT_EXCEEDED;

SSH Break-In Detection Caveats

  • Break-in detection is no substitute for break-in prevention. Follow the SANS ISC suggestions for SSH break-in prevention.
  • Break-In detection will do little good if the attacker is able to instanstly root the system and potentially delete any logs or notifications of their break-in. You should still keep your software up to date, and don't do stupid things like allowing root to login via ssh.
  • Consider sending the alert off-site (like to your pager or cell phone) so that it cannot easily be erased if the attacker gains root access.


comments powered by Disqus