Ejemplo n.º 1
0
def run_scans(host: Host, scans_to_run: list, force: bool = False) -> None:
    """
    Checks if a host meets prerequisites for scans, and runs them.
    """
    # TODO research implementing Threads for this
    # TODO add fault tolerance
    #
    # Iterate over all available tests in the core/scans directory
    # Import the module from core.scans, then the class from the module
    # and finally initialize the class, passing the host to scan.
    for scan in scans_to_run:
        module = import_module("core.scans.{}".format(scan))
        temp = getattr(module, file_to_class_name(scan))
        current_scan = temp(host)

        if current_scan.requirements_met() and not force:
            current_scan.set_config()
            low("Starting {} scan.".format(temp))
            current_scan.run_scan()
            host.scans = current_scan.process_results()
        elif force:
            current_scan.set_config()
            warning("Forcing {} scan to run.".format(temp))
            current_scan.run_scan()
            host.scans = current_scan.process_results()
        else:
            low("Requirements not met for {} scan, skipping.".format(temp))
Ejemplo n.º 2
0
def zap_setup_context(target: Host, port: str, user: str,
                      passwd: str) -> tuple:
    """
    Creates a context for this scan, adding a new user to that context and sets up
    the authentication mechanism.
    """
    zap = ZAPv2()

    if port == '443':
        url = "https://{}".format(str(target))
    else:
        url = "http://{}".format(str(target))

    low("Creating new context for zap scan.")
    context_id = zap.context.new_context("ZapScan")

    zap.context.include_in_context("ZapScan", "{}.*".format(str(target)))
    zap.context.include_in_context("ZapScan", "{}.*".format(url))
    zap.authentication.set_authentication_method(
        context_id, 'httpAuthentication',
        'hostname={}&realm='.format(str(target)))

    low("Creating user for context.")
    user_id = zap.users.new_user(context_id, "zapuser")
    zap.users.set_authentication_credentials(
        context_id, user_id, "username={}&password={}".format(user, passwd))
    zap.users.set_user_enabled(context_id, user_id, True)

    zap.forcedUser.set_forced_user(context_id, user_id)
    zap.forcedUser.set_forced_user_mode_enabled(True)

    return context_id, user_id
Ejemplo n.º 3
0
def start_zap():
    """
    Start up the Zaproxy application so the python API can communicate with it.
    """
    try:
        zap = ZAPv2()
        zap.urlopen('http://127.0.0.1')
    except:
        low("Starting the zaproxy application.")
        Popen(['zaproxy'], stdout=DEVNULL, stderr=DEVNULL)
        wait_for_zap()
Ejemplo n.º 4
0
    def set_config(self) -> None:
        try:
            self.user = self.target.credentials['user']
            self.password = self.target.credentials['passwd']
        except KeyError:
            low("User/Pass not supplied for nikto scan, running without credentials.")
            self.user = ""
            self.password = ""

        for temp in self.target.open_ports:
            if temp in WEB_PORTS:
                self.port = temp
                break
Ejemplo n.º 5
0
    def set_config(self) -> None:
        try:
            self.user = self.target.credentials['user']
            self.password = self.target.credentials['passwd']
        except KeyError:
            low("No USER/PASS provided for zap scan, running without them.")
            self.user = ""
            self.password = ""

        for temp in self.target.open_ports:
            if temp in ('80', '8080', '443'):
                self.port = temp
                break
Ejemplo n.º 6
0
def prereq_scans(host: Host, scans_to_skip: list) -> None:
    """
    PortScan and HydraScan are needed to run first, results from them highly influence
    scans that follow after.
    """
    low("Getting services for target {}".format(str(host)))
    port_scan = PortScan(host)
    if port_scan.requirements_met:
        port_scan.run_scan()
        host.services = port_scan.process_results().results
        host.open_ports = [port['id'] for port in host.services['ports']]
    else:
        low('Prerequisites not met for PortScan.')
        return

    debug(host.services)
    debug("HAS AUTH: {}".format(host.has_auth_surface()))
    debug("HAS WEB: {}".format(host.has_web_interface()))

    hydra_scan = HydraScan(host)
    if hydra_scan.requirements_met() and 'hydra_scan' not in scans_to_skip:
        low("Host {} has interface for brute forcing creds, beginning scan.".
            format(host))
        scans_to_skip.append('hydra_scan')
        hydra_scan.set_config()
        hydra_scan.run_scan()
        creds = hydra_scan.process_results()
        host.credentials = {
            'user': creds['results'][0]['login'],
            'passwd': creds['results'][0]['password']
        }
    else:
        low("Username and password supplied, skipping auth scan.")
