Introduction
Finding an unrecognized SSH public key in a user's ~/.ssh/authorized_keys file is a clear indicator of compromise. An attacker with access to the server (via another vector) may have added their own key to maintain persistent access, even after the original vulnerability is patched. This is a common post-exploitation technique because SSH key access survives password changes and is harder to detect than a modified password.
Symptoms
- Unknown SSH public key found in
~/.ssh/authorized_keys - SSH login from an unfamiliar IP address in
/var/log/auth.log - User reports they did not add the key
- Key fingerprint does not match any known team member
- Multiple servers have the same unauthorized key added
Common Causes
- Server compromised via vulnerable web application
- Stolen SSH private key from a developer's machine
- Shared credentials allowing unauthorized access
- Supply chain attack through compromised deployment pipeline
- Insider threat adding a key for unauthorized access
Step-by-Step Fix
- 1.Document the unauthorized key before removing it:
- 2.```bash
- 3.# Record the key for forensic analysis
- 4.cat ~/.ssh/authorized_keys > /tmp/authorized_keys.evidence
- 5.# Get the fingerprint
- 6.ssh-keygen -lf /tmp/authorized_keys.evidence
- 7.# Note the timestamp of when the file was last modified
- 8.stat ~/.ssh/authorized_keys
- 9.
` - 10.Check authentication logs for access using the unauthorized key:
- 11.```bash
- 12.# Get the key fingerprint
- 13.FINGERPRINT=$(ssh-keygen -lf /tmp/unauthorized_key.pub | awk '{print $2}')
- 14.# Search auth logs for this fingerprint
- 15.sudo grep "$FINGERPRINT" /var/log/auth.log
- 16.sudo grep "$FINGERPRINT" /var/log/secure
- 17.# Check for SSH sessions from unfamiliar IPs
- 18.sudo grep "Accepted publickey" /var/log/auth.log | tail -20
- 19.
` - 20.Remove the unauthorized key immediately:
- 21.```bash
- 22.# Remove the specific key line from authorized_keys
- 23.# First identify which line it is
- 24.grep -n "unauthorized-key-comment" ~/.ssh/authorized_keys
- 25.# Remove it
- 26.sed -i '/unauthorized-key-comment/d' ~/.ssh/authorized_keys
- 27.
` - 28.Check all user accounts on the server for the same key:
- 29.```bash
- 30.for user in $(cut -d: -f1 /etc/passwd); do
- 31.homedir=$(eval echo ~$user)
- 32.if [ -f "$homedir/.ssh/authorized_keys" ]; then
- 33.match=$(grep -l "unauthorized-key-pattern" "$homedir/.ssh/authorized_keys" 2>/dev/null)
- 34.[ -n "$match" ] && echo "FOUND on $user: $match"
- 35.fi
- 36.done
- 37.
` - 38.Audit all recent SSH sessions and check for signs of lateral movement:
- 39.```bash
- 40.# List all SSH sessions in the last 7 days
- 41.sudo grep "session opened" /var/log/auth.log | grep sshd | tail -30
- 42.# Check for new user accounts created
- 43.sudo grep "useradd|adduser" /var/log/auth.log
- 44.# Check for sudo activity
- 45.sudo grep "sudo:" /var/log/auth.log | tail -20
- 46.# Check for cron jobs added
- 47.for user in $(cut -d: -f1 /etc/passwd); do
- 48.crontab -u $user -l 2>/dev/null
- 49.done
- 50.
` - 51.Harden SSH configuration to prevent recurrence:
- 52.```bash
- 53.sudo nano /etc/ssh/sshd_config
- 54.# Disable password authentication
- 55.PasswordAuthentication no
- 56.# Limit which users can SSH
- 57.AllowUsers admin deploy
- 58.# Disable root login
- 59.PermitRootLogin no
- 60.# Log all SSH access
- 61.LogLevel VERBOSE
- 62.sudo systemctl restart sshd
- 63.
`
Prevention
- Implement centralized SSH key management with automated auditing
- Use SSH certificates instead of authorized_keys for better key lifecycle management
- Monitor authorized_keys files with file integrity monitoring (AIDE, OSSEC)
- Implement bastion hosts with session recording for all SSH access
- Rotate SSH keys on a regular schedule and audit all active keys quarterly