def do_mission(self, args):
        """Missions management"""
        print()

        req = MissionsRequester(self.sqlsess)
        if args.add:
            if req.add(args.add):
                self.change_current_mission(args.add, verbose=True)
        elif args.comment:
            req.add_filter(Condition(args.comment[0], FilterData.MISSION_EXACT))
            req.edit_comment(args.comment[1])
        elif args.delete:
            req.add_filter(Condition(args.delete, FilterData.MISSION_EXACT))
            req.delete()        
        elif args.reset:
            if Output.prompt_confirm('Are you sure you want to delete all missions ?', default=False):
                req.reset()
        elif args.rename:
            req.rename(args.rename[0], args.rename[1])
        elif args.search:
            filter_ = Filter()
            filter_.add_condition(Condition(args.search, FilterData.MISSION))
            filter_.add_condition(Condition(args.search, FilterData.COMMENT_MISSION))
            req.add_filter(filter_)
            req.show(self.current_mission)
        elif args.name:
            self.change_current_mission(args.name, verbose=True)
        else:
            print('All available missions:')
            req.show(self.current_mission)

        print()
コード例 #2
0
    def __run_install_update(self, fast_mode, update=False):
        """
        Run install or update command.

        :param fast_mode: Set to true to disable prompts
        :param update: Mode selector, True for update | False for install (default)
        :return: Install/Update status
        :rtype: bool
        """
        if update : cmd = self.update_command.get_cmdline(self.tool_dir)
        else      : cmd = self.install_command.get_cmdline(self.tool_dir)

        mode = 'update' if update else 'install'

        logger.info('Description: {descr}'.format(descr=self.description))
        #Output.print('{mode} command : {cmd}'.format(
        #   mode=mode.capitalize(), cmd=cmd_short))

        if fast_mode \
           or Output.prompt_confirm('Confirm {mode} ?'.format(mode=mode), default=True):

            Output.begin_cmd(cmd)
            ProcessLauncher(cmd).start()
            Output.delimiter()
            logger.success('Tool {mode} has finished'.format(mode=mode))
            return True
        else:
            logger.warning('Tool {mode} aborted'.format(mode=mode))
            return False
    def attack(self):
        """
        Run the attack against all targets
        :param fast_mode:
        """

        # Initialize top status/progress bar
        # If single target (total=None), the counter format will be used instead of the progress bar format
        attack_progress = manager.counter(
            total=len(self.targets) + 1 if len(self.targets) > 1 else None,
            desc='',
            unit='target',
            bar_format=STATUSBAR_FORMAT,  # For multi targets
            counter_format=STATUSBAR_FORMAT_SINGLE)  # For single target

        time.sleep(.5)  # hack for progress bar display

        for i in range(1, len(self.targets) + 1):
            print()
            self.show_summary()
            print()

            # Target selection
            if not self.fast_mode:
                if len(self.targets) > 1:
                    self.current_targetid = Output.prompt_choice_range(
                        'Attack target # ? [{default}] '.format(
                            default=self.current_targetid), 1,
                        len(self.targets), self.current_targetid)
                else:
                    if Output.prompt_confirm('Start attack ?', default=True):
                        self.current_targetid = 1
                    else:
                        logger.warning('Attack canceled !')
                        sys.exit(1)

            target = self.targets[self.current_targetid - 1]

            # Update status/progress bar
            status = 'Current target [{cur}/{total}]: host {ip} | port {port}/{proto} | service {service}'.format(
                cur=i,
                total=len(self.targets),
                ip=target.get_ip(),
                port=target.get_port(),
                proto=target.get_protocol(),
                service=target.get_service_name())
            attack_progress.desc = '{status}{fill}'.format(
                status=status, fill=' ' * (DESC_LENGTH - len(status)))
            attack_progress.update()
            print()

            # Launch the attack on the selected target
            self.__attack_target(self.current_targetid, attack_progress)
            self.current_targetid += 1

        attack_progress.update()
        time.sleep(.5)

        attack_progress.close()
        manager.stop()  # Clear progress bars
    def do_hosts(self, args):
        """Hosts in the current mission scope"""
        print()
        req = HostsRequester(self.sqlsess)
        req.select_mission(self.current_mission)

        # Logical AND is applied between all specified filtering options
        filter_ = Filter(FilterOperator.AND)
        if args.addrs:
            for addr in args.addrs:
                if NetUtils.is_valid_ip(addr) or NetUtils.is_valid_ip_range(addr):
                    filter_.add_condition(Condition(addr, FilterData.IP))
                else:
                    filter_.add_condition(Condition(addr, FilterData.HOST))
        if args.search:
            filter_search = Filter(FilterOperator.OR)
            filter_search.add_condition(Condition(args.search, FilterData.HOST))
            filter_search.add_condition(Condition(args.search, FilterData.OS))
            filter_search.add_condition(Condition(args.search, FilterData.COMMENT_HOST))
            filter_.add_condition(filter_search)
        if args.order:
            req.order_by(args.order)

        try:
            req.add_filter(filter_)
        except FilterException as e:
            logger.error(e)
            return

        # Operations
        if args.comment:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to edit comment for ALL hosts in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.edit_comment(args.comment)
        elif args.delete:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to delete ALL hosts and related services in current mission', default=False):
                    logger.info('Canceled')
                    return
            req.delete()
        else:
            req.show()

        print()
