def __init_with_url(self): """ Initialize with an URL (when targeting HTTP). This method updates: URL, Hostname, IP, Port :raises TargetException: Exception raised if DNS lookup fails """ self.service.url = WebUtils.add_prefix_http(self.service.url) self.service.url = WebUtils.remove_ending_slash(self.service.url) url = urlparse(self.service.url) if NetUtils.is_valid_ip(url.hostname): self.service.host.ip = url.hostname self.service.host.hostname = url.hostname # updated in smart_check else: self.service.host.ip = NetUtils.dns_lookup(url.hostname) if not self.service.host.ip: raise TargetException('Unable to resolve {}'.format( url.hostname)) self.service.host.hostname = url.hostname if not self.service.port: self.service.port = WebUtils.get_port_from_url(self.service.url) if not NetUtils.is_valid_port(self.service.port): raise TargetException('Invalid port number {}'.format( self.service.port))
def __init_with_ip(self): """ Initialize with an IP address or a hostname. This method updates: Hostname, IP :raises TargetException: Exception raised if DNS lookup fails """ if NetUtils.is_valid_ip(self.service.host.ip): self.service.host.hostname = str(self.service.host.ip) # updated in smart_check else: # host.ip actually stores a hostname at this point, a DNS lookup is needed self.service.host.hostname = self.service.host.ip self.service.host.ip = NetUtils.dns_lookup( self.service.host.hostname) if self.service.host.ip: logger.info('DNS lookup on {hostname} -> IP: {ip}'.format( hostname=self.service.host.hostname, ip=self.service.host.ip)) else: raise TargetException('Unable to resolve {}'.format( self.service.host.hostname)) # Forge URL for http services if self.service.name == 'http': if self.get_specific_option_value('https'): proto = 'https' else: proto = 'http' self.service.url = '{proto}://{ip}:{port}'.format( proto=proto, ip=self.service.host.ip, port=self.service.port)
def __init_with_ip(self): """ """ if NetUtils.is_valid_ip(self.service.host.ip): self.service.host.hostname = NetUtils.reverse_dns_lookup(str(self.service.host.ip)) else: # host.ip actually stores a hostname at this point self.service.host.ip = NetUtils.dns_lookup(str(self.service.host.ip)) self.service.host.hostname = self.service.host.ip
def __init_with_url(self): """ """ self.service.url = WebUtils.add_prefix_http(self.service.url) url = urlparse(self.service.url) if NetUtils.is_valid_ip(url.hostname): self.service.host.ip = url.hostname self.service.host.hostname = NetUtils.reverse_dns_lookup(url.hostname) else: self.service.host.ip = NetUtils.dns_lookup(url.hostname) self.service.host.hostname = url.hostname if not self.service.port: self.service.port = WebUtils.get_port_from_url(self.service.url)
def __init_with_url(self, url): p = urlparse(url) if NetUtils.is_valid_ip(p.hostname): self.ip = p.hostname else: self.ip = NetUtils.dns_lookup(p.hostname) if not self.ip: raise TargetException('Unable to resolve {}'.format(p.hostname)) self.port = NetUtils.get_port_from_url(url) if not NetUtils.is_valid_port(self.port): raise TargetException('Invalid port number {}'.format(self.port)) if url.lower().startswith('https://'): self.ssl = True
def add_url(self, url): matching_service = self.sqlsess.query(Service).join(Host).join(Mission)\ .filter(Mission.name == self.current_mission)\ .filter(Service.url == url).first() if matching_service: logger.warning('URL already present into database') else: # Parse URL: Get IP, hostname, port parsed = urlparse(url) if NetUtils.is_valid_ip(parsed.hostname): ip = parsed.hostname hostname = NetUtils.reverse_dns_lookup(parsed.hostname) else: ip = NetUtils.dns_lookup(parsed.hostname) if not ip: logger.error('Host cannot be resolved') return hostname = parsed.hostname port = WebUtils.get_port_from_url(url) # Check URL, grab headers, html title is_reachable, status, resp_headers = WebUtils.is_url_reachable(url) if is_reachable: comment = WebUtils.grab_html_title(url) if resp_headers: http_headers = '\n'.join("{}: {}".format(key, val) for (key, val) in resp_headers.items()) logger.info('HTTP Headers:') print(http_headers) logger.info('Title: {}'.format(comment)) logger.info( 'Grabbing banner from {ip}:{port} with Nmap...'.format( ip=ip, port=port)) banner = NetUtils.grab_banner_nmap(ip, port) logger.info('Banner: {}'.format(banner or 'None')) os = NetUtils.os_from_nmap_banner(banner) if os: logger.info('Detected Host OS: {}'.format(os)) else: comment = 'Not reachable' banner = http_headers = '' logger.warning('URL seems not to be reachable') # Add service in db (and host if not existing) service = Service(name='http', port=port, protocol=Protocol.TCP, url=url, up=is_reachable, http_headers=http_headers, banner=banner, comment=comment) matching_host = self.sqlsess.query(Host).join(Mission)\ .filter(Mission.name == self.current_mission)\ .filter(Host.ip == ip).first() new_host = Host(ip=ip, hostname=hostname, os=os) 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')
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()