Ejemplo n.º 7
0
    def run_scan(self) -> None:
        """
        Perform nmap port scan and suppress output
        """
        self.output_name = '{}/port_scan{}.xml'.format(
            SCAN_OUTPUT_DIR,
            datetime.now().strftime(DATE_ARGS))

        nmap = Popen(
            ['nmap', str(self.target), '-oX', self.output_name],
            stdout=DEVNULL,
            stderr=DEVNULL)

        low("Waiting for port scan on {} to complete".format(str(self.target)))
        nmap.wait()
        low("Port scan on {} completed.".format(str(self.target)))
Ejemplo n.º 8
0
    def run_scan(self) -> None:
        """
        Perform nmap OS fingerprint scan
        """
        self.output_name = '{}/os_scan{}.xml'.format(
            SCAN_OUTPUT_DIR,
            datetime.now().strftime(DATE_ARGS))

        nmap = Popen(
            ['nmap', str(self.target), '-O', '-oX', self.output_name],
            stdout=DEVNULL,
            stderr=DEVNULL)

        low("Waiting for OS fingerprint scan on {} to complete".format(
            str(self.target)))
        nmap.wait()
        low("OS fingerprint scan on {} completed.".format(str(self.target)))
Ejemplo n.º 9
0
def skipfish_scan(target: Host, port: str) -> str:
    """
        DEPRECATED: TODO re-evaulate it's worth, then potentially create Scan
        Drive Skipfish scan against a specified port, save output to a file and return
        outpu file name.
    """
    # File name to save output to
    fname = '{}/skipfish_scan{}_{}.xml'.format(
        SCAN_OUTPUT_DIR, port,
        datetime.now().strftime('%m-%d_%H-%M-%S'))

    skipfish = Popen(['skipfish', '-o', fname, str(target)])
    low('Waiting for Skipfish scan on port {} to complete.'.format(port))

    skipfish.wait()

    low('Skipfish scan completed.')
    return fname
Ejemplo n.º 10
0
    def run_scan(self) -> None:
        """
        Runs zap spider scan with a context including user/pass IF that is available to do so
        """
        start_zap()
        zap = ZAPv2()
        self.output_name = '{}/nikto_scan{}_{}.xml'.format(SCAN_OUTPUT_DIR, self.port,
                                                           datetime.now().strftime(DATE_ARGS))

        if self.port == '443':
            url = "https://{}".format(str(self.target))
        else:
            url = "http://{}".format(str(self.target))

        low("Beginning zap spider on {}".format(url))
        zap.urlopen(url)
        sleep(1)

        if self.user and self.password:
            context_id, user_id = zap_setup_context(self.target, self.port, self.user, self.password)
            spider_id = zap.spider.scan_as_user(context_id, user_id, url)
        else:
            spider_id = zap.spider.scan(url)


        # Scanning as user, just in case forced user mode is wonky
        sleep(1)
        low("Waiting for scan to complete".format(url))
        while int(zap.spider.status(spider_id)) < 100:
            sleep(1)

        low("Spider scan complete.")
        low("Collecting any alerts from spider.")
        while int(zap.pscan.records_to_scan) > 0:
            sleep(1)

        low("Alerts collected.")

        json = zap.core.jsonreport()
        self.output_name = '{}/zap_spider_{}.json'.format(SCAN_OUTPUT_DIR, datetime.now().strftime(
            '%m-%d_%H-%M-%S'))

        with open(self.output_name, "w") as f:
            f.write(json)
