def main(): """ This function obtains hosts from core and starts a nessus scan on these hosts. The nessus tag is appended to the host tags. """ config = Config() core = HostSearch() hosts = core.get_hosts(tags=['!nessus'], up=True) hosts = [host for host in hosts] host_ips = ",".join([str(host.address) for host in hosts]) url = config.get('nessus', 'host') access = config.get('nessus', 'access_key') secret = config.get('nessus', 'secret_key') template_name = config.get('nessus', 'template_name') nessus = Nessus(access, secret, url, template_name) scan_id = nessus.create_scan(host_ips) nessus.start_scan(scan_id) for host in hosts: host.add_tag('nessus') host.save() Logger().log("nessus", "Nessus scan started on {} hosts".format(len(hosts)), {'scanned_hosts': len(hosts)})
def parse_domain_computers(filename): """ Parse the file and extract the computers, import the computers that resolve into jackal. """ with open(filename) as f: data = json.loads(f.read()) hs = HostSearch() count = 0 entry_count = 0 print_notification("Parsing {} entries".format(len(data))) for system in data: entry_count += 1 parsed = parse_single_computer(system) if parsed.ip: host = hs.id_to_object(parsed.ip) host.description.append(parsed.description) host.hostname.append(parsed.dns_hostname) if parsed.os: host.os = parsed.os host.domain_controller = parsed.dc host.add_tag('domaindump') host.save() count += 1 sys.stdout.write('\r') sys.stdout.write("[{}/{}] {} resolved".format(entry_count, len(data), count)) sys.stdout.flush() sys.stdout.write('\r') return count
def main(): hs = HostSearch() arg = argparse.ArgumentParser(parents=[hs.argparser], conflict_handler='resolve') arg.add_argument('-c', '--count', help="Only show the number of results", action="store_true") arg.add_argument('-a', '--add', help="Add a new range", action="store_true") arguments = arg.parse_args() if arguments.add: print_notification("Adding new host") address = input("What host do you want to add? ") host = hs.id_to_object(address) print_success("Added a new host:") print_json(host.to_dict(include_meta=True)) elif arguments.count: print_line("Number of hosts: {}".format(hs.argument_count())) else: response = hs.get_hosts() for hit in response: print_json(hit.to_dict(include_meta=True))
def main(): us = UserSearch() domains = us.get_domains() if not len(domains): print_error("No domains found...") return argparser = argparse.ArgumentParser( description= "Password bruteforce via ldap. All users for the given domain are tried, users with an entry in jk-creds will be omitted." ) argparser.add_argument( "-d", "--domain", choices=domains, default=domains[0], help="Domain to retrieve users from, default: {}".format(domains[0])) argparser.add_argument("-p", "--password", type=str, required=True, help="Password to try") argparser.add_argument( "-s", "--server", type=str, help= "Server to connect to, if not given, one will be retrieved from jackal." ) arguments = argparser.parse_args() host = '' if not arguments.server: hs = HostSearch(use_pipe=False) host_result = hs.search(count=1, up=True, ports=[389], domain=arguments.domain) if len(host_result): host = str(host_result[0].address) else: print_error("No host could be found for domain: {}".format( arguments.domain)) print_error("Try giving one with -s") return else: host = arguments.server cs = CredentialSearch(use_pip=False) known_users = set() credentials = cs.search(domain=arguments.domain) [known_users.add(credential.username) for credential in credentials] users = [ user for user in us.get_users(domain=arguments.domain, tags=['!' + tag]) ] users = [user for user in users if not user.username in known_users] bruteforce(users, arguments.domain, arguments.password, host)
def import_smb(database_path): print_notification("Importing SMB database") conn = sqlite3.connect(database_path) host_search = HostSearch(use_pipe=False) host_map = {} # Inserting the hosts computer_count = 0 for computer in conn.execute("SELECT id, ip, hostname, domain, os, dc FROM computers"): host = host_search.id_to_object(computer[1]) if computer[2]: host.hostname.append(computer[2]) if computer[4]: host.os = computer[4] if computer[5]: host.domain_controller = computer[5] host_map[computer[0]] = computer[1] host.add_tag("cme_import") host.save() computer_count += 1 # Inserting the retrieved users, services and credentials. user_count = 0 admin_count = 0 user_search = UserSearch(use_pipe=False) for user in conn.execute("SELECT id, domain, username, password, credtype, pillaged_from_computerid FROM users"): # Add user jackal_user = user_search.id_to_object(user[2]) if user[1]: jackal_user.domain.append(user[1]) jackal_user.add_tag("cme_import") jackal_user.save() user_count += 1 try: address = host_map[user[5]] except KeyError: address = None # Add credential add_credential(user[2], user[3], user[1], address, user[4], port=445) for admin_host in conn.execute("SELECT computerid FROM admin_relations WHERE userid=?", (int(user[0]),)): admin_count += 1 admin_pc = host_map[admin_host[0]] add_credential(user[2], user[3], user[1], admin_pc, user[4], port=445, access_level='Administrator') conn.close() # Log the info stats = {} stats['hosts'] = computer_count stats['users'] = user_count stats['admins'] = admin_count stats['file'] = database_path Logger().log('cme_smb', "Imported CME smb database: {}".format(database_path), stats)
def exploit(self): """ Starts the exploiting phase, you should run setup before running this function. if auto is set, this function will fire the exploit to all systems. Otherwise a curses interface is shown. """ search = ServiceSearch() host_search = HostSearch() services = search.get_services(tags=['MS17-010']) services = [service for service in services] if len(services) == 0: print_error("No services found that are vulnerable for MS17-010") return if self.auto: print_success("Found {} services vulnerable for MS17-010".format( len(services))) for service in services: print_success("Exploiting " + str(service.address)) host = host_search.id_to_object(str(service.address)) system_os = '' if host.os: system_os = host.os else: system_os = self.detect_os(str(service.address)) host.os = system_os host.save() text = self.exploit_single(str(service.address), system_os) print_notification(text) else: service_list = [] for service in services: host = host_search.id_to_object(str(service.address)) system_os = '' if host.os: system_os = host.os else: system_os = self.detect_os(str(service.address)) host.os = system_os host.save() service_list.append({ 'ip': service.address, 'os': system_os, 'string': "{ip} ({os}) {hostname}".format(ip=service.address, os=system_os, hostname=host.hostname) }) draw_interface(service_list, self.callback, "Exploiting {ip} with OS: {os}")
def __init__(self, netmask='255.255.255.0', include_public=False, own_ip=None): self.ip_list = set() self.ip_ranges = set() self.rs = RangeSearch() self.hs = HostSearch() self.netmask = netmask self.include_public = include_public if own_ip: self.ip_list.add(own_ip)
def import_nmap(result, tag, check_function=all_hosts, import_services=False): """ Imports the given nmap result. """ host_search = HostSearch(arguments=False) service_search = ServiceSearch() parser = NmapParser() report = parser.parse_fromstring(result) imported_hosts = 0 imported_services = 0 for nmap_host in report.hosts: if check_function(nmap_host): imported_hosts += 1 host = host_search.id_to_object(nmap_host.address) host.status = nmap_host.status host.add_tag(tag) if nmap_host.os_fingerprinted: host.os = nmap_host.os_fingerprint if nmap_host.hostnames: host.hostname.extend(nmap_host.hostnames) if import_services: for service in nmap_host.services: imported_services += 1 serv = Service(**service.get_dict()) serv.address = nmap_host.address service_id = service_search.object_to_id(serv) if service_id: # Existing object, save the banner and script results. serv_old = Service.get(service_id) if service.banner: serv_old.banner = service.banner # TODO implement # if service.script_results: # serv_old.script_results.extend(service.script_results) serv_old.save() else: # New object serv.address = nmap_host.address serv.save() if service.state == 'open': host.open_ports.append(service.port) if service.state == 'closed': host.closed_ports.append(service.port) if service.state == 'filtered': host.filtered_ports.append(service.port) host.save() if imported_hosts: print_success("Imported {} hosts, with tag {}".format( imported_hosts, tag)) else: print_error("No hosts found") return {'hosts': imported_hosts, 'services': imported_services}
def nmap_scan(): """ Scans the given hosts with nmap. """ # Create the search and config objects hs = HostSearch() config = Config() # Static options to be able to figure out what options to use depending on the input the user gives. nmap_types = ['top10', 'top100', 'custom', 'top1000', 'all'] options = {'top10':'--top-ports 10', 'top100':'--top-ports 100', 'custom': config.get('nmap', 'options'), 'top1000': '--top-ports 1000', 'all': '-p-'} # Create an argument parser hs_parser = hs.argparser argparser = argparse.ArgumentParser(parents=[hs_parser], conflict_handler='resolve', \ description="Scans hosts from the database using nmap, any arguments that are not in the help are passed to nmap") argparser.add_argument('type', metavar='type', \ help='The number of ports to scan: top10, top100, custom, top1000 (default) or all', \ type=str, choices=nmap_types, default='top1000', const='top1000', nargs='?') arguments, extra_nmap_args = argparser.parse_known_args() # Fix the tags for the search tags = nmap_types[nmap_types.index(arguments.type):] tags = ["!nmap_" + tag for tag in tags] hosts = hs.get_hosts(tags=tags) hosts = [host for host in hosts] # Create the nmap arguments nmap_args = [] nmap_args.extend(extra_nmap_args) nmap_args.extend(options[arguments.type].split(' ')) # Run nmap print_notification("Running nmap with args: {} on {} hosts(s)".format(nmap_args, len(hosts))) if len(hosts): result = nmap(nmap_args, [str(h.address) for h in hosts]) # Import the nmap result for host in hosts: host.add_tag("nmap_{}".format(arguments.type)) host.save() print_notification("Nmap done, importing results") stats = import_nmap(result, "nmap_{}".format(arguments.type), check_function=all_hosts, import_services=True) stats['scanned_hosts'] = len(hosts) stats['type'] = arguments.type Logger().log('nmap_scan', "Performed nmap {} scan on {} hosts".format(arguments.type, len(hosts)), stats) else: print_notification("No hosts found")
def os_discovery(): """ Performs os (and domain) discovery of smb hosts. """ hs = HostSearch() hosts = hs.get_hosts(ports=[445], tags=['!nmap_os']) # TODO fix filter for emtpy fields. hosts = [host for host in hosts if not host.os] host_dict = {} for host in hosts: host_dict[str(host.address)] = host arguments = "--script smb-os-discovery.nse -p 445 -Pn -n --disable-arp-ping".split( ' ') if len(hosts): count = 0 print_notification("Checking OS of {} systems".format(len(hosts))) result = nmap(arguments, [str(h.address) for h in hosts]) parser = NmapParser() report = parser.parse_fromstring(result) for nmap_host in report.hosts: for script_result in nmap_host.scripts_results: script_result = script_result.get('elements', {}) host = host_dict[str(nmap_host.address)] if 'fqdn' in script_result: host.hostname.append(script_result['fqdn']) if 'os' in script_result: count += 1 host.os = script_result['os'] host_dict[str(nmap_host.address)] = host for host in hosts: host.add_tag('nmap_os') host.save() print_notification("Done, found the os of {} systems".format(count)) else: print_notification("No systems found to be checked.")
def parse_ips(ips, netmask, include_public): """ Parses the list of ips, turns these into ranges based on the netmask given. Set include_public to True to include public IP adresses. """ hs = HostSearch() rs = RangeSearch() ranges = [] ips = list(set(ips)) included_ips = [] print_success("Found {} ips".format(len(ips))) for ip in ips: ip_address = ipaddress.ip_address(ip) if include_public or ip_address.is_private: # To stop the screen filling with ranges. if len(ips) < 15: print_success("Found ip: {}".format(ip)) host = hs.id_to_object(ip) host.add_tag('dns_discover') host.save() r = str(ipaddress.IPv4Network("{}/{}".format(ip, netmask), strict=False)) ranges.append(r) included_ips.append(ip) else: print_notification("Excluding ip {}".format(ip)) ranges = list(set(ranges)) print_success("Found {} ranges".format(len(ranges))) for rng in ranges: # To stop the screen filling with ranges. if len(ranges) < 15: print_success("Found range: {}".format(rng)) r = rs.id_to_object(rng) r.add_tag('dns_discover') r.save() stats = {} stats['ips'] = included_ips stats['ranges'] = ranges return stats
class Sniffer(object): """ Sniffer class """ def __init__(self, netmask='255.255.255.0', include_public=False, own_ip=None): self.ip_list = set() self.ip_ranges = set() self.rs = RangeSearch() self.hs = HostSearch() self.netmask = netmask self.include_public = include_public if own_ip: self.ip_list.add(own_ip) def callback(self, pkt): """ Callback for the scapy sniffer """ if ARP in pkt: self.parse_ip(pkt.sprintf("%ARP.psrc%")) if TCP in pkt or UDP in pkt: self.parse_ip(pkt.sprintf("%IP.src%")) self.parse_ip(pkt.sprintf("%IP.dst%")) def parse_ip(self, ip): """ Parses an ip to extract the range. Calls new_ip and new_range when a new ip is found. Excludes ranges that are multicast and loopback. """ if not ip in self.ip_list: try: ip_address = ipaddress.ip_address(ip) use = not (ip_address.is_multicast or ip_address.is_unspecified or ip_address.is_reserved or ip_address.is_loopback or ip_address.is_link_local) if use and (self.include_public or ip_address.is_private): self.new_ip(ip) network = ipaddress.IPv4Network("{}/{}".format( ip, self.netmask), strict=False) self.new_range(str(network)) except ValueError: pass def new_ip(self, ip): """ Function called when a new IP address was seen """ if not ip in self.ip_list: self.ip_list.add(ip) host = self.hs.id_to_object(ip) host.add_tag('sniffer') host.save() print_success("New ip address: {}".format(ip)) def new_range(self, ip_range): """ Function called when a new range was seen """ if not ip_range in self.ip_ranges: self.ip_ranges.add(ip_range) doc = self.rs.id_to_object(ip_range) doc.add_tag('sniffer') doc.save() print_success("New ip range: {}".format(ip_range)) def start(self, timeout=None): """ Starts the sniffing """ if timeout: print_notification( "Starting sniffer for {} seconds".format(timeout)) else: print_notification("Starting sniffer") print_notification("Press ctrl-c to stop sniffing") try: sniff(prn=self.callback, store=0, timeout=timeout) except PermissionError: print_error("Please run this tool as root")