Skip to content

bcoles/ssh-probe-guard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ssh-probe-guard

License: MIT

Detect and automatically respond to Metasploit SSH login scanner fingerprinting activity on Linux hosts.

Background

When Metasploit's auxiliary/scanner/ssh/ssh_login module successfully authenticates via SSH, it immediately executes a deterministic command sequence to identify the target platform:

id                                        # Always — check if we're on a POSIX system
uname -a                                  # If "id=" found — get kernel/OS info
grep unifi.version /tmp/system.cfg        # Always on Linux — probe for Ubiquiti device

This behavior is defined in lib/metasploit/framework/ssh/platform.rb (get_platform_info method).

The grep unifi.version /tmp/system.cfg command is executed on every Linux target regardless of whether it is a Ubiquiti device. On non-Ubiquiti hosts (the vast majority), this command has zero legitimate use — making it an extremely high-fidelity indicator of Metasploit post-auth fingerprinting.

Why This Matters

SSH brute-force attacks are inherently noisy and well-defended — fail2ban, rate limiting, and account lockout policies handle them effectively. But the fingerprinting occurs after successful authentication, meaning the attacker already has valid credentials (obtained through credential stuffing, phishing, password reuse, or a prior breach). At that point, traditional brute-force defenses have already been bypassed.

The fingerprint sequence is the earliest observable indicator that a compromised credential is being used by Metasploit — and it occurs before the attacker can pivot, escalate privileges, or exfiltrate data. Detecting it enables an automated response (session kill + account lock) within ~1 second of login, turning a successful compromise into a failed one. Without fingerprint detection, the attacker's session proceeds silently with no alert beyond a normal successful login in auth.log.

Affected Metasploit Versions

The SSH post-login platform fingerprinting behavior has evolved over several Metasploit releases:

Version Date Change
~4.x (2011) 2011-10-13 Basic platform detection added to ssh_login.rb — runs id + uname -a and matches output against OS patterns (Linux, Darwin, Windows, etc.). Commit a0c34d1c.
4.16.46 2018-03-17 Platform fingerprinting code refactored from inline ssh_login.rb into shared library lib/metasploit/framework/login_scanner/ssh.rb. Commit dcb514e5.
5.0.11 2019-03-12 grep unifi.version /tmp/system.cfg introduced. Ubiquiti UniFi device detection added to the SSH login scanner's gather_proof method. This is the key detectable indicator. Commit a0b1ca17.
5.0.36 2019-06-27 GatherProof advanced option added to ssh_login.rb, allowing users to disable the fingerprinting with set GatherProof false. Enabled by default. Commit dc81adb4. Note: This only controlled the login scanner's gather_proof call. From 6.1.21 onward, GatherProof false no longer prevents the fingerprint — see the 6.1.21 entry.
6.1.21 2021-10-22 Fingerprinting code consolidated into a standalone lib/metasploit/framework/ssh/platform.rb module. A second, independent call was added in SshCommandShellBind#bootstrap to auto-detect the session platform (needed for Unix vs. Windows shell escaping). This call runs unconditionally during session setup, regardless of GatherProof. With both defaults (GatherProof true + CreateSession true), the fingerprint sequence now executes twice. Commit 726c5f26.
6.4.124+ Current No changes to the fingerprint sequence. grep unifi.version /tmp/system.cfg is still executed on every Linux target.

Summary: All Metasploit versions from 5.0.11 (March 2019) through the current release (6.4.124+) execute grep unifi.version /tmp/system.cfg on every Linux host after a successful SSH login. Since 6.1.21 (October 2021), the fingerprint runs during session bootstrap regardless of the GatherProof setting — the only way to suppress it is set CreateSession false (credential-validation-only mode). Versions prior to 5.0.11 still run id and uname -a but lack the distinctive Ubiquiti probe.

How It Works

  1. auditd rules monitor execve syscalls for id, uname, and grep (tagged msf_ssh_fp)
  2. A lightweight Python daemon tails the audit log looking for the Metasploit fingerprint pattern
  3. On detection, the daemon:
    • Kills the SSH session (finds and terminates the sshd process)
    • Locks the compromised user account (via passwd -l)
    • Optionally blocks the attacker's IP (via iptables)
    • Logs the incident to syslog and stderr

Detection latency: 200-500ms from the trigger command.

Detection Logic

Full Sequence Detection (default)

Matches all three commands within a 10-second window from the same audit session:

  • id
  • uname
  • grep with argument containing unifi.version or system.cfg

False positive rate: effectively zero on non-Ubiquiti hosts.