コード例 #5
0
    def __check_post_install_update(self, settings, fast_mode, update=False):
        """
        Post-install/update checks
        :param settings: Settings instance
        :param fast_mode: Boolean indicating whether prompts must be displayed or not
        :return: Boolean indicating status
        """
        mode = ('update', 'updated') if update else ('install', 'installed')
        status = True

        if not fast_mode:
            if not self.check_command:
                logger.info('No check_command defined in settings for {tool}, will assume it is ' \
                'correctly {mode}'.format(tool=self.name_display, mode=mode[1]))
            else:
                logger.info(
                    'Now, checking if {tool} has been {mode} correctly. Hit any key to run test...'
                    .format(tool=self.name_display, mode=mode[1]))
                CLIUtils.getch()
                status = self.__run_check_command()

        # Change install status in configuration file
        if status:
            try:
                if settings.change_installed_status(self.target_service,
                                                    self.name_clean,
                                                    install_status=True):
                    logger.success(
                        'Tool {tool} has been marked as successfully {mode}'.
                        format(tool=self.name_display, mode=mode[1]))
                    return True
                else:
                    logger.error(
                        'Error when updating configuration file "{filename}{ext}"'
                        .format(filename=INSTALL_STATUS_CONF_FILE,
                                ext=CONF_EXT))
                    return False
            except SettingsException as e:
                logger.error('An unexpected error occured when trying to mark the tool as {mode}: ' \
                    '{exception}'.format(exception=e, mode=mode[1]))
                if not update:
                    self.remove(settings)
                return False
        else:
            logger.warning('Tool {tool} has not been marked as {mode}'.format(
                tool=self.name_display, mode=mode[1]))
            if not update:
                self.remove(settings)
            else:
                if not fast_mode and Output.prompt_confirm(
                        'Do you want to try to re-install ?', default=True):
                    return self.__reinstall(settings, fast_mode)
            return False
コード例 #6
0
    def __check_pre_install(self, settings, fast_mode=False):
        """
        Perform some checks before trying to install the tool (already installed ?,
        install command ?).

        :param Settings settings: Settings from config files
        :param bool fast_mode: Set to true to disable prompts
        :return: Result of checks
        :rtype: bool
        """
        if self.installed:
            logger.info('{tool} is already installed (according to settings), ' \
                'skipped'.format(tool=self.name))
            return False

        elif not self.install_command:
            logger.warning('The tool {tool} has no installation command specified in ' \
                'config file'.format(tool=self.name))

            if fast_mode \
               or Output.prompt_confirm('Is the tool already installed on your system ?',
                                        default=True):

                try:
                    if settings.change_installed_status(self.target_service, 
                                                        self.name, 
                                                        True):

                        logger.success('Tool {tool} has been marked as installed in ' \
                            'settings'.format(tool=self.name))
                        return True
                    else:
                        logger.error('Error when saving the configuration file ' \
                            '"{filename}{ext}"'.format(
                                filename=INSTALL_STATUS_CONF_FILE, ext=CONF_EXT))
                        return False

                except SettingsException as e:
                    logger.error(e)
                    self.remove(settings)
                    return False
            else:
                logger.info('Tool {tool} is still not marked as installed in ' \
                    'settings'.format(tool=self.name))
            return False

        return True
