示例#1
0
    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()
示例#2
0
    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}')
示例#3
0
    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
                }
示例#4
0
    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
示例#5
0
    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()
示例#6
0
    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
示例#7
0
    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
示例#8
0
    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()
示例#9
0
    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
示例#10
0
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,
示例#11
0
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)