How to Write Your Own Bash Script to Automate Recon

Jun 11, 2020 11:28 PM
Aug 3, 2020 08:41 PM
637243550187543088.jpg

Automation has been a buzz word for quite some time now, but the principles behind it are as strong as ever. For a hacker or pentester, Bash scripting is one form of automation that cannot be ignored. Virtually any command that can be run from the terminal can be scripted — and should be, in many cases — to save valuable time and effort. And a Bash script just happens to be great for recon.

Step 1: Start the Script

To get started, create a Bash script and name it whatever you like. I'll call mine recon.sh. Using your favorite text editor, make the first line look like this:

#!/bin/bash

This is called a shebang, or hashbang, and simply points to the system's interpreter for Bash.

Next, we'll make sure the user supplies input to the script, and if not, prints a usage example and exits. Use a conditional if-then block:

if [ -z "$1" ]
then
        echo "Usage: ./recon.sh <IP>"
        exit 1
fi

The $1 is the argument we will pass to the script, and the -z option returns true if the string is null. So basically, this says if no argument is passed, print the usage example and exit. The argument we'll use is an IP address.

Step 2: Scan the Host

The next section will run an Nmap scan on the host IP address we supply. First, we'll print a heading for Nmap just to keep things pretty and organized:

printf "\n----- NMAP -----\n\n" > results

We use printf here because it handles newlines (\n) more reliably than echo. This is being written to a text file called results — it will first create the file since it doesn't exist yet, and it will overwrite the file in the future with subsequent scans.

Next, we will print a message and actually run the command:

echo "Running Nmap..."
nmap $1 | tail -n +5 | head -n -3 >> results

The nmap command takes the argument we supplied the script, the IP address, and appends the results to our output file. The tail and head commands remove some lines from the beginning and end of the Nmap output — this is just my personal preference and makes it look a little cleaner in my opinion.

Step 3: Enumerate HTTP

The next section will take the results of the Nmap scan and attempt to enumerate HTTP if certain criteria are met. We will run Gobuster to scan for directories and WhatWeb to get some information about the web server.

We'll use a while loop to read each line from our results file, and if it finds an open port running HTTP, it will kick off Gobuster and WhatWeb:

while read line
do
        if [[ $line == *open* ]] && [[ $line == *http* ]]
        then
                echo "Running Gobuster..."
                gobuster dir -u $1 -w /usr/share/wordlists/dirb/common.txt -qz > temp1

        echo "Running WhatWeb..."
        whatweb $1 -v > temp2
        fi
done < results

If an open HTTP port is found, the code in the if-then block will run. Gobuster takes the IP address we supplied as the -u option and uses a wordlist specified by the -w option. We will also use the -q and -z options here to disable the banner and hide the progress — again, just to keep the output tidy. This will write to a temporary file that will be utilized later in the script.

WhatWeb simply takes the IP address we supplied and writes the output to a second temporary file. The -v option here gives us verbose results. When the while loop exhausts all lines of the results file, it completes, and the script moves on to the next section.

Step 4: Display the Results

The next block of code will determine if the temporary files from earlier exist, and if so, will append the output to the main results file:

if [ -e temp1 ]
then
        printf "\n----- DIRS -----\n\n" >> results
        cat temp1 >> results
        rm temp1
fi

if [ -e temp2 ]
then
    printf "\n----- WEB -----\n\n" >> results
        cat temp2 >> results
        rm temp2
fi

The -e option checks if the file exists — if it does, the code after then runs. It prints another heading, writes the contents of the temporary file to our results, and removes the temporary file.

Finally, the last line of our script will simply display the results on our screen:

cat results

Step 5: Review the Script

The entire script should now look like this:

#!/bin/bash

if [ -z "$1" ]
then
        echo "Usage: ./recon.sh <IP>"
        exit 1
fi

printf "\n----- NMAP -----\n\n" > results

echo "Running Nmap..."
nmap $1 | tail -n +5 | head -n -3 >> results

while read line
do
        if [[ $line == *open* ]] && [[ $line == *http* ]]
        then
                echo "Running Gobuster..."
                gobuster dir -u $1 -w /usr/share/wordlists/dirb/common.txt -qz > temp1

        echo "Running WhatWeb..."
        whatweb $1 -v > temp2
        fi
done < results

if [ -e temp1 ]
then
        printf "\n----- DIRS -----\n\n" >> results
        cat temp1 >> results
        rm temp1
fi

if [ -e temp2 ]
then
    printf "\n----- WEB -----\n\n" >> results
        cat temp2 >> results
        rm temp2
fi

cat results

Step 6: Run the Script

Now we should be ready to run our recon script. In my example, I'm using Metasploitable 2 as the target.

First, make the script executable:

~# chmod +x recon.sh

If we try to run it without an argument, it gives us the usage example:

~# ./recon.sh

Usage: ./recon.sh <IP>

Simply supply the IP address and run it again:

~# ./recon.sh 10.10.0.50

Running Nmap...
Running Gobuster...
Running WhatWeb...
/usr/lib/ruby/vendor_ruby/target.rb:188: warning: URI.escape is obsolete

----- NMAP -----

PORT     STATE SERVICE
21/tcp   open  ftp
22/tcp   open  ssh
23/tcp   open  telnet
25/tcp   open  smtp
53/tcp   open  domain
80/tcp   open  http
111/tcp  open  rpcbind
139/tcp  open  netbios-ssn
445/tcp  open  microsoft-ds
512/tcp  open  exec
513/tcp  open  login
514/tcp  open  shell
1099/tcp open  rmiregistry
1524/tcp open  ingreslock
2049/tcp open  nfs
2121/tcp open  ccproxy-ftp
3306/tcp open  mysql
5432/tcp open  postgresql
5900/tcp open  vnc
6000/tcp open  X11
6667/tcp open  irc
8009/tcp open  ajp13
8180/tcp open  unknown

----- DIRS -----

/.hta (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/.bash_history (Status: 200)
/cgi-bin/ (Status: 403)
/dav (Status: 301)
/phpMyAdmin (Status: 301)
/index (Status: 200)
/index.php (Status: 200)
/test (Status: 301)
/twiki (Status: 301)
/phpinfo (Status: 200)
/phpinfo.php (Status: 200)

----- WEB -----

WhatWeb report for http://10.10.0.50
Status    : 200 OK
Title     : Metasploitable2 - Linux
IP        : 10.10.0.50
Country   : RESERVED, ZZ

Summary   : WebDAV[2], X-Powered-By[PHP/5.2.4-2ubuntu5.24], Apache[2.2.8], PHP[5.2.4-2ubuntu5.24], HTTPServer[Ubuntu Linux][Apache/2.2.8 (Ubuntu) DAV/2]

Detected Plugins:
[ Apache ]
        The Apache HTTP Server Project is an effort to develop and
        maintain an open-source HTTP server for modern operating
        systems including UNIX and Windows NT. The goal of this
        project is to provide a secure, efficient and extensible
        server that provides HTTP services in sync with the current
        HTTP standards.

        Version      : 2.2.8 (from HTTP Server Header)
        Google Dorks: (3)
        Website     : http://httpd.apache.org/

[ HTTPServer ]
        HTTP server header string. This plugin also attempts to
        identify the operating system from the server header.

        OS           : Ubuntu Linux
        String       : Apache/2.2.8 (Ubuntu) DAV/2 (from server string)

[ PHP ]
        PHP is a widely-used general-purpose scripting language
        that is especially suited for Web development and can be
        embedded into HTML. This plugin identifies PHP errors,
        modules and versions and extracts the local file path and
        username if present.

        Version      : 5.2.4-2ubuntu5.24
        Google Dorks: (2)
        Website     : http://www.php.net/

[ WebDAV ]
        Web-based Distributed Authoring and Versioning (WebDAV) is
        a set of methods based on the Hypertext Transfer Protocol
        (HTTP) that facilitates collaboration between users in
        editing and managing documents and files stored on World
        Wide Web servers. - More Info:
        http://en.wikipedia.org/wiki/WebDAV

        Version      : 2

[ X-Powered-By ]
        X-Powered-By HTTP header

        String       : PHP/5.2.4-2ubuntu5.24 (from x-powered-by string)

HTTP Headers:
        HTTP/1.1 200 OK
        Date: Wed, 19 Jun 2019 18:03:39 GMT
        Server: Apache/2.2.8 (Ubuntu) DAV/2
        X-Powered-By: PHP/5.2.4-2ubuntu5.24
        Connection: close
        Transfer-Encoding: chunked
        Content-Type: text/html

It tells us what's running (ignore the ruby error for WhatWeb) and prints out a nice display of the results when it is done.

Expanding the Script

In its current state, this Bash script isn't complicated. It runs an Nmap scan, and if an open HTTP port is found, it kicks off Gobuster and WhatWeb. While useful, this could be expanded in many ways.

First of all, we're only running a basic Nmap scan. We could scan additional ports, run the default scripts, enable OS detection, and more. Basically, anything you can do from the command line you can put in the script. The same thing goes for Gobuster and WhatWeb.

We could also expand the script to enumerate other services besides HTTP. Things like SMB, SSH, and FTP could all be good candidates to add in there. Again, Bash scripting is powerful because it is possible to automate many of the functions typically used in a command-line form.

Wrapping Up

In this tutorial, we created a Bash script to automate some of the activities used in the reconnaissance phase of a penetration test. The script took an IP address as an argument, ran an Nmap scan on the target, and if an open HTTP port was found, kicked off Gobuster and WhatWeb. Bash Scripting is extremely powerful, and even this simple script saved us a ton of time and typing.

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

Comments

No Comments Exist

Be the first, drop a comment!