How To: Crack SSH Private Key Passwords with John the Ripper

Crack SSH Private Key Passwords with John the Ripper

Secure Shell is one of the most common network protocols, typically used to manage remote machines through an encrypted connection. However, SSH is prone to password brute-forcing. Key-based authentication is much more secure, and private keys can even be encrypted for additional security. But even that isn't bulletproof since SSH private key passwords can be cracked using John the Ripper.

SSH Key-Based Authentication

The standard way of connecting to a machine via SSH uses password-based authentication. This has the advantage of being easier to set up but suffers security-wise due to being prone to brute-forcing and password guessing.

Key-based authentication, on the other hand, uses cryptography to ensure secure connections. A key pair is generated consisting of a public and private key. The private key should be kept secret and is used to connect to machines that have the matching public key.

The public key is used to encrypt communication that only the associated private key can decrypt. This makes it nearly impossible for hackers to compromise SSH sessions unless they have access to the private key.

The below steps assume you have already gained access to a target computer from your local machine. I'm using Kali Linux as the local box.

Step 1: Create a New User on the Target

To begin, let's create a new user on the target for demonstration purposes. Use the adduser command, and enter a new password at the prompt:

target:~$ sudo adduser nullbyte

Adding user `nullbyte' ...
Adding new group `nullbyte' (1003) ...
Adding new user `nullbyte' (1003) with group `nullbyte' ...
Creating home directory `/home/nullbyte' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

Next, verify the information is correct. It's OK to just leave everything blank:

Changing the user information for nullbyte
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [y/N] y

We can verify the new user was added successfully by viewing /etc/passwd:

target:~$ cat /etc/passwd

list:x:38:38:Mailing List Manager:/var/list:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
postgres:x:108:117:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
mysql:x:109:118:MySQL Server,,,:/var/lib/mysql:/bin/false
user:x:1001:1001:just a user,111,,:/home/user:/bin/bash

Now we can switch to our new user with the su command:

target:~$ su - nullbyte


Step 2: Generate a Key Pair on the Target

The next thing we need to do is generate a public/private key pair. The ssh-keygen utility can easily take care of this for us. Use the default location, which will create the file in our home directory:

nullbyte@target:~$ ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/home/nullbyte/.ssh/id_rsa):
Created directory '/home/nullbyte/.ssh'.

We want our private key to be encrypted, so make sure to enter a password at the prompt (we'll use the password abc123 just to keep it simple):

Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/nullbyte/.ssh/id_rsa.
Your public key has been saved in /home/nullbyte/.ssh/
The key fingerprint is:
1b:01:68:cc:ea:4f:8e:b5:08:72:17:50:32:1b:98:e6 nullbyte@target

Now we can change into the hidden SSH directory:

nullbyte@target:~$ cd .ssh/

And verify our keys are there:

nullbyte@target:~/.ssh$ ls -la

total 16
drwx------ 2 nullbyte nullbyte 4096 2019-06-19 13:49 .
drwxr-xr-x 3 nullbyte nullbyte 4096 2019-06-19 13:46 ..
-rw------- 1 nullbyte nullbyte 1743 2019-06-19 13:49 id_rsa
-rw-r--r-- 1 nullbyte nullbyte  405 2019-06-19 13:49

We'll also need to create an authorized_keys file to make sure we're allowed to connect from our other machine:

nullbyte@target:~/.ssh$ touch authorized_keys

Set the appropriate permissions on it to ensure only our user can read and write the file:

nullbyte@target:~/.ssh$ chmod 600 authorized_keys

The public key needs to go in this file, so cat it out:

nullbyte@target:~/.ssh$ cat

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA7IATfm6Y2VDtlEkWNGLJ5r9z9euOD1mHcWeB4vCcY+9M+XTEkILb8gk0/0uaNrLfBgcrZi8Y15wIib8122KYfwVIxVn0kbp5sggo4ZZQ9AXAPsdXyP8iIhCdbu34QkEu+pdq1jjK2QKbJRhRt4woAKGXxpApGfWdbyDdElo001VjjmDIpUwKU695YlF98baOlxgUdtW+zhL8J2W6cABeQEO3pXaiu560mJxSfRX8J++5djHiwJ9LMQAVD8khrvYfmnExeT1CuhNcbxdD/kU64ccV0zhecUQgXR1zEY/tWVdJL8wWfUnHWza2BiYqCeEhIdKGlVLvPUx5LbihLUFdCw== nullbyte@target

And copy it into the authorized_keys file, making sure there are no line breaks or extra spaces:

nullbyte@target:~/.ssh$ nano authorized_keys

Step 3: Get the Private Key on the Local Machine

At this point, we need to get the private key (id_rsa) on our local machine. This can happen through a variety of scenarios, like if we had read access due to LFI or even command injection allowing us to execute certain commands.

For demonstration purposes, we'll just transfer it over via HTTP. It's always a good idea to check which, if any, version of Python is installed:

nullbyte@target:~/.ssh$ which python


We can spin up a quick HTTP server with the following command:

nullbyte@target:~/.ssh$ python -m SimpleHTTPServer

Serving HTTP on port 8000 ...

On our local machine, we can use wget to grab the file:

~# wget

--2020-04-15 12:19:39--
Connecting to connected.
HTTP request sent, awaiting response... 200 OK
Length: 1743 (1.7K) [application/octet-stream]
Saving to: ‘id_rsa’

id_rsa                                    100%[=====================================================================================>]   1.70K  --.-KB/s    in 0.001s

2020-04-15 12:19:49 (2.18 MB/s) - ‘id_rsa’ saved [1743/1743]

And verify its contents:

~# cat id_rsa

Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,9A447029ABFAC605


Step 4: Install SSH2John on the Local Machine

Unless the jumbo version of John the Ripper is installed, we'll need to download ssh2john from GitHub since it's not included in the John the Ripper version that's installed in Kali Linux. (If you don't have John the Ripper installed, you can find out how to install it from its GitHub.)

~# wget

--2020-06-07 12:26:03--
Resolving (
Connecting to (||:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7825 (7.6K) [text/plain]
Saving to: ‘’                               100%[=====================================================================================>]   7.64K  --.-KB/s    in 0s

2020-06-07 12:26:04 (21.2 MB/s) - ‘’ saved [7825/7825]

Step 5: Crack the Private Key on the Local Machine

All we have to do is run it against the private key and direct the results to a new hash file using the ssh2john Python tool:

~# python id_rsa > id_rsa.hash

Next, we'll use John to crack the password. But first, we need a suitable wordlist; we'll use a short one that already contains our password to keep it simple. Get it from here:

~# wget

--2020-06-07 12:30:54--
Resolving (
Connecting to (||:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 81 [text/plain]
Saving to: ‘darkweb2017-top10.txt’

darkweb2017-top10.txt                     100%[=====================================================================================>]      81  --.-KB/s    in 0s

2020-06-07 12:30:55 (2.28 MB/s) - ‘darkweb2017-top10.txt’ saved [81/81]

Now run John like usual, feeding it the wordlist and the hash file:

~# john --wordlist=darkweb2017-top10.txt id_rsa.hash

Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 1 for all loaded hashes
Cost 2 (iteration count) is 2 for all loaded hashes
Will run 4 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
abc123           (id_rsa)
1g 0:00:00:00 DONE (2020-06-07 12:32) 1.562g/s 15.62p/s 15.62c/s 15.62C/s 123456..123123
Session completed

We can see it identified our password, but just to be sure, let's use the --show command to verify:

~# john --show id_rsa.hash


1 password hash cracked, 0 left

Step 6: SSH into the Target

We can SSH into the target using the -i option to specify a private key for authentication:

~# ssh -i id_rsa nullbyte@

Permissions 0644 for 'id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "id_rsa": bad permissions
nullbyte@'s password:

And we get an error. It won't allow us to use the key if permissions are too open, so all we have to do is set the permissions to be more restricted:

~# chmod 400 id_rsa

Now we are able to connect. Next, enter the cracked password at the prompt and we're in:

~# ssh -i id_rsa nullbyte@

Enter passphrase for key 'id_rsa':
Linux 2.6.24-16-server #1 SMP Tue July 07 13:58:00 UTC 2008 i686

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To access official Ubuntu documentation, please visit:
Last login: Fri Jun 19 15:20:16 2020 from

Wrapping Up

In this tutorial, we learned about SSH key-based authentication and how to crack private key passwords. First, we created a new user on the target system and generated an SSH key pair. Next, we obtained the private key from the target and used ssh2john to extract the hash. Finally, we cracked the private key password and used it to connect to the target.

Just updated your iPhone? You'll find new features for Podcasts, News, Books, and TV, as well as important security improvements and fresh wallpapers. Find out what's new and changed on your iPhone with the iOS 17.5 update.

Cover image by stevepb/Pixabay; Screenshots by drd_/Null Byte

1 Comment

Don't copy/paste to add public key to authorized key file. Don't even use an editor.

cat >> authorized_key

Why are you setting up a web browser when you already have ssh going? Use scp or sftp!

Share Your Thoughts

  • Hot
  • Latest