class Controller(object): def __init__(self, script_path, arguments, output): self.script_path = script_path self.exit = False self.arguments = arguments self.output = output self.blacklists = self.getBlacklists() self.fuzzer = None self.recursive = self.arguments.recursive self.excludeStatusCodes = self.arguments.excludeStatusCodes self.recursive = self.arguments.recursive self.directories = Queue() self.excludeSubdirs = (arguments.excludeSubdirs if arguments.excludeSubdirs is not None else []) self.output.printHeader(PROGRAM_BANNER) self.dictionary = FuzzerDictionary(self.arguments.wordlist, self.arguments.extensions, self.arguments.lowercase) self.printConfig() try: for url in self.arguments.urlList: try: self.currentUrl = url self.reportManager = ReportManager() self.requester = Requester(url, cookie=self.arguments.cookie, useragent=self.arguments.useragent, maxPool=self.arguments.threadsCount, maxRetries=self.arguments.maxRetries, timeout=self.arguments.timeout, ip=self.arguments.ip, proxy=self.arguments.proxy, redirect=self.arguments.redirect) for key, value in arguments.headers.iteritems(): self.requester.setHeader(key, value) # Initialize directories Queue with start Path self.basePath = self.requester.basePath if self.arguments.scanSubdirs is not None: for subdir in self.arguments.scanSubdirs: self.directories.put(subdir) else: self.directories.put('') self.setupReports(self.requester) self.output.printTarget(self.currentUrl) self.fuzzer = Fuzzer(self.requester, self.dictionary, testFailPath=self.arguments.testFailPath, threads=self.arguments.threadsCount) self.wait() except SkipTargetInterrupt: continue except RequestException, e: self.output.printError('Unexpected error:\n{0}'.format(e.args[0]['message'])) exit(0) except KeyboardInterrupt, SystemExit: self.output.printError('\nCanceled by the user') exit(0)
def __init__(self, requester, dictionary, testFailPath="youCannotBeHere7331", threads=1): self.requester = requester self.dictionary = dictionary self.testFailPath = testFailPath self.testedPaths = Queue() self.basePath = self.requester.basePath self.threads = [] self.threadsCount = threads if len( self.dictionary) >= threads else len(self.dictionary) self.running = False self.testers = {}
def __init__(self, requester, dictionary, testFailPath="youCannotBeHere7331", threads=1): self.requester = requester self.dictionary = dictionary self.testFailPath = testFailPath self.testedPaths = Queue() self.basePath = self.requester.basePath self.threads = [] self.threadsCount = threads if len(self.dictionary) >= threads else len(self.dictionary) self.running = False self.testers = {}
class Fuzzer(object): def __init__(self, requester, dictionary, testFailPath="youCannotBeHere7331", threads=1): self.requester = requester self.dictionary = dictionary self.testFailPath = testFailPath self.testedPaths = Queue() self.basePath = self.requester.basePath self.threads = [] self.threadsCount = threads if len(self.dictionary) >= threads else len(self.dictionary) self.running = False self.testers = {} def wait(self): for thread in self.threads: thread.join() def testersSetup(self): if len(self.testers) != 0: self.testers = {} self.testers["/"] = NotFoundTester(self.requester, "{0}/".format(self.testFailPath)) for extension in self.dictionary.extensions: self.testers[extension] = NotFoundTester(self.requester, "{0}.{1}".format(self.testFailPath, extension)) def threadsSetup(self): if len(self.threads) != 0: self.threads = [] for thread in range(self.threadsCount): newThread = threading.Thread(target=self.thread_proc) newThread.daemon = True self.threads.append(newThread) def getTester(self, path): for extension in list(self.testers.keys()): if path.endswith(extension): return self.testers[extension] # By default, returns folder tester return self.testers["/"] def start(self): # Setting up testers self.testersSetup() # Setting up threads self.threadsSetup() self.index = 0 self.dictionary.reset() self.runningThreadsCount = len(self.threads) self.running = True self.playEvent = threading.Event() self.pausedSemaphore = threading.Semaphore(0) self.playEvent.clear() self.exit = False for thread in self.threads: thread.start() self.play() def play(self): self.playEvent.set() def pause(self): self.playEvent.clear() for thread in self.threads: if thread.is_alive(): self.pausedSemaphore.acquire() def stop(self): self.running = False self.play() def testPath(self, path): response = self.requester.request(path) result = 0 if self.getTester(path).test(response): result = 0 if response.status == 404 else response.status return result, response def isRunning(self): return self.running def finishThreads(self): self.running = False self.finishedEvent.set() def getPath(self): path = None if not self.empty(): path = self.testedPaths.get() if not self.isFinished(): path = self.testedPaths.get() return path def qsize(self): return self.testedPaths.qsize() def empty(self): return self.testedPaths.empty() def isFinished(self): return self.runningThreadsCount == 0 def stopThread(self): self.runningThreadsCount -= 1 if self.runningThreadsCount is 0: self.testedPaths.put(None) def thread_proc(self): self.playEvent.wait() try: path = next(self.dictionary) while path is not None: try: status, response = self.testPath(path) self.testedPaths.put(Path(path=path, status=status, response=response)) except RequestException as e: print("\nUnexpected error:\n{0}\n".format(e.args[0]["message"])) sys.stdout.flush() continue finally: if not self.playEvent.isSet(): self.pausedSemaphore.release() self.playEvent.wait() path = next(self.dictionary) # Raises StopIteration when finishes if not self.running: break except StopIteration: return finally: self.stopThread()
class Controller(object): def __init__(self, script_path, arguments, output): self.script_path = script_path self.exit = False self.arguments = arguments self.output = output self.blacklists = self.getBlacklists() self.fuzzer = None self.recursive = self.arguments.recursive self.excludeStatusCodes = self.arguments.excludeStatusCodes self.recursive = self.arguments.recursive self.directories = Queue() self.excludeSubdirs = (arguments.excludeSubdirs if arguments.excludeSubdirs is not None else []) self.output.printHeader(PROGRAM_BANNER) self.dictionary = FuzzerDictionary(self.arguments.wordlist, self.arguments.extensions, self.arguments.lowercase) self.printConfig() try: for url in self.arguments.urlList: try: self.currentUrl = url self.reportManager = ReportManager() self.requester = Requester(url, cookie=self.arguments.cookie, useragent=self.arguments.useragent, maxPool=self.arguments.threadsCount, maxRetries=self.arguments.maxRetries, timeout=self.arguments.timeout, ip=self.arguments.ip, proxy=self.arguments.proxy, redirect=self.arguments.redirect) for key, value in arguments.headers.items(): self.requester.setHeader(key, value) # Initialize directories Queue with start Path self.basePath = self.requester.basePath if self.arguments.scanSubdirs is not None: for subdir in self.arguments.scanSubdirs: self.directories.put(subdir) else: self.directories.put('') self.setupReports(self.requester) self.output.printTarget(self.currentUrl) self.fuzzer = Fuzzer(self.requester, self.dictionary, testFailPath=self.arguments.testFailPath, threads=self.arguments.threadsCount) self.wait() except SkipTargetInterrupt: continue except RequestException as e: self.output.printError('Unexpected error:\n{0}'.format(e.args[0]['message'])) exit(0) except KeyboardInterrupt as SystemExit: self.output.printError('\nCanceled by the user') exit(0) finally: self.reportManager.save() self.reportManager.close() self.output.printWarning('\nTask Completed') def printConfig(self): self.output.printConfig( ', '.join(self.arguments.extensions), str(self.arguments.threadsCount), str(len(self.dictionary))) def getBlacklists(self): blacklists = {} for status in [400, 403, 500]: blacklistFileName = FileUtils.buildPath(self.script_path, 'db') blacklistFileName = FileUtils.buildPath(blacklistFileName, '{0}_blacklist.txt'.format(status)) if not FileUtils.canRead(blacklistFileName): continue blacklists[status] = [] for line in FileUtils.getLines(blacklistFileName): # Skip comments if line.startswith('#'): continue blacklists[status].append(line) return blacklists def setupReports(self, requester): if self.arguments.autoSave: basePath = ('/' if requester.basePath is '' else requester.basePath) basePath = basePath.replace(os.path.sep, '.')[1:-1] fileName = ('{0}_'.format(basePath) if basePath is not '' else '') fileName += time.strftime('%y-%m-%d_%H-%M-%S.txt') directoryName = '{0}'.format(requester.host) directoryPath = FileUtils.buildPath(self.script_path, 'reports', directoryName) outputFile = FileUtils.buildPath(directoryPath, fileName) if not FileUtils.exists(directoryPath): FileUtils.createDirectory(directoryPath) if not FileUtils.exists(directoryPath): self.output.printError("Couldn't create reports folder {0}".format(directoryPath)) sys.exit(1) if FileUtils.canWrite(directoryPath): report = None if self.arguments.autoSaveFormat == 'simple': report = SimpleReport(requester.host, requester.port, requester.protocol, requester.basePath, outputFile) if self.arguments.autoSaveFormat == 'json': report = JSONReport(requester.host, requester.port, requester.protocol, requester.basePath, outputFile) else: report = PlainTextReport(requester.host, requester.port, requester.protocol, requester.basePath, outputFile) self.reportManager.addOutput(report) else: self.output.printError("Can't write reports to {0}".format(directoryPath)) sys.exit(1) if self.arguments.simpleOutputFile is not None: self.reportManager.addOutput(SimpleReport(requester.host, requester.port, requester.protocol, requester.basePath, self.arguments.simpleOutputFile)) if self.arguments.plainTextOutputFile is not None: self.reportManager.addOutput(PlainTextReport(requester.host, requester.port, requester.protocol, requester.basePath, self.arguments.plainTextOutputFile)) if self.arguments.jsonOutputFile is not None: self.reportManager.addOutput(JSONReport(requester.host, requester.port, requester.protocol, requester.basePath, self.arguments.jsonOutputFile)) def handleInterrupt(self): self.output.printWarning('CTRL+C detected: Pausing threads, please wait...') self.fuzzer.pause() try: while True: msg = "[e]xit / [c]ontinue" if not self.directories.empty(): msg += " / [n]ext" if len(self.arguments.urlList) > 1: msg += " / [s]kip target" self.output.printInLine(msg + ': ') option = input() if option.lower() == 'e': self.exit = True self.fuzzer.stop() raise KeyboardInterrupt elif option.lower() == 'c': self.fuzzer.play() return elif not self.directories.empty() and option.lower() == 'n': self.fuzzer.stop() return elif len(self.arguments.urlList) > 1 and option.lower() == 's': raise SkipTargetInterrupt else: continue except KeyboardInterrupt as SystemExit: self.exit = True raise KeyboardInterrupt def processPaths(self): try: path = self.fuzzer.getPath() while path is not None: try: if path.status is not 0: if path.status not in self.excludeStatusCodes and (self.blacklists.get(path.status) is None or path.path not in self.blacklists.get(path.status)): self.output.printStatusReport(path.path, path.response) self.addDirectory(path.path) self.reportManager.addPath(self.currentDirectory + path.path, path.status, path.response) self.index += 1 self.output.printLastPathEntry(path, self.index, len(self.dictionary)) path = self.fuzzer.getPath() except (KeyboardInterrupt, SystemExit) as e: self.handleInterrupt() if self.exit: raise e else: pass except (KeyboardInterrupt, SystemExit) as e: if self.exit: raise e self.handleInterrupt() if self.exit: raise e else: pass self.fuzzer.wait() def wait(self): while not self.directories.empty(): self.index = 0 self.currentDirectory = self.directories.get() self.output.printWarning('[{1}] Starting: {0}'.format(self.currentDirectory, time.strftime('%H:%M:%S'))) self.fuzzer.requester.basePath = '{0}{1}'.format(self.basePath, self.currentDirectory) self.output.basePath = '{0}{1}'.format(self.basePath, self.currentDirectory) self.fuzzer.start() self.processPaths() return def addDirectory(self, path): if self.recursive == False: return False if path.endswith('/'): if path in [directory + '/' for directory in self.excludeSubdirs]: return False if self.currentDirectory == '': self.directories.put(path) else: self.directories.put('{0}{1}'.format(self.currentDirectory, path)) return True else: return False MAYOR_VERSION = 0 MINOR_VERSION = 3 REVISION = 0 global PROGRAM_BANNER PROGRAM_BANNER = \ r""" __ _|. _ _ _) _ _ _|_ v{0}.{1}.{2} (_||| _) __)(_|| (_| ) """.format(MAYOR_VERSION, MINOR_VERSION, REVISION)
class Fuzzer(object): def __init__(self, requester, dictionary, testFailPath="youCannotBeHere7331", threads=1): self.requester = requester self.dictionary = dictionary self.testFailPath = testFailPath self.testedPaths = Queue() self.basePath = self.requester.basePath self.threads = [] self.threadsCount = threads if len( self.dictionary) >= threads else len(self.dictionary) self.running = False self.testers = {} def wait(self): for thread in self.threads: thread.join() def testersSetup(self): if len(self.testers) != 0: self.testers = {} self.testers['/'] = NotFoundTester(self.requester, '{0}/'.format(self.testFailPath)) for extension in self.dictionary.extensions: self.testers[extension] = NotFoundTester( self.requester, '{0}.{1}'.format(self.testFailPath, extension)) def threadsSetup(self): if len(self.threads) != 0: self.threads = [] for thread in range(self.threadsCount): newThread = threading.Thread(target=self.thread_proc) newThread.daemon = True self.threads.append(newThread) def getTester(self, path): for extension in list(self.testers.keys()): if path.endswith(extension): return self.testers[extension] # By default, returns folder tester return self.testers['/'] def start(self): # Setting up testers self.testersSetup() # Setting up threads self.threadsSetup() self.index = 0 self.dictionary.reset() self.runningThreadsCount = len(self.threads) self.running = True self.playEvent = threading.Event() self.pausedSemaphore = threading.Semaphore(0) self.playEvent.clear() self.exit = False for thread in self.threads: thread.start() self.play() def play(self): self.playEvent.set() def pause(self): self.playEvent.clear() for thread in self.threads: if thread.is_alive(): self.pausedSemaphore.acquire() def stop(self): self.running = False self.play() def testPath(self, path): response = self.requester.request(path) result = 0 if self.getTester(path).test(response): result = (0 if response.status == 404 else response.status) return result, response def isRunning(self): return self.running def finishThreads(self): self.running = False self.finishedEvent.set() def getPath(self): path = None if not self.empty(): path = self.testedPaths.get() if not self.isFinished(): path = self.testedPaths.get() return path def qsize(self): return self.testedPaths.qsize() def empty(self): return self.testedPaths.empty() def isFinished(self): return self.runningThreadsCount == 0 def stopThread(self): self.runningThreadsCount -= 1 if self.runningThreadsCount is 0: self.testedPaths.put(None) def thread_proc(self): self.playEvent.wait() try: path = next(self.dictionary) while path is not None: try: status, response = self.testPath(path) self.testedPaths.put( Path(path=path, status=status, response=response)) except RequestException as e: print('\nUnexpected error:\n{0}\n'.format( e.args[0]['message'])) sys.stdout.flush() continue finally: if not self.playEvent.isSet(): self.pausedSemaphore.release() self.playEvent.wait() path = next( self.dictionary) # Raises StopIteration when finishes if not self.running: break except StopIteration: return finally: self.stopThread()
def __init__(self, script_path, arguments, output): self.script_path = script_path self.exit = False self.arguments = arguments self.output = output self.blacklists = self.getBlacklists() self.fuzzer = None self.recursive = self.arguments.recursive self.excludeStatusCodes = self.arguments.excludeStatusCodes self.recursive = self.arguments.recursive self.directories = Queue() self.excludeSubdirs = (arguments.excludeSubdirs if arguments.excludeSubdirs is not None else []) self.output.printHeader(PROGRAM_BANNER) self.dictionary = FuzzerDictionary(self.arguments.wordlist, self.arguments.extensions, self.arguments.lowercase) self.printConfig() try: for url in self.arguments.urlList: try: self.currentUrl = url self.reportManager = ReportManager() self.requester = Requester( url, cookie=self.arguments.cookie, useragent=self.arguments.useragent, maxPool=self.arguments.threadsCount, maxRetries=self.arguments.maxRetries, timeout=self.arguments.timeout, ip=self.arguments.ip, proxy=self.arguments.proxy, redirect=self.arguments.redirect) for key, value in arguments.headers.items(): self.requester.setHeader(key, value) # Initialize directories Queue with start Path self.basePath = self.requester.basePath if self.arguments.scanSubdirs is not None: for subdir in self.arguments.scanSubdirs: self.directories.put(subdir) else: self.directories.put('') self.setupReports(self.requester) self.output.printTarget(self.currentUrl) self.fuzzer = Fuzzer( self.requester, self.dictionary, testFailPath=self.arguments.testFailPath, threads=self.arguments.threadsCount) self.wait() except SkipTargetInterrupt: continue except RequestException as e: self.output.printError('Unexpected error:\n{0}'.format( e.args[0]['message'])) exit(0) except KeyboardInterrupt as SystemExit: self.output.printError('\nCanceled by the user') exit(0) finally: self.reportManager.save() self.reportManager.close() self.output.printWarning('\nTask Completed')
class Controller(object): def __init__(self, script_path, arguments, output): self.script_path = script_path self.exit = False self.arguments = arguments self.output = output self.blacklists = self.getBlacklists() self.fuzzer = None self.recursive = self.arguments.recursive self.excludeStatusCodes = self.arguments.excludeStatusCodes self.recursive = self.arguments.recursive self.directories = Queue() self.excludeSubdirs = (arguments.excludeSubdirs if arguments.excludeSubdirs is not None else []) self.output.printHeader(PROGRAM_BANNER) self.dictionary = FuzzerDictionary(self.arguments.wordlist, self.arguments.extensions, self.arguments.lowercase) self.printConfig() try: for url in self.arguments.urlList: try: self.currentUrl = url self.reportManager = ReportManager() self.requester = Requester( url, cookie=self.arguments.cookie, useragent=self.arguments.useragent, maxPool=self.arguments.threadsCount, maxRetries=self.arguments.maxRetries, timeout=self.arguments.timeout, ip=self.arguments.ip, proxy=self.arguments.proxy, redirect=self.arguments.redirect) for key, value in arguments.headers.items(): self.requester.setHeader(key, value) # Initialize directories Queue with start Path self.basePath = self.requester.basePath if self.arguments.scanSubdirs is not None: for subdir in self.arguments.scanSubdirs: self.directories.put(subdir) else: self.directories.put('') self.setupReports(self.requester) self.output.printTarget(self.currentUrl) self.fuzzer = Fuzzer( self.requester, self.dictionary, testFailPath=self.arguments.testFailPath, threads=self.arguments.threadsCount) self.wait() except SkipTargetInterrupt: continue except RequestException as e: self.output.printError('Unexpected error:\n{0}'.format( e.args[0]['message'])) exit(0) except KeyboardInterrupt as SystemExit: self.output.printError('\nCanceled by the user') exit(0) finally: self.reportManager.save() self.reportManager.close() self.output.printWarning('\nTask Completed') def printConfig(self): self.output.printConfig(', '.join(self.arguments.extensions), str(self.arguments.threadsCount), str(len(self.dictionary))) def getBlacklists(self): blacklists = {} for status in [400, 403, 500]: blacklistFileName = FileUtils.buildPath(self.script_path, 'db') blacklistFileName = FileUtils.buildPath( blacklistFileName, '{0}_blacklist.txt'.format(status)) if not FileUtils.canRead(blacklistFileName): continue blacklists[status] = [] for line in FileUtils.getLines(blacklistFileName): # Skip comments if line.startswith('#'): continue blacklists[status].append(line) return blacklists def setupReports(self, requester): if self.arguments.autoSave: basePath = ('/' if requester.basePath is '' else requester.basePath) basePath = basePath.replace(os.path.sep, '.')[1:-1] fileName = ('{0}_'.format(basePath) if basePath is not '' else '') fileName += time.strftime('%y-%m-%d_%H-%M-%S.txt') directoryName = '{0}'.format(requester.host) directoryPath = FileUtils.buildPath(self.script_path, 'reports', directoryName) outputFile = FileUtils.buildPath(directoryPath, fileName) if not FileUtils.exists(directoryPath): FileUtils.createDirectory(directoryPath) if not FileUtils.exists(directoryPath): self.output.printError( "Couldn't create reports folder {0}".format( directoryPath)) sys.exit(1) if FileUtils.canWrite(directoryPath): report = None if self.arguments.autoSaveFormat == 'simple': report = SimpleReport(requester.host, requester.port, requester.protocol, requester.basePath, outputFile) if self.arguments.autoSaveFormat == 'json': report = JSONReport(requester.host, requester.port, requester.protocol, requester.basePath, outputFile) else: report = PlainTextReport(requester.host, requester.port, requester.protocol, requester.basePath, outputFile) self.reportManager.addOutput(report) else: self.output.printError( "Can't write reports to {0}".format(directoryPath)) sys.exit(1) if self.arguments.simpleOutputFile is not None: self.reportManager.addOutput( SimpleReport(requester.host, requester.port, requester.protocol, requester.basePath, self.arguments.simpleOutputFile)) if self.arguments.plainTextOutputFile is not None: self.reportManager.addOutput( PlainTextReport(requester.host, requester.port, requester.protocol, requester.basePath, self.arguments.plainTextOutputFile)) if self.arguments.jsonOutputFile is not None: self.reportManager.addOutput( JSONReport(requester.host, requester.port, requester.protocol, requester.basePath, self.arguments.jsonOutputFile)) def handleInterrupt(self): self.output.printWarning( 'CTRL+C detected: Pausing threads, please wait...') self.fuzzer.pause() try: while True: msg = "[e]xit / [c]ontinue" if not self.directories.empty(): msg += " / [n]ext" if len(self.arguments.urlList) > 1: msg += " / [s]kip target" self.output.printInLine(msg + ': ') option = input() if option.lower() == 'e': self.exit = True self.fuzzer.stop() raise KeyboardInterrupt elif option.lower() == 'c': self.fuzzer.play() return elif not self.directories.empty() and option.lower() == 'n': self.fuzzer.stop() return elif len(self.arguments.urlList) > 1 and option.lower() == 's': raise SkipTargetInterrupt else: continue except KeyboardInterrupt as SystemExit: self.exit = True raise KeyboardInterrupt def processPaths(self): try: path = self.fuzzer.getPath() while path is not None: try: if path.status is not 0: if path.status not in self.excludeStatusCodes and ( self.blacklists.get(path.status) is None or path.path not in self.blacklists.get( path.status)): self.output.printStatusReport( path.path, path.response) self.addDirectory(path.path) self.reportManager.addPath( self.currentDirectory + path.path, path.status, path.response) self.index += 1 self.output.printLastPathEntry(path, self.index, len(self.dictionary)) path = self.fuzzer.getPath() except (KeyboardInterrupt, SystemExit) as e: self.handleInterrupt() if self.exit: raise e else: pass except (KeyboardInterrupt, SystemExit) as e: if self.exit: raise e self.handleInterrupt() if self.exit: raise e else: pass self.fuzzer.wait() def wait(self): while not self.directories.empty(): self.index = 0 self.currentDirectory = self.directories.get() self.output.printWarning('[{1}] Starting: {0}'.format( self.currentDirectory, time.strftime('%H:%M:%S'))) self.fuzzer.requester.basePath = '{0}{1}'.format( self.basePath, self.currentDirectory) self.output.basePath = '{0}{1}'.format(self.basePath, self.currentDirectory) self.fuzzer.start() self.processPaths() return def addDirectory(self, path): if self.recursive == False: return False if path.endswith('/'): if path in [directory + '/' for directory in self.excludeSubdirs]: return False if self.currentDirectory == '': self.directories.put(path) else: self.directories.put('{0}{1}'.format(self.currentDirectory, path)) return True else: return False MAYOR_VERSION = 0 MINOR_VERSION = 3 REVISION = 0 global PROGRAM_BANNER PROGRAM_BANNER = \ r""" __ _|. _ _ _) _ _ _|_ v{0}.{1}.{2} (_||| _) __)(_|| (_| ) """.format(MAYOR_VERSION, MINOR_VERSION, REVISION)