コード例 #7
0
    def __run_check_command(self):
        """
        Run the check command. The goal is to quickly check if the tool is not buggy or
        missing some dependencies
        :return: Boolean indicating if tool is correctly installed
        """
        logger.info('Running the check command for the tool {tool}...'.format(
            tool=self.name_display))
        cmd = self.check_command.get_cmdline(self.tool_dir)

        Output.begin_cmd(cmd)
        ProcessLauncher(cmd).start()
        Output.delimiter()

        return Output.prompt_confirm(
            'Does the tool {tool} seem to be running correctly ?'.format(
                tool=self.name_display),
            default=True)
コード例 #8
0
    def __check_pre_install(self, settings, fast_mode):
        """
        Checks to run before installing the tool
        :param settings: Settings instance
        :param fast_mode: Boolean indicating whether prompts must be displayed or not
        :return: Boolean indicating status
        """
        if self.installed:
            logger.info(
                '{tool} is already installed (according to settings), skipped'.
                format(tool=self.name_display))
            return False

        elif not self.install_command:
            logger.warning(
                'The tool {tool} has no installation command specified in config file'
                .format(tool=self.name_display))
            if fast_mode or Output.prompt_confirm(
                    'Is the tool already installed on your system ?',
                    default=True):
                try:
                    if settings.change_installed_status(
                            self.target_service, self.name_clean, True):
                        logger.success(
                            'Tool {tool} has been marked as installed in settings'
                            .format(tool=self.name_display))
                        return True
                    else:
                        logger.error(
                            'Error when saving the configuration file "{filename}{ext}"'
                            .format(filename=INSTALL_STATUS_CONF_FILE,
                                    ext=CONF_EXT))
                        return False
                except SettingsException as e:
                    logger.error(e)
                    self.remove(settings)
                    return False
            else:
                logger.info(
                    'Tool {tool} is still not marked as installed in settings'.
                    format(tool=self.name_display))
            return False

        return True
コード例 #9
0
    def __init__(self):

        try:
            print(BANNER)
            # Parse settings files
            settings = Settings()

            # Parse command-line arguments
            arguments = ArgumentsParser(settings)

            # Create db if needed and initialize sqlalchemy session
            Base.metadata.create_all(engine)
            session = Session()

            # Create "default" mission if necessary
            mission = session.query(Mission).filter(
                Mission.name == 'default').first()
            if not mission:
                mission = Mission(name='default', comment='Default scope')
                session.add(mission)
                session.commit()

            # Controller
            controller = MainController(arguments, settings, session)
            controller.run()

        except KeyboardInterrupt:
            print()
            if Output.prompt_confirm('Are you sure you want to exit ?',
                                     default=False):
                logger.error('User aborted')
                sys.exit(0)
        except (SettingsException, AttackException) as e:
            logger.error(e)
            sys.exit(1)
        except (ValueError, ArgumentsException):
            print
            sys.exit(1)
        except Exception as e:
            print
            logger.error('Unexpected error occured: {0}'.format(str(e)))
            traceback.print_exc()
            sys.exit(1)
コード例 #10
0
    def __run_check_command(self):
        """
        Run the check command.
        The goal is to quickly check if the tool is not buggy or missing some 
        dependencies. The user must analyze the output and gives an answer.

        :return: Response from user
        :rtype: bool
        """
        logger.info('Running the check command for the tool {tool}...'.format(
            tool=self.name))

        cmd = self.check_command.get_cmdline(self.tool_dir)

        Output.begin_cmd(cmd)
        ProcessLauncher(cmd).start()
        Output.delimiter()

        return Output.prompt_confirm('Does the tool {tool} seem to be running ' \
            'correctly ?'.format(tool=self.name), default=True) 
