def run(self): if self.args.list: self.settings.show_list_exploits() else: if self.args.target.lower().startswith('http'): target = Target(ip=None, port=None, url=self.args.target) else: ip, port = self.args.target.split(':', maxsplit=1) target = Target(ip=ip, port=port, url=None, ssl=self.args.ssl) exploit = self.settings.get_exploit(self.args.exploit) OutputUtils.title('Exploitation Attempt: {description}'.format( description=exploit.description)) out = exploit.run(target) if out is None: sys.exit(1) if exploit.check_success(): logger.success('{description}: Target is EXPLOITABLE !'.format( description=exploit.description)) logger.info('Exploit code available in: {directory}'.format( directory=exploit.directory)) else: logger.error( '{description}: Target seems NOT exploitable'.format( description=exploit.description))
def run(self): if self.args.list: self.settings.show_list_exploits() else: # Instantiate Target using URL or IP:PORT if self.args.target.lower().startswith('http'): target = Target(ip=None, port=None, url=self.args.target) else: ip, port = self.args.target.split(':', maxsplit=1) target = Target(ip=ip, port=port, url=None, ssl=self.args.ssl) # Get Exploit (or detection script) for selected vulnerability exploit = self.settings.get_exploit(self.args.vuln) # Check if specified mode is available for specified vuln if not exploit.is_mode_supported(self.args.mode): logger.error( 'Supplied mode ({mode}) is not supported for vulnerability {vuln}' .format(mode=self.args.mode, vuln=self.args.vuln)) sys.exit(1) # Print title and main information OutputUtils.title('Vulnerability: {description}'.format( description=exploit.description)) logger.info( 'Target product: {product}'.format(product=exploit.product)) logger.info('Vulnerability type: {vuln}'.format(vuln=exploit.type)) logger.info('Selected mode: {mode}'.format(mode=self.args.mode)) if self.args.mode == 'exploit' and exploit.type == 'rce': logger.info('RCE output available: {rceoutput}'.format( rceoutput='Y' if exploit.exploit_rce_output else 'N')) # Run exploit/detection script out = exploit.run(target, self.args.mode, self.args.cmd) if out is None: sys.exit(1) # Automatically check success when: # - Run in detection mode # - Run in exploit mode without --cmd provided (automatic exploit test) if self.args.mode == 'detect' or \ (self.args.mode == 'exploit' and (not self.args.cmd or len(self.args.cmd) == 0)): if exploit.check_success(self.args.mode): logger.success( '{description}: Target is EXPLOITABLE !'.format( description=exploit.description)) logger.info('Code available in: {directory}'.format( directory=exploit.directory)) else: logger.error( '{description}: Target seems NOT exploitable'.format( description=exploit.description))
def __run_for_multi_targets(self, args): """Run attack against multiple targets from the database""" # Get Mission from which targets must be extracted mission = self.sqlsess.query(Mission)\ .filter(Mission.name == args.mission).first() if mission: logger.info('Extracting targets from mission "{mission}" ...'.format( mission=mission.name)) else: raise AttackException('Mission {mission} does not exist into the ' \ 'database'.format(mission=args.mission)) # Initialize Services requester and add filter if provided req = ServicesRequester(self.sqlsess) req.select_mission(args.mission) if args.filters_combined: for filt in args.filter: logger.info('Applying filters on mission scope: {filter}'.format( filter=filt)) if len(args.filter) > 1: logger.info('Note: Logical OR is applied between each filter') req.add_filter(args.filters_combined) # Retrieve targeted services from database services = req.get_results() if not services: raise AttackException('There is no matching service to target into the ' \ 'database') # Add each targeted service into Attack scope for service in services: # Update credentials, options, products if specified in command-line if args.creds: for c in args.creds[service.name]: service.add_credential(c.clone()) if args.users: for u in args.users[service.name]: service.add_credential(u.clone()) if args.products: for p in args.products[service.name]: service.add_product(p.clone()) if args.options: for o in args.options[service.name]: service.add_option(o.clone()) # Initialize Target try: target = Target(service, self.settings.services) except TargetException as e: logger.error(e) continue self.attack_scope.add_target(target) # Run the attack self.attack_scope.attack()
def checkAndInitializeTarget(self, ip, port, service, url): """ Initialize the target based either on IP:PORT or on URL, plus service @Args ip: IP address (None if url given) port: Port number (None if url given) service: Service name url: URL (None if ip+port given) @Returns Boolean indicating status """ self.target = Target(ip, port, service, url) if not self.target.is_reachable: self.output.printError('Target seems not to be reachable...') sys.exit(0)
def __run_for_single_target(self, args): """Run attack against a single target specified into args""" req = ServicesRequester(self.sqlsess) mission = None # Get Mission if target must be added into a mission scope if args.add: mission = self.sqlsess.query(Mission).filter(Mission.name == args.add).first() if not mission: raise AttackException('The specified mission does not exist in the ' \ 'database. You should create it if needed') # Create new Service/Host objects (if service already exist, # will be merged by ServicesRequester.add_target) url = args.target_ip_or_url if args.target_mode == TargetMode.URL else '' ip = args.target_ip_or_url if args.target_mode == TargetMode.IP else '' service = Service( name=args.service, port=int(args.target_port), protocol=self.settings.services.get_protocol2(args.service), url=url) host = Host(ip=ip) # Will be updated when initializing Target() host.services.append(service) # Update context (credentials, options, products) if specified in command-line if args.creds: for c in args.creds[args.service]: self.sqlsess.add(c) service.credentials.append(c) if args.users: for u in args.users[args.service]: self.sqlsess.add(u) service.credentials.append(u) if args.products: for p in args.products[args.service]: self.sqlsess.add(p) service.products.append(p) if args.options: for o in args.options[args.service]: self.sqlsess.add(o) service.options.append(o) # Initialize Target try: target = Target(service, self.settings.services) except TargetException as e: logger.error(e) sys.exit(1) # Check Target and update its information: # - Reverse DNS lookup: by default # - Port check: always # - Nmap service detection: by default # - HTML title grabbing: always # - Web technologies detection: always # - Context initialization via SmartStart: always reachable = target.smart_check( reverse_dns_lookup=(args.reverse_dns is None or args.reverse_dns == 'on'), availability_check=True, nmap_banner_grabbing=(args.nmap_banner_grab is None \ or args.nmap_banner_grab == 'on'), html_title_grabbing=True, web_technos_detection=True, smart_context_initialize=True) # Display availability status, exit if not reachable if args.target_mode == TargetMode.IP: msg = 'Target service {neg}reachable: {target}'.format( neg='not ' if not reachable else '', target=target) else: msg = 'Target URL {url} is {neg}reachable'.format( url=target.get_url(), neg='not ' if not reachable else '') if reachable: logger.success(msg) else: logger.error(msg) return # Commit the target with updated information inside the appropriate # mission in the database if mission: logger.info('Results from this attack will be saved under mission ' \ '"{mission}" in database'.format(mission=mission.name)) req.select_mission(mission.name) req.add_target(target) # Run the attack self.attack_scope.add_target(target) self.attack_scope.attack() return
def parse(self, http_recheck=True): """ Parse the Shodan results :param bool http_recheck: If set to True, TCP ports are re-checked for HTTP(s) :return: Hosts :rtype: list(Host)|None """ results = list() host_id = 0 for ip in self.ips_list: host_id += 1 # Lookup the host query = None try: query = self.api.host(ip) except Exception as e: logger.error( "Error when querying shodan for IP {ip}: {exc}".format( ip=ip, exc=e)) return None logger.info('Importing Shodan results from https://www.shodan.io/host/' \ '{ip}'.format(ip=ip)) #print(query) # Get host information hostname = query["hostnames"][0] if query["hostnames"] else ip os = query.get( "os", '') # Shodan is often missing OS detection in my tests... os_vendor = '' os_family = '' if os: os_vendor = OSUtils.get_os_vendor(os) os_family = OSUtils.get_os_family(os) device_type = '' services = query["data"] # Create Host object host = Host( ip=ip, hostname=hostname, os=os, os_vendor=os_vendor, os_family=os_family, mac='', vendor='', type=device_type, ) logger.info('[Host {current_host}/{total_host}] Parsing host: ' \ '{ip}{hostname} ...'.format( current_host=host_id, total_host=len(self.ips_list), ip=host.ip, hostname=' ('+host.hostname+')' if host.hostname != host.ip else '')) # Loop over ports/services port_id = 0 for service in services: port_id += 1 module = service["_shodan"]["module"] name = get_service_name(module) port = service.get("port", None) protocol = service.get("transport", None) url = '' comment = '' html_title = '' http_headers = '' # Print current processed service print() logger.info('[Host {current_host}/{total_host} | ' \ 'Service {current_svc}/{total_svc}] Parsing service: ' \ 'host {ip} | port {port}/{proto} | service {service} ...'.format( current_host=host_id, total_host=len(self.ips_list), current_svc=port_id, total_svc=len(services), ip=host.ip, port=port, proto=protocol, service=name)) # Get banner product_name = service.get('product', '') product_version = service.get('version', '') banner = '{name}{version}'.format( name=product_name, version=' {}'.format(product_version) if product_version else '') # # Deduce OS from banner if possible # if not host.os: # host.os = OSUtils.os_from_nmap_banner(banner) # if host.os: # host.os_vendor = OSUtils.get_os_vendor(host.os) # host.os_family = OSUtils.get_os_family(host.os) # Get URL for http services if name == 'http': if 'https' in module or 'ssl' in module: proto = 'https' else: proto = 'http' url = "{proto}://{host}:{port}".format(proto=proto, host=hostname, port=port) # Recheck for HTTP/HTTPS for services undetermined by Shodan if http_recheck \ and protocol == "tcp" \ and not self.services_config.is_service_supported(name, multi=False): url = WebUtils.is_returning_http_data(ip, port) if url: logger.success("{url} seems to return HTTP data, marking it " \ "as http service".format(url=url)) name = "http" # Get page title and HTTP headers for HTTP services if "http" in name: if 'http' in service: html_title = service['http'].get('title', '') http_headers = service.get('data', '') # Only keep services supported by Jok3r if not self.services_config.is_service_supported(name, multi=False): logger.warning("Service not supported: host {ip} | port " "{port}/{proto} | service {service}".format( ip=ip, port=port, proto=protocol, service=name)) continue # Create Service object if protocol and port: service = Service( name=name, name_original=module, port=port, protocol={ "tcp": Protocol.TCP, "udp": Protocol.UDP }.get(protocol), url=url, up=True, banner=banner, comment=comment, html_title=html_title, http_headers=http_headers, ) host.services.append(service) # Target smart check: # - Check if service is still reachable (possible that it has been # shut down since Shodan scan) # - Perform web technologies detection: We could use the technologies # returned by Shodan API in host['data'][id]['http']['components'], # however it does not detect the version if it is possible # - Initialize the context of the target via SmartModules, based on the # information already known (i.e. banner, web technologies...) target = Target(service, self.services_config) up = target.smart_check( reverse_dns_lookup=False, # Done by Shodan availability_check= True, # Check if service is still reachable nmap_banner_grabbing=False, # Done by Shodan html_title_grabbing=False, # Done by Shodan web_technos_detection=True, smart_context_initialize=True) # TODO: Add an option to disable web technos detections by Jok3r # and only use technos names returned by Shodan (to speed up import # if needed) if not up: logger.warning('Service not reachable') if host.services: results.append(host) return results
def __run_for_single_target(self, args): """ Run attack against a single target specified into argss """ req = ServicesRequester(self.sqlsess) mission = None # Get Mission if target must be added into a mission scope if args.add: mission = self.sqlsess.query(Mission).filter( Mission.name == args.add).first() if not mission: raise AttackException( 'The specified mission does not exist in the database. You should create it if needed' ) # Create new Service/Host objects (if service already exist, will be merged by ServicesRequester.add_target) service = Service( name=args.service, port=int(args.target_port), protocol={ 'tcp': Protocol.TCP, 'udp': Protocol.UDP }.get(self.settings.services.get_protocol(args.service)), url=args.target_ip_or_url if args.target_mode == TargetMode.URL else '') host = Host( ip=args.target_ip_or_url if args.target_mode == TargetMode.IP else '') # Will be updated when initializing Target() host.services.append(service) # Update credentials and options if needed for c in self.creds[args.service]: service.credentials.append(c) for u in self.users[args.service]: service.credentials.append(u) for o in self.options[args.service]: service.options.append(o) # Initialize Target and check if reachable target = Target(service, self.settings.services) if args.disable_banner_grab: logger.info('Check if target is reachable...') else: logger.info( 'Check if target is reachable and grab banner using Nmap...') reachable = target.smart_check( grab_banner_nmap=not args.disable_banner_grab) if args.target_mode == TargetMode.IP: msg = 'Target {neg}reachable: host {ip} | port {port}/{proto} | service {service}'.format( neg='not ' if not reachable else '', ip=target.get_ip(), port=target.get_port(), proto=target.get_protocol(), service=target.get_service_name()) else: msg = 'Target URL {url} is {neg}reachable'.format( url=target.get_url(), neg='not ' if not reachable else '') if reachable: service.up = True logger.success(msg) else: raise AttackException(msg) # Commit new data into database if target must be added to a mission if mission: logger.info( 'Results from this attack will be saved under mission "{mission}" in database' .format(mission=mission.name)) req.select_mission(mission.name) req.add_target(target) # Run the attack self.attack_scope.add_target(target) self.attack_scope.attack()
def __run_for_multi_targets(self, args): """ Run attack against multiple targets from the database """ # Get Mission from which targets must be extracted mission = self.sqlsess.query(Mission).filter( Mission.name == args.mission).first() if mission: logger.info( 'Extracting targets from mission "{mission}" ...'.format( mission=mission.name)) else: raise AttackException( 'Mission {mission} does not exist into the database'.format( mission=args.mission)) # Initialize Services requester and add filter if provided requester = ServicesRequester(self.sqlsess) requester.select_mission(args.mission) if args.filters_combined: for filt in args.filter: logger.info( 'Applying filters on mission scope: {filter}'.format( filter=filt)) if len(args.filter) > 1: logger.info('Logical or is applied between each filter') requester.add_filter(args.filters_combined) # Retrieve targeted services from database services = requester.get_results() if not services: raise AttackException( 'There is no matching service to target into the database') # Add each targeted service into Attack scope logger.info('Checking if targets are reachable...') for service in services: # Update credentials and options if needed for c in self.creds[service.name]: service.credentials.append(c) for u in self.users[service.name]: service.credentials.append(u) for o in self.options[service.name]: service.options.append(o) # Initialize Target and check if reachable target = Target(service, self.settings.services) service.up = target.smart_check(grab_banner_nmap=False) self.sqlsess.commit() msg = 'host {ip} | port {port}/{proto} | service {service}'.format( ip=target.get_ip(), port=target.get_port(), proto=target.get_protocol(), service=target.get_service_name()) if service.up: logger.success('Target reachable: ' + msg) else: logger.warning('Target not reachable (skipped): ' + msg) continue # Update info into database if needed #requester.add_target(target) self.attack_scope.add_target(target) self.attack_scope.attack()
def add_service(self, ip, port, protocol, service, services_config, grab_banner_nmap=True, reverse_dns=True, availability_check=True): """ Add a service into the current mission scope in database. :param str ip: IP address to add :param int port: Port number :param str protocol: Protocol (tcp/udp) :param str service: Service name :param lib.core.ServicesConfig services_config: Services configuration object :param bool grab_banner_nmap: If set to True, run Nmap to grab server banner :param bool reverse_dns: If set to True, perform a reverse DNS lookup :param bool availability_check: If set to True, check if port is open :return: Status :rtype: bool """ proto = { 'tcp': Protocol.TCP, 'udp': Protocol.UDP }.get(protocol, Protocol.TCP) service = Service(port=int(port), protocol=proto, name=service) service.host = Host(ip=ip) try: target = Target(service, services_config) except Exception as e: logger.error(e) return False matching_service = self.sqlsess.query(Service).join(Host).join(Mission)\ .filter(Mission.name == self.current_mission)\ .filter(Host.ip == service.host.ip)\ .filter(Service.port == int(port))\ .filter(Service.protocol == proto).first() if matching_service: logger.warning('Service already present into database') return False else: up = target.smart_check(reverse_dns, availability_check, grab_banner_nmap) if up: # Add service in db (and host if not existing) matching_host = self.sqlsess.query(Host).join(Mission)\ .filter(Mission.name == self.current_mission)\ .filter(Host.ip == service.host.ip).first() new_host = Host(ip=service.host.ip, hostname=service.host.hostname, os=service.host.os, os_vendor=service.host.os_vendor, os_family=service.host.os_family, mac=service.host.mac, vendor=service.host.vendor, type=service.host.type) if matching_host: matching_host.merge(new_host) self.sqlsess.commit() service.host = matching_host else: mission = self.sqlsess.query(Mission)\ .filter(Mission.name == self.current_mission).first() new_host.mission = mission service.host = new_host self.sqlsess.add(new_host) self.sqlsess.add(service) self.sqlsess.commit() logger.success('Service added: host {ip} | port {port}/{proto} | ' \ 'service {service}'.format( ip=service.host.ip, port=port, proto=protocol, service=service.name)) return True else: logger.error( 'Service is not reachable, therefore it is not added') return False
def add_url(self, url, services_config, reverse_dns=True, availability_check=True, grab_banner_nmap=True, web_technos_detection=True): """ Add a URL into the current mission scope in database. :param str url: URL to add :param lib.core.ServicesConfig services_config: Services configuration object :param bool reverse_dns: If set to True, perform a reverse DNS lookup :param bool availability_check: If set to True, check if port is open :param bool grab_banner_nmap: If set to True, run Nmap to grab server banner :param bool web_technos_detection: If set to True, try to detect web technos :return: Status :rtype: bool """ matching_service = self.sqlsess.query(Service).join(Host).join(Mission)\ .filter(Mission.name == self.current_mission)\ .filter((Service.url == url) | \ (Service.url == WebUtils.remove_ending_slash(url))).first() if matching_service: logger.warning('URL already present into database') return False else: service = Service(name='http', protocol=Protocol.TCP, url=url) service.host = Host() # Update in target.smart_check() try: target = Target(service, services_config) except Exception as e: logger.error(e) return False up = target.smart_check(reverse_dns, availability_check, grab_banner_nmap, web_technos_detection) if up: matching_host = self.sqlsess.query(Host).join(Mission)\ .filter(Mission.name == self.current_mission)\ .filter(Host.ip == service.host.ip).first() new_host = Host(ip=service.host.ip, hostname=service.host.hostname, os=service.host.os, os_vendor=service.host.os_vendor, os_family=service.host.os_family, mac=service.host.mac, vendor=service.host.vendor, type=service.host.type) if matching_host: matching_host.merge(new_host) self.sqlsess.commit() service.host = matching_host else: mission = self.sqlsess.query(Mission)\ .filter(Mission.name == self.current_mission).first() new_host.mission = mission service.host = new_host self.sqlsess.add(new_host) self.sqlsess.add(service) self.sqlsess.commit() logger.success('Service/URL added: {url}'.format(url=url)) return True else: logger.error('URL is not reachable, therefore it is not added') return False
def __run_for_single_target(self, args): """Run attack against a single target specified into args""" req = ServicesRequester(self.sqlsess) mission = None # Get Mission if target must be added into a mission scope if args.add: mission = self.sqlsess.query(Mission).filter(Mission.name == args.add).first() if not mission: raise AttackException('The specified mission does not exist in the ' \ 'database. You should create it if needed') # Create new Service/Host objects (if service already exist, # will be merged by ServicesRequester.add_target) url = args.target_ip_or_url if args.target_mode == TargetMode.URL else '' ip = args.target_ip_or_url if args.target_mode == TargetMode.IP else '' service = Service(name=args.service, port=int(args.target_port), protocol=self.settings.services.get_protocol2(args.service), url=url) host = Host(ip=ip) # Will be updated when initializing Target() host.services.append(service) # Update credentials, options, products if specified in command-line for c in self.creds[args.service] : service.credentials.append(c) for u in self.users[args.service] : service.credentials.append(u) for p in self.products[args.service] : service.products.append(p) for o in self.options[args.service] : service.options.append(o) # Initialize Target try: target = Target(service, self.settings.services) except TargetException as e: logger.error(e) sys.exit(1) # Check if target is reachable # (by default, perform reverve DNS lookup & Nmap banner grabbing) reachable = target.smart_check( reverse_dns=(args.reverse_dns is None or args.reverse_dns == 'on'), availability_check=True, grab_banner_nmap=(args.nmap_banner_grab is None \ or args.nmap_banner_grab == 'on')) if args.target_mode == TargetMode.IP: msg = 'Target {neg}reachable: {target}'.format( neg='not ' if not reachable else '', target=target) else: msg = 'Target URL {url} is {neg}reachable'.format( url=target.get_url(), neg='not ' if not reachable else '') if reachable: logger.success(msg) else: # Skip target if not reachable logger.error(msg) return # Commit new data into database if target must be added to a mission if mission: logger.info('Results from this attack will be saved under mission ' \ '"{mission}" in database'.format(mission=mission.name)) req.select_mission(mission.name) req.add_target(target) # Run the attack self.attack_scope.add_target(target) self.attack_scope.attack()
def parse(self, http_recheck=True, html_title_grabbing=True, nmap_banner_grabbing=False, web_technos_detection=True): """ Parse the Nmap results :param bool http_recheck: If set to True, TCP ports are re-checked for HTTP(s) :param bool html_title_grabbing: If set to True, grab title of HTML page (text in <title> tags) and put it as comment for HTTP service :param bool nmap_banner_grabbing: If set to True, run Nmap to grab service banner for each service where it is missing (might be useful if imported Nmap results come from a scan run without -sV/-A) :param bool web_technos_detection: If set to True, try to detect web technos for HTTP service :return: Hosts :rtype: list(Host)|None """ try: nmap_report = NmapParser.parse_fromfile(self.nmap_file) except Exception as e: logger.error('Error when parsing the Nmap file: {0}'.format(e)) return None results = list() host_id = 0 for h in nmap_report.hosts: host_id += 1 # Get the fingerprinted OS if available os = '' os_vendor = '' os_family = '' device_type = '' if h.os_fingerprinted is True \ and h.os_match_probabilities() is not None \ and len(h.os_match_probabilities()) > 0: os_matchs = h.os_match_probabilities() if len(os_matchs) > 0: os = os_matchs[0].name if os_matchs[0].osclasses is not None \ and len(os_matchs[0].osclasses) > 0: os_vendor = os_matchs[0].osclasses[0].vendor os_family = os_matchs[0].osclasses[0].osfamily device_type = OSUtils.get_device_type( os, os_family, os_matchs[0].osclasses[0].type) # Create Host object host = Host(ip=h.ipv4, hostname=h.hostnames[0] if h.hostnames else h.ipv4, os=os, os_vendor=os_vendor, os_family=os_family, mac=h.mac, vendor=h.vendor, type=device_type) logger.info('[File {file} | Host {current_host}/{total_host}] ' \ 'Parsing host: {ip}{hostname} ...'.format( file=FileUtils.extract_filename(self.nmap_file), current_host=host_id, total_host=len(nmap_report.hosts), ip=host.ip, hostname=' ('+host.hostname+')' if host.hostname != host.ip else '')) # Loop over open ports port_id = 0 for p in h.get_open_ports(): port_id += 1 s = h.get_service(p[0], protocol=p[1]) name = get_service_name(s.service) url = '' comment = '' html_title = '' # Print current processed service print() logger.info('[File {file} | Host {current_host}/{total_host} | ' \ 'Service {current_svc}/{total_svc}] Parsing service: ' \ 'host {ip} | port {port}/{proto} | service {service} ...'.format( file=FileUtils.extract_filename(self.nmap_file), current_host=host_id, total_host=len(nmap_report.hosts), current_svc=port_id, total_svc=len(h.get_open_ports()), ip=h.ipv4, port=s.port, proto=s.protocol, service=name)) # Get URL for http services if name == 'http': if 'https' in s.service \ or 'ssl' in s.service \ or s.tunnel in ('ssl', 'tls'): proto = 'https' else: proto = 'http' url = '{proto}://{host}:{port}'.format( proto=proto, host=host.hostname, port=s.port) # Recheck for HTTP/HTTPS for services undetermined by Nmap if http_recheck \ and s.protocol == 'tcp' \ and not self.services_config.is_service_supported(name, multi=False): url = WebUtils.is_returning_http_data(host.ip, s.port) if url: logger.success('{url} seems to return HTTP data, marking it ' \ 'as http service'.format(url=url)) name = 'http' # Only keep services supported by Jok3r if not self.services_config.is_service_supported(name, multi=False): logger.warning('Service not supported: host {ip} | port ' \ '{port}/{proto} | service {service}'.format( ip = h.ipv4, port=s.port, proto=s.protocol, service=name)) continue # # Deduce OS from banner if possible # if not os: # host.os = OSUtils.os_from_nmap_banner(s.banner) # if host.os: # host.os_vendor = OSUtils.get_os_vendor(host.os) # host.os_family = OSUtils.get_os_family(host.os) # Clean Nmap banner banner = NetUtils.clean_nmap_banner(s.banner) # Create Service object service = Service( name=name, name_original=s.service, port=s.port, protocol={'tcp': Protocol.TCP,'udp': Protocol.UDP}.get(s.protocol), url=url, up=True, banner=banner, comment=comment, html_title=html_title) host.services.append(service) # Target smart check: # - Nmap banner grabbing if specified by user and banner is missing in # imported results; # - HTML title and HTTP response headers grabbing for HTTP service; # - Web technologies detection for HTTP service, except if disabled by # user; # - Initialize the context of the target via SmartModules, based on the # information already known (i.e. banner, web technologies...) target = Target(service, self.services_config) up = target.smart_check( reverse_dns_lookup=False, # Done by Nmap availability_check=False, # Done by Nmap nmap_banner_grabbing=nmap_banner_grabbing, # Default: False html_title_grabbing=html_title_grabbing, web_technos_detection=web_technos_detection, # Default: True smart_context_initialize=True) if not up: logger.warning('Service not reachable') if host.services: results.append(host) return results