Book Image

Python Web Penetration Testing Cookbook

By : Benjamin May, Cameron Buchanan, Andrew Mabbitt, Dave Mound, Terry Ip
Book Image

Python Web Penetration Testing Cookbook

By: Benjamin May, Cameron Buchanan, Andrew Mabbitt, Dave Mound, Terry Ip

Overview of this book

Table of Contents (16 chapters)
Python Web Penetration Testing Cookbook
Credits
About the Authors
About the Reviewers
www.PacktPub.com
Preface
Index

Screenshots based on a port list


In the previous script, we created our base function to return an image for a URL. We will now expand on that to loop over a list of ports that are commonly associated with web-based administration portals. This will allow us to point the script at an IP and automatically run through the possible ports that could be associated with a web server. This is to be used in cases when we don't know which ports are open on a server, rather than when where we are specifying the port and domain.

Getting ready

In order for this script to work, we'll need to have the script created in the Getting screenshots of a website with QtWeb Kit recipe. This should be saved in the Pythonxx/Lib folder and named something clear and memorable. Here, we've named that script screenshot.py. The naming of your script is particularly essential as we reference it with an important declaration.

How to do it…

This is the script that we will be using:

import screenshot
import requests

portList = [80,443,2082,2083,2086,2087,2095,2096,8080,8880,8443,9998,4643, 9001,4489]

IP = '127.0.0.1'

http = 'http://'
https = 'https://'

def testAndSave(protocol, portNumber):
    url = protocol + IP + ':' + str(portNumber)
    try:
        r = requests.get(url,timeout=1)

        if r.status_code == 200:
            print 'Found site on ' + url 
            s = screenshot.Screenshot()
            image = s.get_image(url)
            image.save(str(portNumber) + '.png')
    except:
        pass

for port in portList:
    testAndSave(http, port)
    testAndSave(https, port)

How it works…

We first create our import declarations. In this script, we use the screenshot script we created before and also the requests library. The requests library is used so that we can check the status of a request before trying to convert it to an image. We don't want to waste time trying to convert sites that don't exist.

Next, we import our libraries:

import screenshot
import requests

The next step sets up the array of common port numbers that we will be iterating over. We also set up a string with the IP address we will be using:

portList = [80,443,2082,2083,2086,2087,2095,2096,8080,8880,8443,9998,4643, 9001,4489]

IP = '127.0.0.1'

Next, we create strings to hold the protocol part of the URL that we will be building later; this just makes the code later on a little bit neater:

http = 'http://'
https = 'https://'

Next, we create our method, which will do the work of building the URL string. After we've created the URL, we check whether we get a 200 response code back for our get request. If the request is successful, we convert the web page returned to an image and save it with the filename being the successful port number. The code is wrapped in a try block because if the site doesn't exist when we make the request, it will throw an error:

def testAndSave(protocol, portNumber):
    url = protocol + IP + ':' + str(portNumber)
    try:
        r = requests.get(url,timeout=1)

        if r.status_code == 200:
            print 'Found site on ' + url 
            s = screenshot.Screenshot()
            image = s.get_image(url)
            image.save(str(portNumber) + '.png')
    except:
        pass

Now that our method is ready, we simply iterate over each port in the port list and call our method. We do this once for the HTTP protocol and then with HTTPS:

for port in portList:
    testAndSave(http, port)
    testAndSave(https, port)

And that's it. Simply run the script and it will save the images to the same location as the script.

There's more…

You might notice that the script takes a while to run. This is because it has to check each port in turn. In practice, you would probably want to make this a multithreaded script so that it can check multiple URLs at the same time. Let's take a quick look at how we can modify the code to achieve this.

First, we'll need a couple more import declarations:

import Queue
import threading

Next, we need to create a new function that we will call threader. This new function will handle putting our testAndSave functions into the queue:

def threader(q, port):
    q.put(testAndSave(http, port))
    q.put(testAndSave(https, port))

Now that we have our new function, we just need to set up a new Queue object and make a few threading calls. We will take out the testAndSave calls from our FOR loop over the portList variable and replace it with this code:

q = Queue.Queue()

for port in portList:
    t = threading.Thread(target=threader, args=(q, port))
    t.deamon = True
    t.start()

s = q.get()

So, our new script in total now looks like this:

import Queue
import threading
import screenshot
import requests

portList = [80,443,2082,2083,2086,2087,2095,2096,8080,8880,8443,9998,4643, 9001,4489]

IP = '127.0.0.1'

http = 'http://'
https = 'https://'

def testAndSave(protocol, portNumber):
    url = protocol + IP + ':' + str(portNumber)
    try:
        r = requests.get(url,timeout=1)

        if r.status_code == 200:
            print 'Found site on ' + url 
            s = screenshot.Screenshot()
            image = s.get_image(url)
            image.save(str(portNumber) + '.png')
    except:
        pass

def threader(q, port):
    q.put(testAndSave(http, port))
    q.put(testAndSave(https, port))

q = Queue.Queue()

for port in portList:
    t = threading.Thread(target=threader, args=(q, port))
    t.deamon = True
    t.start()

s = q.get()

If we run this now, we will get a much quicker execution of our code as the web requests are now being executed in parallel with each other.

You could try to further expand the script to work on a range of IP addresses too; this can be handy when you're testing an internal network range.