コード例 #11
0
ファイル: Tool.py プロジェクト: 5l1v3r1/jok3r-1
    def run_check_command(self, fast_mode=False):
        """
        Run the check command.
        The goal is to quickly check if the tool is not buggy or missing some 
        dependencies. The user must analyze the output and gives an answer.

        :param bool fast_mode: Set to true to disable prompts

        :return: Response from user in interactive mode, otherwise status
            based on exit code (True if exit code is 0)
        :rtype: bool
        """
        if not self.check_command:
            logger.info('No check_command defined in settings for the tool ' \
                '{tool}'.format(tool=self.name))
            return True

        logger.info('Running the check command for the tool {tool}...'.format(
            tool=self.name))

        cmd = self.check_command.get_cmdline(self)

        Output.begin_cmd(cmd)
        returncode, _ = ProcessLauncher(cmd).start()
        Output.delimiter()

        if returncode != 0:
            logger.warning('Check command has finished with an error ' \
                'exit code: {code}'.format(code=returncode))
        else:
            logger.success('Check command has finished with success exit code')

        if fast_mode:
            return (returncode == 0)
        else:
            return Output.prompt_confirm('Does the tool {tool} seem to be running ' \
                'correctly ?'.format(tool=self.name), default=True)
コード例 #12
0
    def run(self):

        # Create report directory
        dirname = '{mission}-{datetime}'.format(
            mission=StringUtils.clean(self.mission.replace(' ', '_'),
                                      allowed_specials=('_', '-')),
            datetime=datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
        self.output_path = self.output_path + '/' + dirname

        if not FileUtils.create_directory(self.output_path):
            logger.error('Unable to create report directory: "{path}"'.format(
                path=self.output_path))
            return False

        # Retrieve all services in selected mission
        req = ServicesRequester(self.sqlsession)
        req.select_mission(self.mission)
        services = req.get_results()

        # Generate screenshots
        processor = ScreenshotsProcessor(self.mission, self.sqlsession)
        processor.run()

        screens_dir = self.output_path + '/screenshots'
        if not FileUtils.create_directory(screens_dir):
            logger.warning(
                'Unable to create screenshots directory: "{path}"'.format(
                    path=screens_dir))
        else:
            for service in services:
                if service.name == 'http' and service.screenshot is not None \
                        and service.screenshot.status == ScreenStatus.OK:

                    img_name = 'scren-{ip}-{port}-{id}'.format(
                        ip=str(service.host.ip),
                        port=service.port,
                        id=service.id)
                    path = screens_dir + '/' + img_name

                    ImageUtils.save_image(service.screenshot.image,
                                          path + '.png')
                    ImageUtils.save_image(service.screenshot.thumbnail,
                                          path + '.thumb.png')

        # Create index.html
        html = self.__generate_index()
        if FileUtils.write(self.output_path + '/index.html', html):
            logger.info('index.html file generated')
        else:
            logger.error('An error occured while generating index.html')
            return False

        # Create results-<service>.html (1 for each service)
        for service in services:
            # Useless to create page when no check has been run for the service
            if len(service.results) == 0:
                continue

            html = self.__generate_results_page(service)
            # Create a unique name for the service HTML file
            filename = 'results-{ip}-{port}-{service}-{id}.html'.format(
                ip=str(service.host.ip),
                port=service.port,
                service=service.name,
                id=service.id)
            if FileUtils.write(self.output_path + '/' + filename, html):
                logger.info(
                    '{filename} file generated'.format(filename=filename))
            else:
                logger.error(
                    'An error occured while generating {filename}'.format(
                        filename=filename))
                return False

        logger.success('HTML Report written with success in: {path}'.format(
            path=self.output_path))
        logger.info('Important: If running from Docker container, make sure to run ' \
            '"xhost +" on the host before')
        if Output.prompt_confirm('Would you like to open the report now ?',
                                 default=True):
            webbrowser.open(self.output_path + '/index.html')

        return True
コード例 #13
0
ファイル: AttackScope.py プロジェクト: 5l1v3r1/jok3r-1
    def attack(self):
        """Run the attack against all targets in the scope"""

        # Initialize top status/progress bar
        # If single target (total=None), the counter format will be used instead of 
        # the progress bar format
        attack_progress = manager.counter(
            total=len(self.targets)+1 if len(self.targets) > 1 else None, 
            desc='', 
            unit='target',
            bar_format=STATUSBAR_FORMAT, # For multi targets
            counter_format=STATUSBAR_FORMAT_SINGLE) # For single target

        time.sleep(.5) # hack for progress bar display

        # Loop over the targets
        for i in range(1,len(self.targets)+1):

            # Display table with targets
            self.show_summary()

            # Prompt for target selection
            if not self.fast_mode:
                if len(self.targets) == 1:
                    if Output.prompt_confirm('Start attack ?', default=True):
                        self.current_targetid = 1
                    else:
                        logger.warning('Attack canceled !')
                        sys.exit(1)

                else:
                    self.current_targetid = Output.prompt_choice_range(
                        'Attack target # (Ctrl+C to quit) ? [{default}] '.format(
                            default=self.current_targetid), 
                        1, len(self.targets), self.current_targetid)

            target = self.targets[self.current_targetid-1]

            # Update status/progress bar
            status = 'Current target [{cur}/{total}]: {target}'.format(
                    cur    = i,
                    total  = len(self.targets),
                    target = target)

            attack_progress.desc = '{status}{fill}'.format(
                status = status,
                fill   = ' '*(DESC_LENGTH-len(status)))
            attack_progress.update()
            print()

            # Check the selected target and update its information
            # This is done for targets loaded from the database in multi-targets mode
            # (For single target, done before adding it to a mission in AttackController)
            #
            # - Reverse DNS lookup: not by default (should have already been done)
            # - Port check: always (target might not been reachable anymore)
            # - Nmap service detection: not by default (should have already been done)
            # - HTML title grabbing: always
            # - Web technologies detection: always
            # - Context initialization via SmartStart: always
            if len(self.targets) > 1:
                reachable = target.smart_check(
                    reverse_dns_lookup=(self.arguments.args.reverse_dns == 'on'), 
                    availability_check=True, 
                    nmap_banner_grabbing=(self.arguments.args.nmap_banner_grab == 'on'),
                    html_title_grabbing=True,
                    web_technos_detection=True,
                    smart_context_initialize=True)

                # Update info into database if needed
                self.services_requester.add_target(target)

                # Display availability status, skip if not reachable
                if target.service.name == 'http':
                    msg = 'Target URL {url} is {neg}reachable'.format(
                        url=target.get_url(),
                        neg='not ' if not reachable else '')
                else:
                    msg = 'Target {neg}reachable: {target}'.format(
                        neg='not ' if not reachable else '',
                        target=target)

                if reachable:
                    logger.success(msg)
                else: 
                    logger.error(msg)
                    self.__next_target()
                    continue

            # Launch the attack on the selected target
            self.__attack_target(target, attack_progress)

            # Move to next target
            self.__next_target()


        # Clear progress bars
        attack_progress.update()
        time.sleep(.5)

        attack_progress.close()
        manager.stop() 
    def do_services(self, args):
        """Services in the current mission scope"""
        print()
        req = ServicesRequester(self.sqlsess)
        req.select_mission(self.current_mission)

        # Logical AND is applied between all specified filtering options
        filter_ = Filter(FilterOperator.AND)
        if args.names:
            for n in args.names:
                if not self.settings.services.is_service_supported(n, multi=False):
                    logger.error('Service {name} is not valid/supported'.format(name=n.lower()))
                    return
            filter_.add_condition(Condition(args.names, FilterData.SERVICE_EXACT))

        if args.order:
            req.order_by(args.order)

        if args.hostname:
            # OR between submitted hostnames
            filter_.add_condition(Condition(args.hostname.split(','), FilterData.HOST))
        if args.ip:
            # OR between submitted ips/ranges
            filter_.add_condition(Condition(args.ip.split(','), FilterData.IP))
        if args.port:
            # OR between ports/port-ranges
            filter_.add_condition(Condition(args.port.split(','), FilterData.PORT))
        if args.proto:
            filter_.add_condition(Condition(args.proto, FilterData.PROTOCOL))
        if args.up:
            filter_.add_condition(Condition(args.up, FilterData.UP))
        if args.search:
            filter_search = Filter(FilterOperator.OR)
            filter_search.add_condition(Condition(args.search, FilterData.HOST))
            filter_search.add_condition(Condition(args.search, FilterData.BANNER))
            filter_search.add_condition(Condition(args.search, FilterData.URL))
            filter_search.add_condition(Condition(args.search, FilterData.COMMENT_SERVICE))
            filter_.add_condition(filter_search)

        try:
            req.add_filter(filter_)
        except FilterException as e:
            logger.error(e)
            return

        # Operations
        if args.add:
            host, port, service = args.add
            if NetUtils.is_valid_ip(host):
                ip = host
                hostname = NetUtils.reverse_dns_lookup(ip) 
                logger.info('Reverse DNS lookup on IP {ip}: {hostname}'.format(ip=ip, hostname=hostname))
            else:
                ip = NetUtils.dns_lookup(host)
                if not ip:
                    logger.error('Cannot resolve hostname')
                    return
                hostname = host
                logger.info('DNS lookup on {hostname}: IP {ip}'.format(hostname=host, ip=ip))

            if not NetUtils.is_valid_port(port):
                logger.error('Port is invalid, not in range [0-65535]')
            elif not self.settings.services.is_service_supported(service, multi=False):
                logger.error('Service {name} is not valid/supported'.format(name=service.lower()))
            else:
                req.add_service(ip, hostname, port, self.settings.services.get_protocol(service), service)
        elif args.url:
            args.url = WebUtils.add_prefix_http(args.url)
            if not WebUtils.is_valid_url(args.url):
                logger.error('URL is invalid')
            else:
                req.add_url(args.url)
        elif args.delete:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to delete ALL services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.delete()
        elif args.comment:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to edit comment for ALL services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.edit_comment(args.comment)
        elif args.https:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to apply switch for ALL URLs in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.switch_https()         
        elif args.addcred:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to add same creds for ALL services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.add_cred(args.addcred[0], args.addcred[1], None) 
        elif args.addcred_http:
            if not req.are_only_http_services_selected():
                logger.warning('Some non-HTTP services are selected. Use --addcred instead for non-HTTP services')
                return
            if not self.settings.services.is_valid_authentication_type(args.addcred_http[2]):
                logger.warning('Invalid HTTP authentication type')
                logger.info('List of supported authentication types: ')
                for auth_type in self.settings.services.get_authentication_types('http'):
                    logger.info('- {type}'.format(type=auth_type))
                return
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to add same creds for ALL HTTP services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.add_cred(args.addcred_http[0], args.addcred_http[1], args.addcred_http[2]) 
        elif args.adduser:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to add same username for ALL services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.add_cred(args.adduser[0], None, None)
        elif args.adduser_http:
            if not req.are_only_http_services_selected():
                logger.warning('Some non-HTTP services are selected. Use --adduser instead for non-HTTP services')
                return
            if not self.settings.services.is_valid_authentication_type(args.adduser_http[1]):
                logger.warning('Invalid HTTP authentication type')
                logger.info('List of supported authentication types: ')
                for auth_type in self.settings.services.get_authentication_types('http'):
                    logger.info('- {type}'.format(type=auth_type))
                return
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to add same username for ALL HTTP services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.add_cred(args.adduser_http[0], None, args.adduser_http[1]) 
        else:
            req.show()                      

        print()
コード例 #15
0
    def __check_post_install_update(self, settings, fast_mode=False, update=False):
        """
        Perform some operation after install/update:
            - Check if correctly installed by running "check_command" and prompting,
            - Update install status in configuration file.

        :param Settings settings: Settings from config files
        :param bool fast_mode: Set to true to disable prompts
        :param update: Mode selector, True for update | False for install (default)
        :return: Status of operations
        :rtype: bool
        """
        mode = ('update','updated') if update else ('install','installed')
        status = True

        # Check install/update
        if not fast_mode:
            if not self.check_command:
                logger.info('No check_command defined in settings for {tool}, will ' \
                    'assume it is correctly {mode}'.format(tool=self.name, mode=mode[1]))
            else:
                logger.info('Now, checking if {tool} has been {mode} correctly. ' \
                    'Hit any key to run test...'.format(tool=self.name, mode=mode[1]))
                CLIUtils.getch()
                status = self.__run_check_command()

        # Change install status in configuration file
        if status:
            try:

                if settings.change_installed_status(self.target_service, 
                                                    self.name, 
                                                    install_status=True):

                    logger.success('Tool {tool} has been marked as successfully ' \
                        '{mode}'.format(tool=self.name, mode=mode[1]))
                    return True
                else:
                    logger.error('Error when updating configuration file ' \
                        '"{filename}{ext}"'.format(
                            filename=INSTALL_STATUS_CONF_FILE, ext=CONF_EXT))
                    return False

            except SettingsException as e:
                logger.error('An unexpected error occured when trying to mark the '\
                    'tool as {mode}: {exc}'.format(mode=mode[1], exc=e))

                if not update:
                    self.remove(settings)
                return False
        else:
            logger.warning('Tool {tool} has not been marked as {mode}'.format(
                tool=self.name, mode=mode[1]))
            if not update:
                self.remove(settings)
            else:
                if not fast_mode \
                   and Output.prompt_confirm('Do you want to try to re-install ?', 
                                             default=True):

                    return self.__reinstall(settings, fast_mode)

            return False
    def do_creds(self, args):
        """Credentials in the current mission scope"""
        print()
        req = CredentialsRequester(self.sqlsess)
        req.select_mission(self.current_mission)

        # Logical AND is applied between all specified filtering options
        filter_ = Filter(FilterOperator.AND)
        if args.username:
            filter_.add_condition(Condition(args.username, FilterData.USERNAME))
        if args.password:
            filter_.add_condition(Condition(args.password, FilterData.PASSWORD))
        if args.both:
            filter_.add_condition(Condition(args.both, FilterData.USER_AND_PASS))
        elif args.onlyuser:
            filter_.add_condition(Condition(args.onlyuser, FilterData.ONLY_USER))
        if args.hostname:
            # OR between submitted hostnames
            filter_.add_condition(Condition(args.hostname.split(','), FilterData.HOST))
        if args.ip:
            # OR between submitted ips/ranges
            filter_.add_condition(Condition(args.ip.split(','), FilterData.IP))
        if args.port:
            # OR between ports/port-ranges
            filter_.add_condition(Condition(args.port.split(','), FilterData.PORT))
        if args.service:
            for s in args.service.split(','):
                if not self.settings.services.is_service_supported(s, multi=False):
                    logger.error('Service {name} is not valid/supported'.format(name=s.lower()))
                    return
            filter_.add_condition(Condition(args.service.split(','), FilterData.SERVICE_EXACT))
        if args.order:
            req.order_by(args.order)
        if args.search:
            filter_search = Filter(FilterOperator.OR)
            filter_search.add_condition(Condition(args.search, FilterData.HOST))
            filter_search.add_condition(Condition(args.search, FilterData.AUTH_TYPE))
            filter_search.add_condition(Condition(args.search, FilterData.USERNAME))
            filter_search.add_condition(Condition(args.search, FilterData.PASSWORD))
            filter_search.add_condition(Condition(args.search, FilterData.URL))
            filter_search.add_condition(Condition(args.search, FilterData.COMMENT_CRED))
            filter_.add_condition(filter_search)
        try:
            req.add_filter(filter_)
        except FilterException as e:
            logger.error(e)
            return

        # Operations
        add = args.addcred or args.addcred_http or args.adduser or args.adduser_http
        if add:
            try:
                service_id = int(add[0])
            except:
                logger.error('Invalid service id')
                return

            if args.addcred:
                req.add_cred(service_id, args.add[1], args.add[2], None)
            elif args.addcred_http:
                if not self.settings.services.is_valid_authentication_type(args.addcred_http[3]):
                    logger.warning('Invalid HTTP authentication type')
                    logger.info('List of supported authentication types: ')
                    for auth_type in self.settings.services.get_authentication_types('http'):
                        logger.info('- {type}'.format(type=auth_type))
                    return
                req.add_cred(service_id, args.addcred_http[1], args.addcred_http[2], args.addcred_http[3])
            elif args.adduser:
                req.add_cred(service_id, args.add[1], None, None)
            elif args.adduser_http:
                if not self.settings.services.is_valid_authentication_type(args.adduser_http[2]):
                    logger.warning('Invalid HTTP authentication type')
                    logger.info('List of supported authentication types: ')
                    for auth_type in self.settings.services.get_authentication_types('http'):
                        logger.info('- {type}'.format(type=auth_type))
                    return
                req.add_cred(service_id, args.adduser_http[1], None, args.adduser_http[2])
        elif args.comment:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to edit comment for ALL creds in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.edit_comment(args.comment)
        elif args.delete:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to delete ALL creds in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.delete()
        else:
            if not args.order:
                req.order_by('ip')
            req.show()

        print()
コード例 #17
0
    def attack(self):
        """Run the attack against all targets in the scope"""

        # Initialize top status/progress bar
        # If single target (total=None), the counter format will be used instead of
        # the progress bar format
        attack_progress = manager.counter(
            total=len(self.targets) + 1 if len(self.targets) > 1 else None,
            desc='',
            unit='target',
            bar_format=STATUSBAR_FORMAT,  # For multi targets
            counter_format=STATUSBAR_FORMAT_SINGLE)  # For single target

        time.sleep(.5)  # hack for progress bar display

        # Loop over the targets
        for i in range(1, len(self.targets) + 1):

            # In Multi-targets mode:
            # Display summary table and prompt for target selection
            # (not if too many target to avoid poor output)
            if 2 <= len(self.targets) <= 15:
                self.show_summary()

            if not self.fast_mode and len(self.targets) > 1:
                self.current_targetid = Output.prompt_choice_range(
                    'Attack target # (Ctrl+C to quit) ? [{default}] '.format(
                        default=self.current_targetid), 1, len(self.targets),
                    self.current_targetid)

            target = self.targets[self.current_targetid - 1]

            # Update status/progress bar
            status = 'Current target [{cur}/{total}]: {target}'.format(
                cur=i, total=len(self.targets), target=target)

            attack_progress.desc = '{status}{fill}'.format(
                status=status, fill=' ' * (DESC_LENGTH - len(status)))
            attack_progress.update()
            print()

            # Check the current target
            # For single target mode: already done in AttackController
            if len(self.targets) > 1:
                # By default, do NOT perform reverve DNS lookup & Nmap banner grabbing
                # because we assume it has been added via Nmap results in most cases
                # and thus, has already been done (behaviour can be changed with opt)
                reachable = target.smart_check(
                    reverse_dns=(self.arguments.args.reverse_dns == 'on'),
                    availability_check=True,
                    grab_banner_nmap=(
                        self.arguments.args.nmap_banner_grab == 'on'),
                    web_technos_detection=False)

                if target.service.name == 'http':
                    msg = 'Target URL {url} is {neg}reachable'.format(
                        url=target.get_url(),
                        neg='not ' if not reachable else '')
                else:
                    msg = 'Target {neg}reachable: {target}'.format(
                        neg='not ' if not reachable else '', target=target)

                # Update info into database if needed
                self.services_requester.add_target(target)

                if reachable:
                    #target.service.up = True
                    logger.success(msg)
                else:
                    # Skip target if not reachable
                    logger.error(msg)
                    continue

            # In Single-target mode: Display summary table and prompt for confirmation
            if len(self.targets) == 1:
                self.show_summary()

                if not self.fast_mode:
                    if Output.prompt_confirm('Start attack ?', default=True):
                        self.current_targetid = 1
                    else:
                        logger.warning('Attack canceled !')
                        sys.exit(1)

            # Launch the attack on the selected target
            self.__attack_target(target, attack_progress)
            self.current_targetid += 1
            self.current_targetid = self.current_targetid % len(self.targets)

        attack_progress.update()
        time.sleep(.5)

        attack_progress.close()
        manager.stop()  # Clear progress bars