Just a Web Fuzzer Example

Bellow script demonstrate how to create a very basic multithreaded web file and directory fuzzer.

It is far from being as fast as other famous web fuzzers (wfuzz, dirb, gobuster etc..) but it is at least a good start to understand how to create yours.

#!/bin/python3

'''
    -= Just a web fuzzer example =-
    (@DarkCoderSc)

    Dependencies:
        - pip install progressbar2
'''

import requests
import progressbar 
from multiprocessing import Pool
from multiprocessing.dummy import Pool as ThreadPool
from multiprocessing import Lock
import argparse

#
# Acquire parameters
#
parser = argparse.ArgumentParser(description="Just a web fuzzer example")

parser.add_argument('-u', '--url', action="store", dest="base_url", required=True, help="Target base URL to fuzz (ex: http://example.com/")
parser.add_argument('-w', '--wordlist', action="store", dest="wordlist_file", metavar="in-file", type=argparse.FileType('r'), required=True, help="Plain text wordlist file location.")
parser.add_argument('-x', '--extensions', action="store", dest="extensions", nargs='*', required=False, help="Append file extension at the end of each candidates (ex: .php .php5 .html .html5)")

try:
    argv = parser.parse_args()
except IOError:
    parser.error()


#
# Log Defs
#
def success(message):
    print("[\033[32mOK\033[39m] " + message)

def fail(message):
    print("[\033[31mKO\033[39m] " + message)

def debug(message):
    print("[\033[33m!!\033[39m] " + message)


#
# Fuzzer
#
def fuzz(args):
    lock = args[0]
    pbar = args[2]

    global base_url

    target_url = base_url + args[1]

    req = requests.head(target_url)

    status = req.status_code

    message = "{} - {}".format(status, target_url)

    if (status == 200):
        success(message)
    elif (status != 404):
        debug(message)

    lock.acquire()
    try:                   
        global progress

        progress += 1

        pbar.update(progress)
    finally:
        lock.release()   
    return

base_url = argv.base_url
if not base_url.endswith("/"):
    base_url += "/"

with open(argv.wordlist_file.name, "r", errors="ignore") as file:
    candidates = file.readlines()

    widgets = [
        ' [', progressbar.Timer(), '] ',
        progressbar.Bar(),
        ' (', progressbar.ETA(), ') ',
    ]

    ext_count = 1
    if argv.extensions:
        ext_count = len(argv.extensions) +1

    pbar = progressbar.ProgressBar(maxval=(len(candidates) * ext_count), widgets=widgets, redirect_stdout=True)         

    progress = 0

    pbar.start()
    try:
        pool = ThreadPool()
        try:    
            lock = Lock()
            
            for index, candidate in enumerate(candidates):
                candidate = candidate.strip()            
                
                if not candidate:
                    continue
                
                pool.map(fuzz, [[lock, candidate, pbar]])

                if (ext_count > 1):
                    for extension in argv.extensions:
                        pool.map(fuzz, [[lock, (candidate + extension), pbar]])            
                    
        finally:
            pool.close()
            pool.join()
    finally:
        pbar.finish()
comments powered by Disqus