Ejemplo n.º 11
0
def host_scan(subnet: str) -> str:
    """
    Drive nmap host scan, save output to a file and return output file name.
    """
    # File name to save output to
    fname = '{}/host_scan{}.xml'.format(
        SCAN_OUTPUT_DIR,
        datetime.now().strftime('%m-%d_%H-%M-%S'))

    # Drive host scan and output to file
    nmap = Popen(['nmap', subnet, '-sn', '-oX', fname],
                 stdout=DEVNULL,
                 stderr=DEVNULL)
    low("Waiting for host scan to complete.")

    nmap.wait()

    low("Host scan completed.")
    return fname
Ejemplo n.º 12
0
    def run_scan(self) -> None:
        """
        Runs actual nikto web app scan with basic args
        """
        self.output_name = '{}/nikto_scan{}_{}.xml'.format(SCAN_OUTPUT_DIR, self.port, datetime.now().strftime(
            DATE_ARGS))

        # This scanner can be helpful with stdout since it doesnt flood logs and can
        # be polled for progress of the scan
        low('Waiting for Nikto scan on port {} to complete'.format(self.port))
        if self.user and self.password:
            nikto = Popen(['nikto', '-host', str(self.target), '-port',
                           self.port, '-id', '{}:{}'.format(self.user, self.password),
                           '-output', self.output_name])
        else:
            nikto = Popen(['nikto', '-host', str(self.target), '-port', self.port, '-output', self.output_name])

        nikto.wait()
        low('Nikto scan completed.')
Ejemplo n.º 13
0
def handle_args(args: Namespace) -> list:
    """
    Parse arguments for scan and configure host objects. The scan arg is more demanding about
    the information it requires before it will run tests, and will not attempt to dynamically
    figure out information about the target before running a scan.
    """
    low("Target supplied: {}".format(args.target))
    hosts = [Host(host) for host in args.target]

    if args.credentials:
        if len(args.credentials.split(':')) != 2:
            warning("Credentials should be as supplied <USER>:<PASS>")
            low("Defaulting to no credentials")
        else:
            low("User and Password supplied for scans, {}".format(
                args.credentials))
            for host in hosts:
                host.credentials = {
                    'user': args.credentials.split(':')[0],
                    'passwd': args.credentials.split(':')[1]
                }

    for host in hosts:
        host.open_ports = args.ports

    return hosts
Ejemplo n.º 14
0
    def run_scan(self) -> None:
        """
        Perform actual scan by brute forcing the service available on the host
        """
        # File name to save output to
        self.output_name = '{}/hydra_scan{}_{}.json'.format(SCAN_OUTPUT_DIR, self.service, datetime.now().strftime(
            '%m-%d_%H-%M-%S'))

        try:
            warning("Brute forcing credentials can take a long time, consider running with creds.")
            hydra = Popen([
                'hydra', '-L', WORD_LIST, '-P', WORD_LIST, '-u', '-f', '-o', self.output_name,
                "-b", "json", "{}://{}".format(self.service, str(self.target))])

            low('Waiting for hydra scan on {} to complete.'.format(self.service))
            hydra.wait()
        except KeyboardInterrupt:
            low("Hydra scan aborted. Other scans may not be as effective without credentials.")

        low('Hydra scan completed.')
Ejemplo n.º 15
0
def handle_args(args: Namespace) -> list:
    """
    Parse arguments for test and configure host objects.
    """
    # If no targets provided, assume were finding them on network.
    # Once we have targets, if no test given, port/service scan them.
    if not args.target:
        low("Target not supplied, running host scan.")
        hosts = get_hosts(verify_subnet(args.subnet))
    else:
        low("Target supplied: {}".format(args.target))
        hosts = [Host(host) for host in args.target]

    if args.user and args.passwd:
        low("Username and Password supplied for tests, {}:{}".format(
            args.user, args.passwd))
        for host in hosts:
            host.credentials = {'user': args.user, 'passwd': args.passwd}

    return hosts