Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 2 min read

Ten thousand failed logins matter less than one success

The scenario is fictional (RFC 5737 IPs). Detection only. A public SSH server gets thousands of failed logins a day. Alerting on all of them burns out analysts. Hidden in that noise is one line you must never miss:

The scenario is fictional (RFC 5737 IPs). Detection only.

A public SSH server gets thousands of failed logins a day. Alerting on all of them burns out analysts. Hidden in that noise is one line you must never miss:

Accepted password for root from 203.0.113.77

What you'll learn

  • How brute force and spraying differ, and what each needs
  • Picking only IPs that failed then succeeded
  • Detecting spraying by distinct target accounts
  • The Windows equivalents

The story at a glance

02:18 failed root logins (btmp), 02:20 root success (wtmp), 02:22 payload fetched.

Three attack shapes

Type Shape Detection axis
Brute force many passwords, one account, fast failures per source IP
Spraying few passwords, many accounts, slow distinct target accounts per IP
Credential stuffing leaked pairs reused known leaks, success from unknown devices

Failure followed by success

LOG=/var/log/auth.log; THRESHOLD=20
for ip in $(grep 'Failed password' $LOG | awk '{for(i=1;i<=NF;i++)if($i=="from")print $(i+1)}' | sort -u); do
  fails=$(grep -c "Failed password.*from ${ip} " "$LOG")
  succ=$(grep -c "Accepted .*from ${ip} " "$LOG")
  [ "$fails" -ge "$THRESHOLD" ] && [ "$succ" -ge 1 ] && echo "[SUSPECT] ip=${ip} fails=${fails} success=${succ}"
done

On a synthetic log it printed only [SUSPECT] ip=203.0.113.77 fails=30 success=1; an IP with 50 failures and no success was ignored.

Spraying

awk '/Failed password/ {u="";ip=""; for(i=1;i<=NF;i++){if($i=="for")u=$(i+1); if($i=="invalid")u=$(i+2); if($i=="from")ip=$(i+1)} if(ip!=""&&u!="")print ip,u}' /var/log/auth.log \
 | sort -u | awk '{c[$1]++} END{for(ip in c)print c[ip],ip}' | sort -rn | head

198.51.100.9, with 12 accounts failed once each, topped the list. Rule of thumb from the book: 10+ distinct accounts from one IP suggests spraying.

What to alert on

(1) brute force with a success, (2) spraying, (3) failures from internal segments.

Auth method hint

A pile of Failed password means that host allows password auth at all. Public-key-only hosts stay nearly silent.

Windows mapping

Failed password = 4625, Accepted = 4624, Invalid user = SubStatus 0xC0000064, wrong password = 0xC000006A (book; not tested here).

Next: Golden and Silver tickets, spotted by logs that aren't there.

Adapted from chapter 22 of my Japanese book on server defense.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.