def show(self, highlight=None): """ Display selected missions. :param str highlight: Name of the mission to highlight """ results = self.get_results() if not results: logger.warning('No matching mission') else: data = list() columns = [ 'Mission', 'Creation date', 'Comment', '# Hosts', '# Services', ] for mission in results: color = 'light_green' if mission.name == highlight else None data.append([ Output.colored(mission.name, color=color), Output.colored(str(mission.creation_date), color=color), Output.colored(StringUtils.wrap(mission.comment, 50), color=color), Output.colored(len(mission.hosts), color=color), Output.colored(mission.get_nb_services(), color=color), ]) Output.table(columns, data, hrules=False)
def show(self): """Display selected services""" results = self.get_results() if not results: logger.warning('No service to display') else: data = list() columns = [ 'id', 'IP', #'Hostname', 'Port', 'Proto', 'Service', 'Banner', 'URL', 'Comment/Title', 'Checks', 'Creds', 'Vulns', ] for r in results: # Creds numbers nb_userpass = r.get_nb_credentials(single_username=False) nb_usernames = r.get_nb_credentials(single_username=True) nb_creds = '{}{}{}'.format( '{}'.format(Output.colored(str(nb_userpass), color='green' \ if nb_userpass > 0 else None)) if nb_userpass > 0 else '', '/' if nb_userpass > 0 and nb_usernames > 0 else '', '{} usr'.format(Output.colored(str(nb_usernames), color='yellow' \ if nb_usernames > 0 else None)) if nb_usernames > 0 else '') nb_vulns = Output.colored(str(len(r.vulns)), color='green' \ if len(r.vulns) > 0 else None) if len(r.vulns) > 0 else '' # Col "Comment/Title" (title is for HTML title for HTTP) if r.html_title: comment = r.html_title else: comment = r.comment data.append([ r.id, r.host.ip, #r.host.hostname, r.port, { Protocol.TCP: 'tcp', Protocol.UDP: 'udp' }.get(r.protocol), r.name, StringUtils.wrap(r.banner, 55), StringUtils.wrap(r.url, 50), StringUtils.shorten(comment, 40), len(r.results), nb_creds, nb_vulns, ]) Output.table(columns, data, hrules=False)
def change_current_mission(self, name, verbose=False): mission = self.sqlsess.query(Mission).filter(Mission.name == name).first() if not mission: logger.error('No mission with this name') else: self.current_mission = name self.prompt = Output.colored('jok3rdb', color='light_green', attrs='bold') + \ Output.colored('[{mission}]'.format(mission=name), color='light_blue', attrs='bold') + \ Output.colored('> ', color='light_green', attrs='bold') if verbose: logger.info('Selected mission is now {name}'.format(name=name))
def show(self, filter_service=None): """ Display information about supported attack profiles :param str filter_service: Service name to filter with (default: no filter) """ data = list() columns = [ 'Profile', 'Description', ] for p in self.profiles: #print(p.checks) if not filter_service or p.is_service_supported(filter_service): data.append([ Output.colored(p.name, attrs='bold'), StringUtils.wrap(p.description, 120) ]) if filter_service: service = 'for service {}'.format(filter_service.upper()) else: service = '' Output.title1('Attack Profiles {service}'.format(service=service)) Output.table(columns, data, hrules=False) if not filter_service: print Output.print('Run "info --attack-profiles <service>" to see the attack ' \ 'profiles supported for a given service.')
def info(self): """ Modes mode Info """ self.mode = Mode.INFO parser = self.__create_subcmd_parser() info = parser.add_argument_group(Output.colored('Info', attrs='bold')) info_mxg = info.add_mutually_exclusive_group() info_mxg.add_argument('--services', help='List supported services', action='store_true', dest='show_services', default=False) info_mxg.add_argument('--options', help='List supported context-specific options', action='store_true', dest='show_specific_options', default=False) info_mxg.add_argument( '--http-auth-types', help='List the supported HTTP authentication types', action='store_true', dest='show_http_auth_types', default=False) info_mxg.add_argument('--checks', help='List all the checks for the given service', action='store', dest='show_checks', metavar='<service>', default=None) self.subparser = parser self.args = parser.parse_args(sys.argv[2:])
def show(self): results = self.get_results() if not results: logger.warning('No service to display') else: data = list() columns = [ 'id', 'IP', #'Hostname', 'Port', 'Proto', 'Service', 'Banner', 'URL', 'Comment', 'Checks', 'Creds', ] for r in results: nb_userpass = r.get_nb_credentials(single_username=False) nb_usernames = r.get_nb_credentials(single_username=True) nb_creds = '{}{}{}'.format( '{}'.format(Output.colored(str(nb_userpass), color='green' \ if nb_userpass > 0 else None)) if nb_userpass > 0 else '', '/' if nb_userpass > 0 and nb_usernames > 0 else '', '{} users'.format(Output.colored(str(nb_usernames), color='yellow' \ if nb_usernames > 0 else None)) if nb_usernames > 0 else '') data.append([ r.id, r.host.ip, #r.host.hostname, r.port, { Protocol.TCP: 'tcp', Protocol.UDP: 'udp' }.get(r.protocol), r.name, StringUtils.wrap(r.banner, 65), StringUtils.wrap(r.url, 50), StringUtils.wrap(r.comment, 50), len(r.results), nb_creds, ]) Output.table(columns, data, hrules=False)
def show(self): """Display selected credentials""" results = self.get_results() if not results: logger.warning('No credential to display') else: data = list() columns = [ 'IP', 'Hostname', 'Service', 'Port', 'Proto', 'Type', 'Username', 'Password', 'URL', 'Comment', ] for r in results: username = '******' if r.username == '' else r.username username = Output.colored(username, color='green' if \ r.password is not None else 'yellow') password = { '': '<empty>', None: '<???>' }.get(r.password, r.password) password = Output.colored(password, color='green' if \ r.password is not None else 'yellow') data.append([ r.service.host.ip, r.service.host.hostname \ if r.service.host.hostname != str(r.service.host.ip) else '', r.service.name, r.service.port, {Protocol.TCP: 'tcp', Protocol.UDP: 'udp'}.get(r.service.protocol), r.type or '', username, password, StringUtils.wrap(r.service.url, 50), StringUtils.wrap(r.comment, 50), ]) Output.table(columns, data, hrules=False)
def show_toolbox(self, filter_service=None): """ Display a table showing the content of the toolbox. :param str filter_service: Service name to filter with (default: no filter) """ if filter_service is not None and filter_service not in self.services: return data = list() columns = [ 'Name', 'Service', 'Status/Update', 'Description', ] services = self.services if filter_service is None else [ filter_service ] for service in services: for tool in self.tools[service]: # Install status style if tool.installed: status = Output.colored('OK | ' + tool.last_update.split(' ')[0], color='green') else: status = Output.colored('Not installed', color='red') # Add line for the tool data.append([ tool.name, tool.target_service, status, StringUtils.wrap(tool.description, 120), # Max line length ]) Output.title1('Toolbox content - {filter}'.format( filter='all services' if filter_service is None \ else 'service ' + filter_service)) Output.table(columns, data, hrules=False)
def show_summary(self): """ """ data = list() columns = [ 'id', 'IP', 'Hostname', 'Port', 'Proto', 'Service', 'Banner', 'URL', ] id_ = 1 for target in self.targets: pointer_color = 'blue' if self.current_targetid == id_ else None pointer_attr = 'bold' if self.current_targetid == id_ else None data.append([ Output.colored( '>' + str(id_) if self.current_targetid == id_ else str(id_), color=pointer_color, attrs=pointer_attr), Output.colored(target.get_ip(), color=pointer_color, attrs=pointer_attr), Output.colored(target.get_host(), color=pointer_color, attrs=pointer_attr), Output.colored(str(target.get_port()), color=pointer_color, attrs=pointer_attr), Output.colored(target.get_protocol(), color=pointer_color, attrs=pointer_attr), Output.colored(target.get_service_name(), color=pointer_color, attrs=pointer_attr), Output.colored(StringUtils.wrap(target.get_banner(), 70), color=pointer_color, attrs=pointer_attr), Output.colored(StringUtils.wrap(target.get_url(), 50), color=pointer_color, attrs=pointer_attr), ]) id_ += 1 Output.table(columns, data, hrules=False)
def show(self): """Display a table with all the checks for the service.""" data = list() columns = [ 'Name', 'Category', 'Description', 'Tool used', #'# Commands', ] for category in self.categories: for check in self.checks[category]: color_tool = 'grey_19' if not check.tool.installed else None data.append([ check.name, category, check.description, Output.colored(check.tool.name, color=color_tool), #len(check.commands), ]) Output.title1('Checks for service {service}'.format(service=self.service)) Output.table(columns, data, hrules=False)
def toolbox(self): """Arguments for subcommand Toolbox""" self.mode = Mode.TOOLBOX parser = self.__create_subcmd_parser() toolbox = parser.add_argument_group( Output.colored('Toolbox management', attrs='bold'), 'The Toolbox contains all the tools used by Jok3r for running the security' \ ' checks.\nThey are classified by the services they target.') toolbox_mxg = toolbox.add_mutually_exclusive_group() toolbox_mxg.add_argument( '--show', help='Show toolbox content for a given service', action='store', dest='show_toolbox_for_svc', metavar='<service>', default=None) toolbox_mxg.add_argument('--show-all', help='Show full toolbox content', action='store_true', dest='show_toolbox_all', default=False) toolbox_mxg.add_argument( '--install', help='Install the tools targeting a given service', action='store', dest='install_for_svc', metavar='<service>', default=None) toolbox_mxg.add_argument('--install-tool', help='Install a given tool', action='store', dest='install_tool', metavar='<tool-name>', default=None) toolbox_mxg.add_argument('--install-all', help='Install all the tools in the toolbox', action='store_true', dest='install_all', default=False) toolbox_mxg.add_argument( '--update', help='Update the installed tools targeting a given service', action='store', dest='update_for_svc', metavar='<service>', default=None) toolbox_mxg.add_argument('--update-tool', help='Update a given tool', action='store', dest='update_tool', metavar='<tool-name>', default=None) toolbox_mxg.add_argument( '--update-all', help='Update all installed tools in the toolbox', action='store_true', dest='update_all', default=False) toolbox_mxg.add_argument( '--uninstall', help='Uninstall the tools targeting a given service', action='store', dest='uninstall_for_svc', metavar='<service>', default=None) toolbox_mxg.add_argument('--uninstall-tool', help='Uninstall a given tool', action='store', dest='uninstall_tool', metavar='<tool-name>', default=None) toolbox_mxg.add_argument('--uninstall-all', help='Uninstall all tools in the toolbox', action='store_true', dest='uninstall_all', default=False) parameter = parser.add_argument_group( Output.colored('Parameter', attrs='bold')) parameter.add_argument( '--auto', help = 'Automatic mode. Disable manual post-install checks, rely only ' \ 'on exit code instead', action = 'store_true', dest = 'fast_mode', default = False) check = parser.add_argument_group(Output.colored('Check', attrs='bold')) check.add_argument( '--check', help = 'Check all installed tools automatically. Return exit code 1 ' \ 'for any problem', action = 'store_true', dest = 'check_toolbox', default = False) self.subparser = parser # Inside Mode, so ignore the first TWO argvs self.args = parser.parse_args(sys.argv[2:])
def attack(self): """Arguments for subcommand Attack""" self.mode = Mode.ATTACK parser = self.__create_subcmd_parser() singletarget = parser.add_argument_group( Output.colored('Mode: Single target', attrs='bold'), 'Run security checks against one target.') singletarget.add_argument( '-t', '--target', help='Target IP[:PORT] (default port if not specified) or URL', action='store', dest='target_ip_or_url', metavar='<ip[:port] | url>', default=None) singletarget.add_argument('-s', '--service', help='Target service', action='store', dest='service', metavar='<service>', default=None) singletarget.add_argument( '--add2db', help= 'Add/update the target into a given mission scope in the database (default: mission "default")', action='store', dest='add', metavar='<mission>', default='default') multitargets = parser.add_argument_group( Output.colored('Mode: Multiple targets from a mission scope', attrs='bold'), 'Select targets from the scope of an existing mission.') multitargets.add_argument( '-m', '--mission', help='Load targets from the specified mission', action='store', dest='mission', metavar='<mission>', default=None) multitargets.add_argument( '-f', '--filter', help = 'Set of conditions to select a subset of targets\n' \ '(e.g "ip=10.1.1.0/24,10.0.0.4;port=80,8000-8100;service=http")\n'\ 'Available filter options: {opt}\n' \ 'Several filters can be used (logical OR) by using the option ' \ 'multiple times'.format(opt=', '.join(TARGET_FILTERS)), action = 'append', dest = 'filter', metavar = '<filter>', default = None) multitargets.add_argument( '--new-only', help= 'Target only services for which no check at all has already been run', action='store_true', dest='unscanned', default=False) init = parser.add_argument_group( Output.colored('Target initialization', attrs='bold')) init.add_argument( '--reverse-dns', help = 'Enable/disable reverse DNS lookup (default: ' \ 'On for single target / Off for multiple)', choices = ['on', 'off'], default = None) init.add_argument( '--nmap-banner-grab', help = 'Enable/disable Nmap banner grabbing (default: ' \ 'On for single target / Off for multiple)', choices = ['on', 'off'], default = None) selection = parser.add_argument_group( Output.colored('Attack configuration', attrs='bold'), 'Select a subset of checks to run, either manually or by using a ' \ 'pre-defined attack profile.') selection_mxg = selection.add_mutually_exclusive_group() selection_mxg.add_argument('--profile', help='Use a pre-defined attack profile', action='store', dest='profile', metavar='<profile>', default=None) selection_mxg.add_argument( '--cat-only', help='Run only checks in specified category(ies) (comma-separated)', action='store', dest='cat_only', metavar='<cat1,cat2...>', default=None) selection_mxg.add_argument( '--cat-exclude', help = 'Run all checks except the ones in specified ' \ 'category(ies) (comma-separated)', action = 'store', dest = 'cat_exclude', metavar = '<cat1,cat2...>', default = None) selection_mxg.add_argument( '--checks', help='Run only the specified check(s) (comma-separated)', action='store', dest='checks', metavar='<check1,check2...>', default=None) running = parser.add_argument_group( Output.colored('Running option', attrs='bold')) running.add_argument( '--fast', help='Fast mode, disable prompts/user interaction', action='store_true', dest='fast_mode', default=False) running.add_argument('--recheck', help='Do not skip checks when already run', action='store_true', dest='recheck', default=False) running.add_argument('-d', help='Enable debug mode', action='store_true', dest='debug', default=False) bruteforce = parser.add_argument_group( Output.colored('Bruteforce options', attrs='bold')) bruteforce.add_argument( '--userlist', help='List of usernames to use (instead of default lists)', action='store', dest='userlist', default=None) bruteforce.add_argument( '--passlist', help='List of passwords to use (instead of default lists)', action='store', dest='passlist', default=None) # bruteforce.add_argument( # '--weblist', # help = 'Wordlist for web content discovery', # action = 'store', # dest = 'weblist', # default = None) context = parser.add_argument_group( Output.colored('Context parameters', attrs='bold'), 'Define manually some known information about the target(s).\n' \ 'Not Recommended: in most cases, you do not have to use these parameters ' \ 'because Jok3r does its best\nto detect the context automatically, based ' \ 'on the results of various checks.') context.add_argument('--cred', help='Credentials (username + password)', action=Store2or3Append, nargs='+', dest='creds', metavar=('[<svc>[.<type>]] <user> <pass>', '')) context.add_argument('--user', help='Single username', action=Store1or2Append, nargs='+', dest='users', metavar=('[<svc>[.<type>]] <user>', '')) context.add_argument('--product', help='Product', action='append', dest='products', metavar='<type=name>', default=None) context.add_argument('--option', help='Specific option', action='append', dest='options', metavar='<name=value>', default=None) parser.epilog = ATTACK_EXAMPLES self.subparser = parser self.args = parser.parse_args(sys.argv[2:])
# -*- coding: utf-8 -*- ### ### Output > StatusBar ### import enlighten import sys import time from lib.output.Output import Output # enlighten module API reference: # https://python-enlighten.readthedocs.io/en/latest/api.html STATUSBAR_FORMAT = Output.colored( '{desc}{desc_pad}|{percentage:3.0f}% |{bar}| [{elapsed}]', color='white', highlight='navy_blue') STATUSBAR_FORMAT_SINGLE = Output.colored('{desc}{desc_pad}{fill}', color='white', highlight='navy_blue') DESC_LENGTH = 81 # By default enlighten does not take into account special chars used for coloration in # the format (by colored module), a dirty hack consists in re-adjusting the terminal # width in manager.width by adding a correct value (24). # It is also necessary to override the method manager._resize_handler which is called # each time the window is resized, in order to make sure the width is corrected HACK_LENGTH = 24 # Subclassing Manager class from
def show_summary(self): """ Display a table showing the summary of the attack scope. The table has a max size defined in lib.core.Config, to avoid displaying an unreadable summary when large amount of targets have been loaded. """ if len(self.targets) > ATTACK_SUMMARY_TABLE_MAX_SIZE: id_min = self.current_targetid-2 if id_min < 1: id_min = 1 id_max = self.current_targetid+ATTACK_SUMMARY_TABLE_MAX_SIZE-1 \ -(self.current_targetid-id_min) if id_max > len(self.targets): id_min = id_min-(id_max-len(self.targets)) id_max = len(self.targets) else: id_min = 1 id_max = len(self.targets) data = list() columns = [ 'id', 'IP', 'Hostname', 'Port', 'Proto', 'Service', 'Banner', 'URL', ] id_ = 1 for target in self.targets: if id_ < id_min: id_ += 1 continue if id_ > id_max: break pointer_color = 'blue' if self.current_targetid == id_ else None pointer_attr = 'bold' if self.current_targetid == id_ else None data.append([ Output.colored('>'+str(id_) if self.current_targetid == id_ \ else str(id_), color=pointer_color, attrs=pointer_attr), Output.colored(target.get_ip(), color=pointer_color, attrs=pointer_attr), Output.colored(StringUtils.wrap(target.get_host(), 50), color=pointer_color, attrs=pointer_attr), Output.colored(str(target.get_port()), color=pointer_color, attrs=pointer_attr), Output.colored(target.get_protocol(), color=pointer_color, attrs=pointer_attr), Output.colored(target.get_service_name(), color=pointer_color, attrs=pointer_attr), Output.colored(StringUtils.wrap(target.get_banner(), 55), color=pointer_color, attrs=pointer_attr), Output.colored(StringUtils.wrap(target.get_url(), 50), color=pointer_color, attrs=pointer_attr), ]) id_ += 1 print() Output.table(columns, data, hrules=False) if len(self.targets) > ATTACK_SUMMARY_TABLE_MAX_SIZE: logger.info('Table has been truncated. Total number of loaded ' \ 'targets: {}'.format(len(self.targets))) print()
def toolbox(self): """ Modes mode Toolbox """ self.mode = Mode.TOOLBOX parser = self.__create_subcmd_parser() toolbox = parser.add_argument_group( Output.colored('Toolbox management', attrs='bold'), 'Tools are classified by services they can target into the toolbox. Tools that may be used ' + 'against various\ndifferent services are grouped under the name "multi".' ) toolbox_mxg = toolbox.add_mutually_exclusive_group() toolbox_mxg.add_argument( '--show', help='Show toolbox content for a given service', action='store', dest='show_toolbox_for_svc', metavar='<service>', default=None) toolbox_mxg.add_argument('--show-all', help='Show full toolbox content', action='store_true', dest='show_toolbox_all', default=False) toolbox_mxg.add_argument('--install', help='Install the tools for a given service', action='store', dest='install_for_svc', metavar='<service>', default=None) toolbox_mxg.add_argument('--install-all', help='Install all the tools in the toolbox', action='store_true', dest='install_all', default=False) toolbox_mxg.add_argument( '--update', help='Update the installed tools for a given service', action='store', dest='update_for_svc', metavar='<service>', default=None) toolbox_mxg.add_argument( '--update-all', help='Update all installed tools in the toolbox', action='store_true', dest='update_all', default=False) toolbox_mxg.add_argument( '--uninstall', help='Uninstall the tools for a given service', action='store', dest='uninstall_for_svc', metavar='<service>', default=None) toolbox_mxg.add_argument('--uninstall-tool', help='Uninstall a given tool', action='store', dest='uninstall_tool', metavar='<tool-name>', default=None) toolbox_mxg.add_argument('--uninstall-all', help='Uninstall all tools in the toolbox', action='store_true', dest='uninstall_all', default=False) toolbox.add_argument( '--fast', help='Fast mode, disable prompts and post-install checks', action='store_true', dest='fast_mode', default=False) self.subparser = parser # Inside Mode, so ignore the first TWO argvs self.args = parser.parse_args(sys.argv[2:])
def attack(self): """ Modes mode Attack """ self.mode = Mode.ATTACK parser = self.__create_subcmd_parser() singletarget = parser.add_argument_group( Output.colored('Single target', attrs='bold'), 'Quickly define a target to run checks against it.') singletarget.add_argument( '-t', '--target', help='Target IP[:PORT] (default port if not specified) or URL', action='store', dest='target_ip_or_url', metavar='<ip[:port] | url>', default=None) singletarget.add_argument('-s', '--service', help='Target service', action='store', dest='service', metavar='<service>', default=None) singletarget.add_argument( '--add', help='Add/update the target into a given mission scope', action='store', dest='add', metavar='<mission>', default=None) singletarget.add_argument( '--disable-banner-grab', help='Disable banner grabbing with Nmap at start', action='store_true', default=False) multitargets = parser.add_argument_group( Output.colored('Multiple targets from a mission scope', attrs='bold'), 'Select targets from the scope of an existing mission.') multitargets.add_argument( '-m', '--mission', help='Load targets from the specified mission', action='store', dest='mission', metavar='<mission>', default=None) multitargets.add_argument( '-f', '--filter', help='Set of conditions to select a subset of targets\n' + '(e.g "ip=192.168.1.0/24,10.0.0.4;port=80,8000-8100;service=http").\n' + 'Available filter options: {opt}\n'.format( opt=', '.join(TARGET_FILTERS)) + 'Several sets can be combined (logical OR) by using the option multiple times', action='append', dest='filter', metavar='<filter>', default=None) selection = parser.add_argument_group( Output.colored('Selection of checks', attrs='bold'), 'Select only some categories/checks to run against the target(s).') selection_mxg = selection.add_mutually_exclusive_group() selection_mxg.add_argument( '--cat-only', help='Run only tools in specified category(ies) (comma-separated)', action='store', dest='cat_only', metavar='<cat1,cat2...>', default=None) selection_mxg.add_argument( '--cat-exclude', help= 'Do not run tools in specified category(ies) (comma-separated)', action='store', dest='cat_exclude', metavar='<cat1,cat2...>', default=None) selection_mxg.add_argument( '--checks', help='Run only the specified check(s) (comma-separated)', action='store', dest='checks', metavar='<check1,check2...>', default=None) running = parser.add_argument_group( Output.colored('Running option', attrs='bold')) running.add_argument('--fast', help='Fast mode, disable prompts', action='store_true', dest='fast_mode', default=False) auth = parser.add_argument_group(Output.colored('Authentication', attrs='bold'), 'Define authentication option if some credentials or single usernames are known.\n' \ 'Options can be used multiple times. For multiple targets, the service for which \n' \ 'the creds/users will be used should be specified.') auth.add_argument('--cred', help='Credentials (username + password)', action=Store2or3Append, nargs='+', dest='creds', metavar=('[<svc>[.<type>]] <user> <pass>', '')) auth.add_argument('--user', help='Single username', action=Store1or2Append, nargs='+', dest='users', metavar=('[<svc>[.<type>]] <user>', '')) specific = parser.add_argument_group( Output.colored('Context-specific options', attrs='bold'), 'Define manually some known info about the target(s).') specific.add_argument( 'specific', help= 'Context-specific options, format name=value (space-separated)', metavar='<opt1=val1 opt2=val2 ...>', nargs='*') self.subparser = parser self.args = parser.parse_args(sys.argv[2:])