Countering SSH Brute Attackers

The amount of attacks a server gets when the SSH port is open is ridiculous. And most of the IP addresses are from China, so its kind of hard to track down the person making these requests without doing some massive digging.

So to make these attacks easier to read, I put together a Linux command that parses your access.log file.

The command extracts the attempted username and IP that the hacker used.

The command follows:
sudo cat /var/log/auth.log | grep 'invalid user' | grep -v ']$' | awk '{print $11 " -->" $13}'

This command will return a nicely visualized output of the attackers IP and their attempted username.

tanis -->220.95.232.46
chateau -->106.12.28.210
ftpuser -->149.56.15.98
ryan -->220.95.232.46
support -->190.14.247.90
ORD_SERVER -->149.56.15.98

 

Once you are comfortable with the command, I suggest you put it in your path so you can run it without having to be in the same directory as the access.log

sudo touch /usr/bin/brute
echo "#!/bin/bash" > /usr/bin/brute
echo "sudo cat /var/log/auth.log | grep 'invalid user' | grep -v ']$' | awk '{print \$11 \" -->\" \$13}'" >> /usr/bin/brute

Now that it can be executed from anywhere in the system, it’s time to introduce the Python and Bash scripts. The Python script was taken from Violent Python and modified to fit the situation.

And the bash script parses each IP address, and hands it off to the python port scanner.

First, the Python script.

import optparse
from socket import *
def main():
    parser = optparse.OptionParser('usage %prog -H <target host> -p <target port>')
    parser.add_option('-H', dest='tgtHost', type='string', help='specify target host')
    (options, args) = parser.parse_args()
    
    tgtHost = options.tgtHost
    
    tgtPorts = [20,21,22,23,25,53,67,68,69,80,110,123,137,138,139,143,161,162,179,389,443,636,989,990]
    
    with open('already_scanned.txt', 'ra') as already_scanned:
        
        already_scanned_list = already_scanned.readlines()
    
    already_scanned_list = [x.strip() for x in already_scanned_list]
    
    if (tgtHost == None):
        print parser.usage
        exit(0)
    if tgtHost in already_scanned_list:
        print "IP already scanned"
    else:
        already_scanned = open('already_scanned.txt', 'a')
        already_scanned.write(str(tgtHost) + "\n" )
        already_scanned.close()
        portScan(tgtHost, tgtPorts)


def connScan(tgtHost, tgtPort):
    try:
        connSkt = socket(AF_INET, SOCK_STREAM)
        connSkt.connect((tgtHost, tgtPort))
        print '[+] %d/tcp open' % tgtPort
        f = open('open_ports.txt', 'a')
        f.write("HOST: " + str(tgtHost) + " PORT ---> " + str(tgtPort) + "\n")
        f.close()
        connSkt.close()
    except:
        print '[-] %d/tcp closed'%tgtPort


def portScan(tgtHost, tgtPorts):
    try:
        tgtIP = gethostbyname(tgtHost)
    except:
        print "[-] Cannot resolve '%s': Unkown host"%tgtHost
    try:
        tgtIP = tgtHost
        tgtName = gethostbyaddr(tgtIP)
        print '\n[+] Scan results for: ' + tgtName[0]
    except:
        print '\n[+] Scan results for: ' +  tgtIP
    setdefaulttimeout(1)
    for tgtPort in tgtPorts:
        print 'Scanning port ' + str(tgtPort)
        connScan(tgtHost, int(tgtPort))
if __name__ == '__main__':
    main()

 

The program opens up a file called “already_scanned.txt” and checks if the IP address has already been scanned.

The reason for this is because you will often have multiple attempts from the same IP.

So instead of port scanning each IP indiscriminately, time is saved by checking if its already been scanned.

The Python script scans for the most common open ports, and if it finds an open port, appends the IP address and port to a file called ‘open_ports.txt’

Finally, the bash script takes the output of the ‘brute’ command and passes it to the Python script.

#!/bin/bash

brute > newest_log.txt
input="newest_log.txt"


while IFS= read -r var
do
  ipaddress=$( echo "$var" | awk -F " -->" '{print $2}' )
  #echo "$ipaddress"
  python portscan.py -H "$ipaddress" 
done < "$input"

 

This script calls the brute command, and redirects the output to a file called “newest_log.txt”.

The bash file loops through each line of the file (every line is a different IP) and calls the portscan.py file with the IP address as the argument.

Now, you can run this manually, or use crontab to run it once a day.

And everytime you log in, check the “open_ports.txt” file and see what you have.

I know disabling passwords for SSH ports and using keys is standard protocol, but this is sort of like a honey-pot allowing you to analyze attacks and counter them, in turn sharpening your netsec skills.

 

You Might Also Like

Leave a Reply

Your email address will not be published. Required fields are marked *