def show(self): """Display selected vulnerabilities""" results = self.get_results() if not results: logger.warning('No vulnerability to display') else: data = list() columns = [ 'IP', 'Service', 'Port', 'Proto', 'Vulnerability', ] for r in results: data.append([ r.service.host.ip, r.service.name, r.service.port, { Protocol.TCP: 'tcp', Protocol.UDP: 'udp' }.get(r.service.protocol), StringUtils.wrap(r.name, 140), ]) Output.table(columns, data, hrules=False)
def show(self): """Display selected results""" results = self.get_results() Output.title2('Attacks results:') if not results: logger.warning('No results to display') else: data = list() columns = [ 'IP', 'Port', 'Proto', 'Service', 'Check id', 'Category', 'Check', '# Commands run', ] for r in results: data.append([ r.service.host.ip, r.service.port, { Protocol.TCP: 'tcp', Protocol.UDP: 'udp' }.get(r.service.protocol), r.service.name, r.id, r.category, r.check, len(r.command_outputs), ]) Output.table(columns, data, hrules=False)
def show_products(self, filter_service=None): """ Display supported products in a table :param list filter_service: Filter on services (default: all) """ data = list() columns = [ 'Type', 'Product Names', ] services = self.list_services() if filter_service is None else [ filter_service ] for service in services: products = self.services[service]['products'] for product_type in products: names = sorted( self.services[service]['products'][product_type]) names = StringUtils.wrap(', '.join(names), 100) data.append([product_type, names]) Output.title1('Available products for {filter}'.format( filter='all services' if filter_service is None \ else 'service ' + filter_service)) if not data: logger.warning('No product') else: Output.table(columns, data)
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: 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 '', '<empty>' if r.username == '' else r.username, {'': '<empty>', None: '<???>'}.get(r.password, r.password), StringUtils.wrap(r.service.url, 50), StringUtils.wrap(r.comment, 50), ]) Output.table(columns, data, hrules=False)
def show_categories(self, filter_service=None): """ Show list of categories of checks for the given service or all services :param filter_service: None or given service :return: None """ data = list() columns = [ 'Category', 'Services', ] services = self.list_services() if filter_service is None else [ filter_service ] svcbycat = defaultdict(list) for service in services: for category in self.services[service]['checks'].categories: svcbycat[category].append(service) for category in svcbycat: data.append([ category, StringUtils.wrap(', '.join(svcbycat[category]), 100) ]) Output.table(columns, data)
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 show(self): """Display selected hosts""" results = self.get_results() if not results: logger.warning('No host to display') else: data = list() columns = [ 'IP', 'Hostname', 'OS', 'Type', 'Vendor', 'Comment', 'TCP', 'UDP', ] for r in results: data.append([ r.ip, StringUtils.wrap(r.hostname, 45) if r.hostname != str(r.ip) else '', StringUtils.wrap(r.os, 50), r.type, StringUtils.wrap(r.vendor, 30), StringUtils.shorten(r.comment, 40), r.get_nb_services(Protocol.TCP), r.get_nb_services(Protocol.UDP), ]) Output.table(columns, data, hrules=False)
def show_services(self, toolbox): """ Display supported services in a table. :param Toolbox toolbox: Toolbox """ data = list() columns = [ 'Service', 'Default port', '# Tools', '# Checks', ] for service in self.list_services(multi=True): data.append([ service, 'N/A' if service == 'multi' else '{port}/{proto}'.format( port = self.services[service]['default_port'], proto = self.services[service]['protocol']), '{nb_installed}/{nb_tools}'.format( nb_installed = toolbox.nb_tools(filter_service=service, only_installed=True), nb_tools = toolbox.nb_tools(filter_service=service)), 'N/A' if service == 'multi' \ else self.services[service]['checks'].nb_checks(), ]) Output.title1('Supported services') Output.table(columns, data, hrules=False)
def show(self): """Display selected specific options""" results = self.get_results() if not results: logger.warning('No specific option to display') else: data = list() columns = [ 'IP', 'Hostname', 'Service', 'Port', 'Proto', 'Name', 'Value', ] for r in results: 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.name, r.value, ]) Output.table(columns, data, hrules=False)
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): """Show selected products""" results = self.get_results() if not results: logger.warning('No product to display') else: data = list() columns = [ 'IP', 'Hostname', 'Service', 'Port', 'Proto', 'Type', 'Name', 'Version', ] for r in results: 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, r.name, r.version, ]) Output.table(columns, data, hrules=False)
def show_services(self, toolbox): """ Show all supported services along with number of installed tools / total number :param toolbox: Toolbox object :return: None """ data = list() columns = [ 'Service', 'Default port', '# Tools', '# Checks', ] for service in self.list_services(multi=True): data.append([ service, 'N/A' if service == 'multi' else '{port}/{proto}'.format( port=self.services[service]['default_port'], proto=self.services[service]['protocol']), '{nb_installed}/{nb_tools}'.format( nb_installed=toolbox.nb_tools_installed(service), nb_tools=toolbox.nb_tools(service)), 'N/A' if service == 'multi' else self.services[service]['checks'].nb_checks(), ]) Output.title1('Supported services') 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 print_technos(self): """ Display web technologies detected in a table. """ if len(self.technos) > 0: data = list() columns = ['Name', 'Version'] for t in self.technos: data.append([t['name'], t['version']]) Output.table(columns, data, hrules=False) else: logger.warning('No technology detected')
def __attack_target(self, id_, attack_progress): """ Run checks against a given target :param id_: Number of the target (as displayed in "id" column in show_summary()) """ target = self.targets[id_ - 1] if target.get_http_headers(): logger.info('HTTP Response headers:') for l in target.get_http_headers().splitlines(): Output.print(l) print() if target.get_credentials(): logger.info('Credentials set for this target:') data = list() columns = ['username', 'password'] if target.get_service_name() == 'http': columns.append('auth-type') for c in target.get_credentials(): username = '******' if c.username == '' else c.username if c.password is None: password = '******' else: password = '******' if c.password == '' else c.password line = [username, password] if target.get_service_name() == 'http': line.append(c.type) data.append(line) Output.table(columns, data, hrules=False) if target.get_specific_options(): logger.info('Context-specific options set for this target:') data = list() columns = ['option', 'value'] for o in target.get_specific_options(): data.append([o.name, o.value]) Output.table(columns, data, hrules=False) # TODO: add/edit specific options before run self.smartmodules_loader.call_start_method(target.service) service_checks = self.settings.services.get_service_checks( target.get_service_name()) service_checks.run(target, self.smartmodules_loader, self.results_requester, self.filter_categories, self.filter_checks, fast_mode=self.fast_mode, attack_progress=attack_progress)
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): 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_authentication_types(self, service='http'): """Display list of authentication types for HTTP.""" Output.title1('Supported {service} authentication types'.format( service=service.upper())) if not self.is_service_supported(service, multi=False): logger.warning('The service {service} is not supported'.format( service=service)) elif not self.services[service]['auth_types']: logger.warning('No special authentication type for this service') else: data = list() for t in sorted(self.services[service]['auth_types']): data.append([t]) Output.table(['Authentication types'], data, hrules=False)
def show_search_results(self, string, nb_words=12): """ Display command outputs search results. For good readability, only some words surrounding the search string are displayed. :param str string: Search string (accepts wildcard "%") :param int nb_words: Number of words surrounding the search string to show """ results = self.query.filter(CommandOutput.output.ilike('%'+string+'%')) if not results: logger.error('No result') else: Output.title2('Search results:') data = list() columns = [ 'IP', 'Port', 'Proto', 'Service', 'Check id', 'Category', 'Check', 'Matching text', ] for r in results: match = StringUtils.surrounding_text(r.outputraw, string, nb_words) # There might have several matches in one command result (one row # per match) for m in match: data.append([ r.result.service.host.ip, r.result.service.port, {Protocol.TCP: 'tcp', Protocol.UDP: 'udp'}.get( r.result.service.protocol), r.result.service.name, r.result.id, r.result.category, r.result.check, StringUtils.wrap(m, 70), ]) print() 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_authentication_types(self, service): """ Show list of authentication types for the given service. Actually relevant only for HTTP (for now ?) :param service: Service name :return: None """ Output.title1('Supported {service} authentication types'.format( service=service.upper())) if not self.is_service_supported(service, multi=False): logger.warning('The service {service} is not supported'.format( service=service)) elif not self.services[service]['auth_types']: logger.warning('No special authentication type for this service') else: data = list() for t in sorted(self.services[service]['auth_types']): data.append([t]) Output.table(['Authentication types'], data, hrules=False)
def show(self): results = self.get_results() if not results: logger.warning('No host to display') else: data = list() columns = [ 'IP', 'Hostname', 'OS', 'Comment', '# Services', ] for r in results: data.append( [r.ip, r.hostname, r.os, r.comment, len(r.services)]) Output.table(columns, data, hrules=False)
def show_results(self, service_id): service = self.sqlsess.query(Service).filter( Service.id == service_id).first() if not service: logger.error('Invalid service id') else: Output.title2('Attacks results:') Output.title2( 'Target: host={ip}{hostname} | port={port}/{proto} | service {service}' .format(ip=service.host.ip, hostname=' (' + service.host.hostname + ')' if service.host.hostname else '', port=service.port, proto={ Protocol.TCP: 'tcp', Protocol.UDP: 'udp' }.get(service.protocol), service=service.name)) results = self.sqlsess.query(Result).filter( Result.service_id == service_id).all() if not results: logger.warning('No results to display') else: data = list() columns = [ 'Check id', 'Category', 'Check', '# Commands', ] for r in results: data.append([ r.id, r.category, r.check, len(r.command_outputs), ]) Output.table(columns, data, hrules=False)
def show_specific_options(self, filter_service=None): """ Display supported specific options in a table. :param list filter_service: Filter on services (default: all) """ data = list() columns = [ 'Option', 'Service', 'Supported values', ] services = self.list_services() if filter_service is None else [ filter_service ] for service in services: options = self.services[service]['specific_options'] for opt in options: if options[opt] == OptionType.BOOLEAN: values = 'true, false' elif options[opt] == OptionType.LIST: values = sorted( self.services[service]['supported_list_options'][opt]) values = StringUtils.wrap(', '.join(values), 80) else: values = '<anything>' data.append([opt, service, values]) Output.title1('Available context-specific options for {filter}'.format( filter='all services' if filter_service is None \ else 'service ' + filter_service)) if not data: logger.warning('No specific option') else: 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 print_context(self): """Print target's context information""" # Print credentials if available if self.get_credentials(): logger.info('Credentials set for this target:') data = list() columns = ['Username', 'Password'] if self.get_service_name() == 'http': columns.append('auth-type') for c in self.get_credentials(): username = '******' if c.username == '' else c.username if c.password is None: password = '******' else: password = '******' if c.password == '' else c.password line = [username, password] if self.get_service_name() == 'http': line.append(c.type) data.append(line) Output.table(columns, data, hrules=False) # Print specific options if available if self.get_specific_options(): logger.info('Context-specific options set for this target:') data = list() columns = ['Option', 'Value'] for o in self.get_specific_options(): data.append([o.name, o.value]) Output.table(columns, data, hrules=False) # Print products if available if self.get_products(): logger.info('Products detected for this target:') data = list() columns = ['Type', 'Name', 'Version'] for p in self.get_products(): data.append([p.type, p.name, p.version]) Output.table(columns, data, hrules=False) # Print OS type if available if self.get_os(): logger.info('OS type detected for this target: {os}'.format( os=self.get_os()))
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()