def run_modules(self): """ Runs all the modules in the current scan. runs through each module in the selected scan type and calls its run method, which runs the scan for that specific module Args: None Returns: None """ # check that the scan type passed in by command line is defined # in the config file, if not exit if self.scan_type not in self.scan_types: warning(f'Scan type {self.scan_type} not in config file') exit() # build a list of the modules in the scan type modules_to_run = [] for module_name in self.scan_types[self.scan_type]: try: modules_to_run.append(self.modules[module_name]) except KeyError: warning(f'Module name {module_name} not found.' 'Please check the config file.') exit() # loop through the modules in the scan type and call the run method for module in modules_to_run: module.run_module()
def save_report(self, text): ext = '' if self.type == 'text': ext = '.txt' elif self.type == 'html': ext = '.html' elif self.type == 'pdf': ext = '.pdf' else: ext = '.txt' date = datetime.datetime.now().strftime("%d-%m-%Y-%H:%M:%S") filename = f'WAVS Report - {date}' path = f'reports/{filename}{ext}' if self.type == 'pdf': text.write_pdf(path) else: try: with open(path, 'w') as f: f.write(text) except IOError: warning(f'Could not save report: {path}') exit() info(f'Saved report to: {path}')
def _run_thread(self, form): """ search through form parameters to find anti-csrf tokens """ if len(form) != 3: warning('Internal error, not enough form elements in CSRF') exit() # give the form data human friendly names method = form['method'] page = form['action'] params = form['params'] # were only concerned with POST requests for CSRF if method == 'POST': # check if param names contain any anti-csrf token params if not any(csrf_name in params for csrf_name in self.csrf_fields): success(f'No anti-csrf tokens for: {page}/{",".join(params)}', prepend=' ') return { 'method': method, 'page': page, 'parameter': params, 'payload': None }
def _get_previous_results(self, module_name): """ loads in results from previous scans, should be overwritten to load in specific results needed for this module Args: module_name: name of the module to load results from Returns: a list of results from a module """ # modules should be located in the modules.core package module = load_module("modules.core", module_name) # if the module didnt load if not module: warning(f'Could not find module {module_name}') exit() # get the modules table name table_name = module.info['db_table_name'] # get the contents of the table table = self.main.db.get_scan_db().table(table_name) # get the results for this scan results = table.search(where('scan_id') == self.main.id) # put all the results into one list final = [] for r in results: final.extend(r['results']) return final
def __init__(self): self.db_paths = {} self.db_paths['wordlist'] = 'database/wordlists.db' # the database to hold scan results self.db_paths['scan_results'] = 'database/scans.db' # the 'wordlist' database is required for the program to function # so if it cant be found the program should warn and exit if not os.path.exists(self.db_paths['wordlist']): warning(f'Could not find wordlist database at: ' f'{self.db_paths["wordlist"]}') exit()
def show_previous_scans(self): """ Displays a list of past scans and allows user to select one. This method prints out a list of all the past scans saved in the 'scans' database, along with their scan IDs. It prompts the user to enter the scan ID of the scan to be selected. Args: None Returns: the scan ID of the selected scan """ info('Previous scans:') # store an instance of the 'scans' database scans_table = self.db.get_scan_db().table('scans') # get all the saved scans scans = scans_table.all() # loop through each scan for scan in scans: # print the scan details to stdout success( f'ID: {scan.doc_id},' f'Host: {scan["host"]}', f'Port: {scan["port"]}', f'Time: {scan["timestamp"]}', prepend=' ') # prompt the user to enter the scan ID of the scan to be selected # it will reject scan IDs which dont exist, and any input which is # not an int check = False while not check: try: choice = int(input('> ')) if not self.db.scan_exists(choice): warning(f'Scan ID: {choice} does not exist') else: check = True except (ValueError): pass return choice
def _load_modules(self, modules_list): """ Loads in vulnerability scanner modules. Takes a list of modules to load, imports the associated python module then instantiates the class in the module. It saves the instance in a list. Args: modules_list: a list of strings, the modules to be loaded Returns: a list of dictionaries containing instance of loaded module """ # temporary list to hold loaded modules modules_loaded = {} # loop through each module string in the list for mod in modules_list: # split the string into package name, and class name module_path_list = mod.split('/') class_name = module_path_list[-1:][0] package_name = '.'.join(module_path_list[:-1]) # load the module temp_module = load_module(package_name, class_name) # if the module could not be found, exit if not temp_module: warning(f"Could not load the module at {mod}.") exit() # instantiate the loaded module, passing in the Webscanner instance temp_module = temp_module(self) # save the module instance by its name in a dict if hasattr(temp_module, "info"): modules_loaded[temp_module.info["name"]] = temp_module # return all the instances of loaded modules return modules_loaded
def _check_fuzzing(self): ''' checks if a random string returns a 200 success code. a 200 code would mean the web application is returning 200 for all requests. :param: :return: ''' # construct a random string of length 10 should_not_find = ''.join( random.choice(string.ascii_lowercase) for i in range(20)) # make a get request with random string as a directory resp = requests.get( f'{self.main.get_host_url_base()}/' f'{should_not_find}', self.main.cookies) # check for success code if resp.status_code == 200: warning(f'/{should_not_find} returned code 200. ') warning('Consider removing code 200 as success code') exit()
def _parse_cmd_line_args(self): """ Parses command line arguments. parses the command line arguments passed into the program, and makes sure the arguments passed are valid. Args: None Returns: None """ # save the command line arguments arg_parse = self.cmd_args # a protocol needs to be supplied in host and needs to be # either http or https, otherwise the program should exit if arg_parse.host[:4] != 'http': warning('Please specify the protocol for host, http or https') exit() # split the host into protocol and ip/hostname self.proto, self.host = arg_parse.host.split('://') self.proto += '://' # if no port is specified then set port based on protocol, # these are the default ports for the http and https protocols if arg_parse.port == 0: if self.proto == 'http://': self.port = 80 elif self.proto == 'https://': self.port = 443 else: self.port = arg_parse.port # make sure the base directory starts with a / # if base_dir is '' we dont need to worry if arg_parse.base_dir: self.base_dir = arg_parse.base_dir if self.base_dir[0] != '/': self.base_dir = f'/{self.base_dir}' else: self.base_dir = arg_parse.base_dir # if cookies are supplied, parses the cookies into a dictionary which # is required by the requests module temp_cookies = http.cookies.SimpleCookie(arg_parse.cookies) self.cookies = requests.cookies.RequestsCookieJar() self.cookies.update(temp_cookies) # store the scan type, must be a value listed in the config.json file # under 'scan_types', if not specified by command line argument the # 'default' scan type is stored self.scan_type = arg_parse.type # parse any restricted paths passed in from command line # these paths on the target application that should not be crawled if arg_parse.restrict_paths: # if a list has been passed, split the list if ',' in arg_parse.restrict_paths: self.restrict_paths = arg_parse.restrict_paths.split(',') else: # otherwise make the single path into a list self.restrict_paths = [arg_parse.restrict_paths] else: self.restrict_paths = [] # add success codes passed in from command line if arg_parse.add_success_codes: self.success_codes.extend([ code for code in arg_parse.add_success_codes if code not in self.success_codes]) # remove success codes passed in from command line if arg_parse.remove_success_codes: self.success_codes = [ code for code in self.success_codes if code not in arg_parse.remove_success_codes] # whether or not to create report self.should_create_report = not arg_parse.no_report # this option controls whether the 'Crawler' module should crawl the # target automatically, or whether it should use a proxy to let the # user crawl the target manually through a web browser self.options['manual_crawl'] = arg_parse.manual_crawl # save the report extension self.options['report_extension'] = arg_parse.save_ext
from util_functions import warning # text generation module try: from textgenrnn import textgenrnn except ImportError: warning('Text generation relies on textgenrnn module, which wasnt found.') warning('Use "pip3 install textgenrnn"') exit() class TextGenerator: def __init__(self, main): self.main = main self.textgen = textgenrnn() def _train_on_text(self, text_list): epochs_to_train = self.main.options['text_gen_epochs'] try: self.textgen.train_on_texts(text_list, num_epochs=epochs_to_train) except: pass def generate(self, text_list): self._train_on_text(text_list) generated_list = [] temperature = self.main.options['text_generator_temp'] try: generated_list = self.textgen.generate(n=10, temperature=temperature,
from conf import config from util_functions import info, success, warning import datetime import textwrap from html import escape try: from weasyprint import HTML except: warning('GTK not installed. Cant create PDF reports') HTML = {} class ReportGenerator: def __init__(self, main): self.main = main self.report_type = self.main.options['report_extension'] def generate_report(self, scan_id): if self.report_type == 'html': self.generate_html(scan_id) elif self.report_type == 'txt': self.generate_txt(scan_id) elif self.report_type == 'pdf': self.generate_pdf(scan_id) def generate_txt(self, scan_id): generator = TextReportGenerator(self.main, scan_id) generator.save_report(generator.render()) def generate_html(self, scan_id): generator = HTMLReportGenerator(self.main, scan_id)