コード例 #1
0
ファイル: nessus.py プロジェクト: taufderl/jackal
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)})
コード例 #2
0
ファイル: domaindump.py プロジェクト: taufderl/jackal
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
コード例 #3
0
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))
コード例 #4
0
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)
コード例 #5
0
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)
コード例 #6
0
    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}")
コード例 #7
0
ファイル: sniffer.py プロジェクト: mwgielen/jackal-tools
 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)
コード例 #8
0
ファイル: nmap.py プロジェクト: taufderl/jackal
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}
コード例 #9
0
ファイル: nmap.py プロジェクト: mwgielen/jackal
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")
コード例 #10
0
ファイル: nmap.py プロジェクト: taufderl/jackal
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.")
コード例 #11
0
ファイル: dns_discover.py プロジェクト: mwgielen/jackal
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
コード例 #12
0
ファイル: sniffer.py プロジェクト: mwgielen/jackal-tools
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")