
This project explores whether modern OpenSSH reveals valid usernames through subtle response or timing differences. CVE-2016-6210 user enumeration investigation ( Welch's t-test, Cohen's d, and detection engineering ) on a controlled lab on Ubuntu 22.04.5 LTS, it also examines the traces such attempts leave behind and how they can be detected..
A reproducible re-investigation of OpenSSH username enumeration using statistical analysis.
This project re-investigates CVE-2016-6210, a documented OpenSSH timing side-channel, to determine whether it remains observable on a modern Ubuntu Server using the default PAM configuration.
Rather than assuming the published behaviour still applies, the project evaluates authentication timing measurements collected through manual probing, Hydra, and Metasploit using Welch's t-test and Cohen's d to distinguish genuine timing signals from measurement noise.
The study found no statistically significant timing difference on the tested default configuration, demonstrating the value of reproducible experimentation and evidence-based validation of published security claims.
⚠️ Legal Notice
This project was conducted entirely within a self-owned, isolated laboratory environment. All findings apply only to the tested configuration. Never test systems you do not own or have explicit written authorization to test.
User enumeration - the ability to determine whether a specific username exists on a remote system without valid credentials. It is a critical first step in the attack chain leading to account compromise:
Reconnaissance → [User Enumeration] → Password Attack → Access
↑
This project investigates here
If an attacker can distinguish "this user exists" from "this user does not exist" by analysing server responses, they can dramatically reduce the keyspace for subsequent brute force or credential stuffing attacks.
SSH is a frequent target because it is nearly universally exposed, handles password authentication, and older implementations had measurable timing differences between valid and invalid usernames (CVE-2016-6210).
This investigation asks two questions:
All testing was performed in a fully isolated host-only virtual network with no internet exposure.
| Machine | OS | Role | IP | SSH Version |
|---|---|---|---|---|
| Attacker | Kali Linux 2024.1 | Offensive tools, analysis scripts | 192.168.56.5 | — |
| Target | Ubuntu Server 22.04.5 LTS | Running OpenSSH with default config | 192.168.56.10 | OpenSSH 8.9p1 |
Target SSH configuration (/etc/ssh/sshd_config defaults):
PasswordAuthentication yes
UsePAM yes # Key setting — normalises timing via dummy hash
PermitRootLogin prohibit-password
MaxAuthTries 6
LogLevel INFO
UsePAM yes is the critical hardening setting. It forces OpenSSH to run a dummy bcrypt computation for non-existent users, matching the timing of a real password check.
This was introduced specifically as a countermeasure to CVE-2016-6210.
Each attack method was run as an independent trial with a clean log state:
# Reset log state on target before each trial
sudo truncate -s 0 /var/log/auth.log
# After attack: collect evidence
sudo cp /var/log/auth.log ~/evidence/trial-N-auth.log
Evidence collected per trial:
/var/log/auth.log from targettime.perf_counter() in manual_ssh.py| Method | Tool | Wordlist | Purpose |
|---|---|---|---|
| Manual SSH | ssh CLI + Paramiko | 50 common usernames | Baseline; inspect raw responses |
| Hydra brute force | hydra | same 50 | Automated; leverages Hydra's built-in enum mode |
| Metasploit module | auxiliary/scanner/ssh/ssh_enumuser | same 50 | Framework's dedicated enumeration module |
| Banner fingerprinting | custom BannerFingerprinter | N/A | No-auth version leak, CVE check |
| Timing analysis | custom ResponseAnalyzer | valid vs invalid subset | Statistical side-channel check |
This project goes beyond running tools — it wraps each attack and all detection logic in a structured Python codebase and provides an orchestrator that runs the entire pipeline end-to-end.
src/attack_tools/)ManualSSHEnumerator — Tests each username N times with paramiko, recording
precise timing, result type, and SSH banner. Computes mean/std per username. Critically,
it does not reuse connections between attempts, ensuring each sample captures the
full server-side processing time.
BannerFingerprinter — Grabs the SSH banner over a raw TCP socket (no credentials
needed). Parses implementation name, version string, and OS hint. Cross-references
against a local CVE registry. A version like OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 reveals
the exact server software — potentially enough to identify known vulnerabilities before
any authentication is attempted.
HydraAutomation — Subprocess wrapper around Hydra. Parses stdout to extract
successful logins, error messages, and Hydra's own enumeration verdict
(does not support user enumeration).
MetasploitScanner — Writes a temporary resource script and drives msfconsole
via subprocess. Parses output for hardening detection and any found usernames.
src/detection_tools/)LogParser — Regex-based auth.log parser supporting five SSH event types:
failed_invalid_user, failed_valid_user, pre_auth_reject, accepted,
disconnected. Returns structured event dicts with timestamp, event type, username,
source IP, and port.
ResponseAnalyzer — Performs Welch's t-test on timing distributions from valid vs
invalid usernames. Computes timing delta (ms), p-value, Cohen's d effect size, and
a plain-language conclusion. Threshold: delta ≥ 5ms AND p < 0.05 triggers a side-channel
warning.
EnumerationDetector — Four detection patterns:
AlertingSystem — Lightweight alert emitter. Generates timestamped JSON alerts to
stdout. Extend with email/SIEM/webhook integrations as needed.
run_investigation.py — CLI driver that runs all four stages in sequence and writes
results to data/results/. Run with --help for full usage.