Strong Indicator Mode (--strong-indicator-only)

Triggers on grep unifi.version /tmp/system.cfg alone without requiring the full sequence. Lower latency but same false positive profile.

Requirements

  • Linux with auditd installed and running
  • Python 3.8+
  • Root privileges (for killing sessions and locking accounts)

Installation

sudo ./install.sh

This will:

  1. Install audit rules to /etc/audit/rules.d/ssh-probe-guard.rules
  2. Install the daemon to /usr/local/bin/ssh-probe-guard
  3. Install and enable a systemd service

Usage

As a systemd service (recommended)

sudo systemctl start ssh-probe-guard    # start
sudo systemctl status ssh-probe-guard   # check status
journalctl -u ssh-probe-guard -f        # follow logs

Manual / dry-run

# Detect and log only, no response actions
sudo python3 ssh_probe_guard.py --dry-run

# Full response: kill session + lock account
sudo python3 ssh_probe_guard.py

# Also block attacker IP via iptables
sudo python3 ssh_probe_guard.py --block-ip

# Respond to single strong indicator (faster)
sudo python3 ssh_probe_guard.py --strong-indicator-only

Options

Flag Description
--dry-run Log detections only, take no response actions
--no-kill Lock accounts but don't kill SSH sessions
--no-lock-account Kill session but don't lock the user account
--block-ip Also add an iptables DROP rule for the attacker IP
--strong-indicator-only Trigger on grep unifi.version alone
--audit-log PATH Custom audit log path

Example Output

When Metasploit's SSH login scanner authenticates and fingerprints a host, ssh-probe-guard detects the sequence, kills the session, and locks the account — all within ~1 second:

$ journalctl -u ssh-probe-guard -f
Apr 02 23:47:45 ubuntu ssh-probe-guard[21474]: ssh-probe-guard v1.1.0 starting - monitoring /var/log/audit/audit.log (lock_account=True, block_ip=False, dry_run=False)
Apr 02 23:47:55 ubuntu ssh-probe-guard[21474]: METASPLOIT SSH FINGERPRINT DETECTED - User: test, PID: 21527, PPID: 21526, Session: 33, Reason: Full fingerprint sequence (id -> uname -a -> grep unifi.version)
Apr 02 23:47:55 ubuntu ssh-probe-guard[21474]: Killing SSH session - sshd PID: 21477 (user: test, ses: 33)
Apr 02 23:47:56 ubuntu ssh-probe-guard[21474]: SSH session killed successfully (sshd PID: 21477)
Apr 02 23:47:56 ubuntu ssh-probe-guard[21474]: Locking user account: test
Apr 02 23:47:56 ubuntu usermod[21542]: lock user 'test' password
Apr 02 23:47:56 ubuntu ssh-probe-guard[21474]: Account locked via usermod: test

Uninstall

sudo systemctl disable --now ssh-probe-guard
sudo rm /usr/local/bin/ssh-probe-guard \
       /etc/audit/rules.d/ssh-probe-guard.rules \
       /etc/systemd/system/ssh-probe-guard.service
sudo augenrules --load

Limitations

  • CreateSession false: The fingerprint sequence runs in two independent code paths: once in the login scanner's gather_proof (controlled by GatherProof), and again during session bootstrap in SshCommandShellBind#bootstrap (unconditional — needed to choose between Unix/Windows shell escaping). Setting GatherProof false only skips the first call. The fingerprinting still executes during session setup. The only way to fully suppress it is set CreateSession false, which also prevents getting a session — making the scan credential-validation-only.
  • Custom login scanners: This specifically detects Metasploit's get_platform_info sequence. Other tools with different fingerprinting logic would not be detected by these exact rules (but the approach is extensible).
  • Ubiquiti devices: On actual Ubiquiti hardware, grep unifi.version /tmp/system.cfg is not anomalous. Use the full sequence detection mode (default) on Ubiquiti devices, or exclude them.

Why auditd + Daemon vs. Alternatives

Approach Pros Cons
auditd + daemon (this tool) Works on all Linux, kernel-level visibility, simple to deploy ~200-500ms latency
PAM module Hooks session start Can't monitor post-login commands
eBPF <50ms latency, lowest overhead Requires kernel 4.18+, complex development
SSH ForceCommand Simple Breaks normal SSH usage
inotify on /tmp/system.cfg Fast for file access Only catches file access, not the full command pattern

The auditd approach was chosen for maximum compatibility, reliability, and maintainability.

About

Detect and automatically respond to Metasploit SSH login scanner fingerprinting activity on Linux hosts.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors