Beispiel #1
0
class Module(ToolTemplate):
    name = "DNSRecon"
    binary_name = "dnsrecon"
    """
    This module runs DNSRecon on a domain or set of domains. This will extract found DNS entries.
    It can also run over IP ranges, looking for additional domains in the PTR records.

    DNSRecon can be installed from https://github.com/darkoperator/dnsrecon
    """
    def __init__(self, db):
        self.db = db
        self.BaseDomain = BaseDomainRepository(db, self.name)
        self.Domain = DomainRepository(db, self.name)
        self.ScopeCIDR = ScopeCIDRRepository(db, self.name)
        self.IPAddress = IPRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()
        self.options.add_argument("-d",
                                  "--domain",
                                  help="Target domain for dnsRecon")
        self.options.add_argument("-f",
                                  "--file",
                                  help="Import domains from file")
        self.options.add_argument(
            "-i",
            "--import_database",
            help="Import domains from database",
            action="store_true",
        )
        self.options.add_argument("-r",
                                  "--range",
                                  help="Range to scan for PTR records")
        self.options.add_argument(
            "-R",
            "--import_range",
            help="Import CIDRs from in-scope ranges in database",
            action="store_true",
        )
        self.options.add_argument("--rescan",
                                  help="Rescan domains already scanned",
                                  action="store_true")
        # self.options.add_argument('--import_output_xml', help="Import XML file")
        # self.options.add_argument('--import_output_json', help="Import json file")

    def get_targets(self, args):

        targets = []
        if args.domain:
            created, domain = self.BaseDomain.find_or_create(
                domain=args.domain, passive_scope=True)
            targets.append(domain.domain)

        elif args.file:
            domains = open(args.file).read().split("\n")
            for d in domains:
                if d:
                    created, domain = self.BaseDomain.find_or_create(
                        domain=d, passive_scope=True)
                    targets.append(domain.domain)

        elif args.import_database:
            if args.rescan:
                domains = self.BaseDomain.all(scope_type="passive")
            else:
                domains = self.BaseDomain.all(scope_type="passive",
                                              tool=self.name)
            for domain in domains:
                targets.append(domain.domain)

        elif args.range:
            targets.append(args.range)

        elif args.import_range:
            if args.rescan:
                cidrs = self.ScopeCIDR.all()
            else:
                cidrs = self.ScopeCIDR.all(tool=self.name)

            for cidr in cidrs:
                targets.append(cidr.cidr)

        if args.output_path[0] == "/":
            self.path = os.path.join(self.base_config["PROJECT"]["base_path"],
                                     args.output_path[1:])
        else:
            self.path = os.path.join(self.base_config["PROJECT"]["base_path"],
                                     args.output_path)

        if not os.path.exists(self.path):
            os.makedirs(self.path)

        res = []
        for t in targets:
            res.append({
                "target":
                t,
                "output":
                os.path.join(self.path,
                             t.replace("/", "_") + ".json"),
            })

        return res

    def build_cmd(self, args):
        command = self.binary

        if args.domain or args.file or args.import_database:

            command += " -d {target} -j {output} "

        else:
            command += " -s -r {target} -j {output} "

        if args.tool_args:
            command += args.tool_args

        return command

    def process_output(self, cmds):

        for c in cmds:
            target = c["target"]
            output_path = c["output"]

            try:
                res = json.loads(open(output_path).read())
            except IOError:
                display_error("DnsRecon failed for {}".format(target))
                continue
            if " -d " in res[0]["arguments"]:
                created, dbrec = self.Domain.find_or_create(domain=target)
                dbrec.dns = res
                dbrec.save()

            for record in res:
                domain = None
                ip = None
                if record.get("type") == "A" or record.get("type") == "PTR":
                    domain = record.get("name").lower().replace("www.", "")
                    ip = record.get("address")

                elif record.get("type") == "MX":
                    domain = record.get("exchange").lower().replace("www.", "")

                elif record.get("type") == "SRV" or record.get("type" == "NS"):
                    domain = record.get("target").lower().replace("www.", "")

                elif record.get("type") == "SOA":
                    domain = record.get("mname").lower().replace("www.", "")

                if domain:
                    created, domain_obj = self.Domain.find_or_create(
                        domain=domain)
                    if ip:
                        created, ip_obj = self.IPAddress.find_or_create(
                            ip_address=ip)
                        domain_obj.ip_addresses.append(ip_obj)
                        domain_obj.save()

            if '/' in target:
                created, bd = self.ScopeCIDR.find_or_create(cidr=target)
            else:
                created, bd = self.BaseDomain.find_or_create(domain=target)
            bd.set_tool(self.name)
        self.Domain.commit()
Beispiel #2
0
class Module(ToolTemplate):
'''
PyMeta is a tool used for searching domains on various search engines, finding all of the relevant
documents, and raiding the exif data to find users.

'''
    name = "PyMeta"
    binary_name = "pymeta"

    def __init__(self, db):
        self.db = db
        self.BaseDomain = BaseDomainRepository(db, self.name)
        self.User = UserRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()

        self.options.add_argument("-d", "--domain", help="Domain to brute force")
        self.options.add_argument("-f", "--file", help="Import domains from file")
        self.options.add_argument(
            "-i",
            "--import_database",
            help="Import domains from database",
            action="store_true",
        )
        self.options.add_argument(
            "-s",
            "--rescan",
            help="Rescan domains that have already been scanned",
            action="store_true",
        )

    def get_targets(self, args):

        targets = []
        if args.domain:
            targets.append(args.domain)

        elif args.file:
            domains = open(args.file).read().split("\n")
            for d in domains:
                if d:
                    targets.append(d)

        elif args.import_database:
            if args.rescan:
                domains = self.BaseDomain.all(scope_type="passive")
            else:
                domains = self.BaseDomain.all(tool=self.name, scope_type="passive")
            for d in domains:

                targets.append(d.domain)

        res = []

        if args.output_path[0] == "/":
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path[1:]
            )
        else:
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path
            )

        if not os.path.exists(output_path):
            os.makedirs(output_path)

        for t in targets:

            output = os.path.join(output_path)
            res.append({"target": t, "output": output})

        return res

    def build_cmd(self, args):

        cmd = self.binary + " -o {output} -d {target} -csv -f full "
        if args.tool_args:
            cmd += args.tool_args
        return cmd

    def process_output(self, cmds):

        for cmd in cmds:
            output_path = cmd["output"]

            created, domain_obj = self.BaseDomain.find_or_create(domain=cmd["target"])

            try:
                csvreader = csv.reader(open(os.path.join(cmd["output"], "pymeta_{}.csv".format(cmd["target"]))))
                
                if sys.version[0] == '2':
                    headers = csvreader.next()
                    
                else:
                    headers = csvreader.__next__()

                searchable_headers = ["Author", "Creator", "Producer"]
                indexes = [headers.index(s) for s in searchable_headers if s in headers]

                data = []
                for row in csvreader:
                    for i in indexes:
                        data.append(row[i])

                data = list(set(data))  # Dedup

                for d in data:
                    # pdb.set_trace()
                    if d.strip() and len(d.split(' '))==2:

                        res = raw_input("Is %s a valid name? [y/N] " % d)
                        if res and res[0].lower() == "y":
                            if " " in d:
                                if ", " in d:
                                    first_name = d.split(", ")[1]
                                    last_name = d.split(", ")[0]
                                else:
                                    first_name = d.split(" ")[0]
                                    last_name = " ".join(d.split(" ")[1:])

                                created, user = self.User.find_or_create(
                                    first_name=first_name, last_name=last_name
                                )
                                if created:
                                    print("New user created")
                                user.domain = domain_obj
                    elif '@' in d:
                        res = raw_input("Is %s a valid email address? [y/N] " % d)
                        if res and res[0].lower() == 'y':
                            created, user = self.User.find_or_create(
                                email=d.strip())
                            if created:
                                print("New user created")
                            user.domain = domain_obj

            except IOError:
                pass
            except Exception as e:
                
                display_error("Error processing pymeta_{}.csv: {}".format(cmd["target"], e))
            
        self.User.commit()
Beispiel #3
0
class Module(ToolTemplate):
    '''
    This module uses Gobuster in the DNS brute forcing mode. Gobuster can be installed from:

    https://github.com/OJ/gobuster
    '''

    name = "GobusterDNS"
    binary_name = "gobuster"

    def __init__(self, db):
        self.db = db
        self.BaseDomain = BaseDomainRepository(db, self.name)
        self.Domain = DomainRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()

        self.options.add_argument("-d",
                                  "--domain",
                                  help="Domain to brute force")
        self.options.add_argument("-f",
                                  "--file",
                                  help="Import domains from file")
        self.options.add_argument(
            "-i",
            "--import_database",
            help="Import domains from database",
            action="store_true",
        )
        self.options.add_argument(
            "-s",
            "--rescan",
            help="Rescan domains that have already been brute forced",
            action="store_true",
        )
        self.options.set_defaults(
            timeout=600)  # Kick the default timeout to 10 minutes

    def get_targets(self, args):
        targets = []

        if args.domain:

            targets.append(args.domain)

        if args.file:
            domains = open(args.file).read().split("\n")
            for d in domains:
                if d:
                    targets.append(d)

        if args.import_database:
            if args.rescan:
                targets += [
                    b.domain for b in self.BaseDomain.all(scope_type="passive")
                ]
            else:
                targets += [
                    b.domain for b in self.BaseDomain.all(scope_type="passive",
                                                          tool=self.name)
                ]

        if args.output_path[0] == "/":
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path[1:])

        else:
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path)

        if not os.path.exists(output_path):
            os.makedirs(output_path)

        res = []
        for t in targets:
            res.append({
                "target":
                t,
                "output":
                os.path.join(output_path,
                             t.replace("/", "_") + "-dns.txt"),
            })

        return res

    def build_cmd(self, args):

        cmd = self.binary + " dns "
        cmd += " -o {output} -d {target} "

        if args.tool_args:
            cmd += args.tool_args

        return cmd

    def process_output(self, cmds):

        for c in cmds:
            output_path = c["output"]
            if os.path.isfile(output_path):
                data = open(output_path).read().split("\n")
                for d in data:
                    if "Found: " in d:
                        new_domain = d.split(" ")[1].lower()
                        created, subdomain = self.Domain.find_or_create(
                            domain=new_domain)
            else:
                display_error("{} not found.".format(output_path))

            created, bd = self.BaseDomain.find_or_create(domain=c['target'])
            bd.set_tool(self.name)
        self.Domain.commit()
class Module(ToolTemplate):
    '''
    This module uses the Ruby version of Aquatone. You can usually install it with "gem install aquatone"

    '''
    name = "Aquatone Takeover"
    binary_name = "aquatone-takeover"

    def __init__(self, db):
        self.db = db
        self.Domain = DomainRepository(db, self.name)
        self.BaseDomain = BaseDomainRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()

        self.options.add_argument(
            "-i",
            "--import_database",
            help="Import domains from database",
            action="store_true",
        )
        self.options.add_argument(
            "-r",
            "--rescan",
            help="Run aquatone on hosts that have already been processed.",
            action="store_true",
        )
        self.options.set_defaults(timeout=None)

    def get_targets(self, args):
        """
        This module is used to build out a target list and output file list, depending on the arguments. Should return a
        list in the format [(target, output), (target, output), etc, etc]
        """
        targets = []

        if args.import_database:
            if args.rescan:
                all_domains = self.BaseDomain.all(scope_type="passive")
            else:
                all_domains = self.BaseDomain.all(tool=self.name,
                                                  scope_type="passive")
            for d in all_domains:
                # We need to find all of the http/https ports and create the json file.
                output_path = os.path.join(
                    self.base_config["PROJECT"]["base_path"],
                    "output",
                    "aquatone",
                    d.domain,
                )
                if not os.path.exists(output_path):
                    os.makedirs(output_path)

                hosts_j = {}
                hosts = []
                open_ports = []
                urls = []

                targets.append(d.domain)

                for s in d.subdomains:
                    name = s.domain

                    for ip in s.ip_addresses:
                        hosts_j[name] = ip.ip_address
                        port_list = []
                        for p in ip.ports:

                            if "http" in p.service_name:
                                hosts.append("{}.{}".format(
                                    name, ip.ip_address))

                                port_list.append(p.port_number)
                                urls.append("{}://{}:{}/".format(
                                    p.service_name, name, p.port_number))
                                urls.append("{}://{}:{}/".format(
                                    p.service_name, ip.ip_address,
                                    p.port_number))
                        if port_list:
                            open_ports.append("{},{}".format(
                                ip.ip_address,
                                ",".join([str(o) for o in port_list])))

                open(os.path.join(output_path, "hosts.txt"),
                     "w").write("\n".join(list(set(hosts))))
                open(os.path.join(output_path, "urls.txt"),
                     "w").write("\n".join(list(set(urls))))
                open(os.path.join(output_path, "open_ports.txt"),
                     "w").write("\n".join(list(set(open_ports))))
                open(os.path.join(output_path, "hosts.json"),
                     "w").write(json.dumps(hosts_j))
        else:
            display_error("You need to supply domain(s).")

        res = []
        for t in targets:
            res.append({"target": t})

        return res

    def build_cmd(self, args):
        """
        Create the actual command that will be executed. Use {target} and {output} as placeholders.
        """
        cmd = self.binary + " -d {target} "

        if args.tool_args:
            cmd += args.tool_args

        return cmd

    def pre_run(self, args):
        output_path = os.path.join(self.base_config["PROJECT"]["base_path"],
                                   "output")

        self.orig_home = os.environ["HOME"]

        os.environ["HOME"] = output_path

    def process_output(self, cmds):
        """
        Process the output generated by the earlier commands.
        """

        for cmd in cmds:

            created, domain = self.BaseDomain.find_or_create(
                domain=cmd['target'])
            domain.set_tool(self.name)

        self.BaseDomain.commit()

    def post_run(self, args):

        display("Potential takeovers are stored in {}".format(
            os.environ["HOME"]))
        os.environ["HOME"] = self.orig_home
Beispiel #5
0
class Module(ToolTemplate):

    name = "Whois"
    binary_name = "whois"

    def __init__(self, db):
        self.db = db
        self.BaseDomain = BaseDomainRepository(db, self.name)
        self.ScopeCidr = ScopeCIDRRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()

        self.options.add_argument("-d", "--domain", help="Domain to query")
        self.options.add_argument("-c", "--cidr", help="CIDR to query")

        self.options.add_argument(
            "-s",
            "--rescan",
            help="Rescan domains that have already been scanned",
            action="store_true",
        )
        self.options.add_argument(
            "-a",
            "--all_data",
            help="Scan all data in database, regardless of scope",
            action="store_true",
        )
        self.options.add_argument(
            "-i",
            "--import_database",
            help="Run WHOIS on all domains and CIDRs in database",
            action="store_true",
        )

    def get_targets(self, args):

        targets = []
        if args.domain:

            targets.append({"domain": args.domain, "cidr": ""})

        elif args.cidr:

            targets.append({"domain": "", "cidr": args.cidr.split("/")[0]})

        elif args.import_database:

            if args.all_data:
                scope_type = ""
            else:
                scope_type = "passive"
            if args.rescan:
                domains = self.BaseDomain.all(scope_type=scope_type)
                cidrs = self.ScopeCidr.all()
            else:
                domains = self.BaseDomain.all(scope_type=scope_type,
                                              tool=self.name)
                cidrs = self.ScopeCidr.all(tool=self.name)

            for domain in domains:
                targets.append({"domain": domain.domain, "cidr": ""})
            for cidr in cidrs:
                targets.append({"domain": "", "cidr": cidr.cidr.split("/")[0]})

        if args.output_path[0] == "/":
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path[1:])
        else:
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path)

        if not os.path.exists(output_path):
            os.makedirs(output_path)

        for t in targets:
            t["output"] = os.path.join(output_path, t["domain"] + t["cidr"])

        return targets

    def build_cmd(self, args):

        if not args.tool_args:
            args.tool_args = ""
        cmd = (
            'bash -c "' + self.binary  # noqa: W503
            + " {domain}{cidr} "  # noqa: W503
            + args.tool_args  # noqa: W503
            + '> {output}" '  # noqa: W503
        )

        return cmd

    def process_output(self, cmds):

        display("Importing data to database")

        for cmd in cmds:
            if cmd["cidr"]:
                _, cidr = self.ScopeCidr.find_or_create(cidr=cmd["cidr"])
                cidr.meta["whois"] = open(cmd["output"]).read()
                display(cidr.meta["whois"])
                cidr.update()

            elif cmd["domain"]:
                _, domain = self.BaseDomain.find_or_create(
                    domain=cmd["domain"])
                domain.meta["whois"] = open(cmd["output"]).read()
                display(domain.meta["whois"])
                domain.update()

        self.BaseDomain.commit()
Beispiel #6
0
class Module(ModuleTemplate):

    name = "LinkedInt"
    binary_name = "linkedint.py"

    def __init__(self, db):
        self.db = db
        self.BaseDomain = BaseDomainRepository(db, self.name)
        self.User = UserRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()

        self.options.add_argument(
            "-b",
            "--binary",
            help="Path to binary for LinkedInt",
            default=self.binary_name,
        )
        self.options.add_argument("-d",
                                  "--domain",
                                  help="Domain to add onto email")
        self.options.add_argument("-c",
                                  "--company_id",
                                  help="Company ID to search")
        self.options.add_argument("-C",
                                  "--restrict",
                                  help="Restrict to company filter",
                                  action="store_true")
        self.options.add_argument(
            "-e",
            "--email_format",
            help=
            "Format for emails: auto,full,firstlast,firstmlast,flast,first.last,fmlast,lastfirst, default is auto",
            default="auto",
        )
        self.options.add_argument("-k",
                                  "--keywords",
                                  help="Keywords to search for")
        self.options.add_argument(
            "-o",
            "--output_path",
            help=
            "Path which will contain program output (relative to base_path in config",
            default=self.name,
        )
        self.options.add_argument(
            "-s",
            "--rescan",
            help="Rescan domains that have already been scanned",
            action="store_true",
        )
        self.options.add_argument(
            "--smart_shuffle",
            help=
            "Provide a list of keywords. The tool will run once with all of the keywords, then run again excluding all of the keywords. This is useful for bypassing the 1k limit. Keywords must be comma separated.",
        )
        self.options.add_argument(
            "--top",
            help="Use the top X keywords from the job titles for smart shuffle"
        )
        self.options.add_argument(
            "--auto_keyword",
            help=
            "Generate a list of keywords from titles already discovered, and search repeatedly using the top x number of results (specified with --top).",
            action="store_true")

    def run(self, args):
        # pdb.set_trace()
        if not args.binary:
            self.binary = which.run("LinkedInt.py")

        else:
            self.binary = which.run(args.binary)

        if not self.binary:
            display_error(
                "LinkedInt binary not found. Please explicitly provide path with --binary"
            )

        if args.domain:
            created, domain = self.BaseDomain.find_or_create(
                domain=args.domain)
            if args.top:
                titles = [
                    user.job_title.split(" at ")[0] for user in domain.users
                    if user.job_title
                ]
                words = []
                for t in titles:
                    words += [w.lower() for w in get_words(t)]

                word_count = Counter(words).most_common()

                display("Using the top %s words:" % args.top)
                res = []
                for w in word_count[:int(args.top)]:
                    display("\t{}\t{}".format(w[0], w[1]))
                    res.append(w[0])

                # pdb.set_trace()
                args.smart_shuffle = ",".join(res)

            if args.auto_keyword:
                if not args.top:
                    display_error(
                        "You must specify the top number of keywords using --top"
                    )
                else:
                    if os.path.isfile('/tmp/armory_linkedinsearchqueries'):
                        blacklist = open('/tmp/armory_linkedinsearchqueries'
                                         ).read().split('\n')
                    else:
                        blacklist = []
                    bfile = open('/tmp/armory_linkedinsearchqueries', 'a')
                    for w in args.smart_shuffle.split(','):

                        if w not in blacklist:

                            args.keywords = w
                            self.process_domain(domain, args)
                            self.BaseDomain.commit()
                            bfile.write('{}\n'.format(w))
                        else:
                            display(
                                "Skipped {} due to it already being searched.".
                                format(w))
                    bfile.close()
            elif args.smart_shuffle:
                args.keywords = " OR ".join(
                    ['"{}"'.format(i) for i in args.smart_shuffle.split(",")])
                self.process_domain(domain, args)
                self.BaseDomain.commit()
                args.keywords = " AND ".join(
                    ['-"{}"'.format(i) for i in args.smart_shuffle.split(",")])
                self.process_domain(domain, args)
                self.BaseDomain.commit()
            else:
                self.process_domain(domain, args)
                self.BaseDomain.commit()

            self.BaseDomain.commit()

    def process_domain(self, domain_obj, args):

        domain = domain_obj.domain

        if args.output_path[0] == "/":
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path[1:])
        else:
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path)

        if not os.path.exists(output_path):
            os.makedirs(output_path)

        output_path = os.path.join(output_path,
                                   "%s-linkedint" % domain.replace(".", "_"))

        command_args = " -o %s" % output_path

        command_args += " -e %s" % domain
        if args.keywords:
            command_args += " -u '%s'" % args.keywords

        if args.company_id:
            command_args += " -i %s " % args.company_id

        if args.restrict:
            command_args += " -c "
        # if args.threads:
        #     command_args += " -t " + args.threads
        if args.email_format:
            command_args += " -f " + args.email_format

        current_dir = os.getcwd()

        new_dir = "/".join(self.binary.split("/")[:-1])

        os.chdir(new_dir)

        cmd = shlex.split("python2 " + self.binary + command_args)
        print("Executing: %s" % " ".join(cmd))

        subprocess.Popen(cmd).wait()

        os.chdir(current_dir)
        count = 0
        with open(output_path + ".csv") as csvfile:
            csvreader = csv.reader(csvfile, delimiter=",", quotechar='"')

            for row in csvreader:
                count += 1

                created, user = self.User.find_or_create(
                    email=remove_binary(row[3]))

                user.first_name = remove_binary(row[0])
                user.last_name = remove_binary(row[1]).split(',')[0]
                user.job_title = remove_binary(row[4])
                user.location = remove_binary(row[5])

                if created:
                    user.domain = domain_obj

                    print("New user: %s %s" %
                          (remove_binary(row[0]), remove_binary(row[1])))

                user.update()

        print("%s found and imported" % count)
        self.User.commit()
Beispiel #7
0
class Module(ToolTemplate):

    name = "TheHarvester"
    binary_name = "theharvester"

    def __init__(self, db):
        self.db = db
        self.BaseDomain = BaseDomainRepository(db, self.name)
        self.Domain = DomainRepository(db, self.name)
        self.User = UserRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()

        self.options.add_argument("-d", "--domain", help="Domain to harvest")
        self.options.add_argument("-f",
                                  "--file",
                                  help="Import domains from file")
        self.options.add_argument(
            "-i",
            "--import_database",
            help="Import domains from database",
            action="store_true",
        )
        self.options.add_argument(
            "-s",
            "--rescan",
            help="Rescan domains that have already been scanned",
            action="store_true",
        )

    def get_targets(self, args):

        targets = []
        if args.domain:

            targets.append({"target": args.domain})

        elif args.file:
            domains = open(args.file).read().split("\n")
            for d in domains:
                if d:
                    created, domain = self.BaseDomain.find_or_create(domain=d)
                    targets.append({"target": domain.domain})

        elif args.import_database:
            if args.rescan:
                domains = self.BaseDomain.all(scope_type="passive")
            else:
                domains = self.BaseDomain.all(tool=self.name,
                                              scope_type="passive")
            for d in domains:

                targets.append({"target": d.domain})

        if args.output_path[0] == "/":
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path[1:])
        else:
            output_path = os.path.join(
                self.base_config["PROJECT"]["base_path"], args.output_path)

        if not os.path.exists(output_path):
            os.makedirs(output_path)

        for t in targets:
            t["output"] = os.path.join(
                output_path, "%s-theharvester" % t["target"].replace(".", "_"))

        return targets

    def build_cmd(self, args):

        cmd = self.binary + " -f {output} -b default -d {target} "

        if args.tool_args:
            cmd += args.tool_args

        return cmd

    def process_output(self, cmds):

        for cmd in cmds:

            try:
                data = xmltodict.parse(open(cmd["output"] + ".xml").read())
            except Exception as e:
                # display_error("Error with {}: {}".format(cmd["output"], e))
                data = None

            if data:

                if data["theHarvester"].get("email", False):
                    if type(data["theHarvester"]["email"]) == list:
                        emails = data["theHarvester"]["email"]
                    else:
                        emails = [data["theHarvester"]["email"]]
                    for e in emails:
                        display("Processing E-mail: {}".format(e))
                        created, user = self.User.find_or_create(email=e)

                        _, domain = self.BaseDomain.find_or_create(
                            domain=e.split("@")[1])
                        user.domain = domain
                        user.update()

                        if created:
                            display_new("New email: %s" % e)
                if data["theHarvester"].get("host", False):
                    if type(data["theHarvester"]["host"]) == list:
                        hosts = data["theHarvester"]["host"]
                    else:
                        hosts = [data["theHarvester"]["host"]]

                    for d in hosts:

                        created, domain = self.Domain.find_or_create(
                            domain=d["hostname"])

                if data["theHarvester"].get("vhost", False):
                    if type(data["theHarvester"]["vhost"]) == list:
                        hosts = data["theHarvester"]["vhost"]
                    else:
                        hosts = [data["theHarvester"]["vhost"]]

                    for d in hosts:

                        created, domain = self.Domain.find_or_create(
                            domain=d["hostname"])
        self.BaseDomain.commit()
Beispiel #8
0
class Module(ToolTemplate):
    '''
    This module uses the Ruby version of Aquatone. You can usually install it with "gem install aquatone"

    '''
    name = "aquatone-discover"
    binary_name = "aquatone-discover"

    def __init__(self, db):
        self.db = db
        self.Domain = DomainRepository(db, self.name)
        self.BaseDomain = BaseDomainRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()

        self.options.add_argument("-d",
                                  "--domain",
                                  help="Target domain for aquatone")
        self.options.add_argument("-f",
                                  "--file",
                                  help="Import domains from file")
        self.options.add_argument(
            "-i",
            "--import_database",
            help="Import domains from database",
            action="store_true",
        )
        self.options.add_argument(
            "-r",
            "--rescan",
            help="Run aquatone on hosts that have already been processed.",
            action="store_true",
        )
        self.options.set_defaults(timeout=None)

    def get_targets(self, args):
        """
        This module is used to build out a target list and output file list, depending on the arguments. Should return a
        list in the format [(target, output), (target, output), etc, etc]
        """
        targets = []

        if args.domain:
            created, domain = self.BaseDomain.find_or_create(
                domain=args.domain)
            targets.append(domain.domain)

        elif args.file:
            domainsFile = open(args.file).read().split("\n")
            for d in domainsFile:
                if d:
                    created, domain = self.BaseDomain.find_or_create(domain=d)
                    targets.append(domain.domain)

        elif args.import_database:
            if args.rescan:
                all_domains = self.BaseDomain.all(scope_type="passive")
            else:
                all_domains = self.BaseDomain.all(tool=self.name,
                                                  scope_type="passive")
            for d in all_domains:
                targets.append(d.domain)

        else:
            print("You need to supply domain(s).")

        output_path = os.path.join(self.base_config["PROJECT"]["base_path"],
                                   "output", "aquatone")

        if not os.path.exists(output_path):
            os.makedirs(output_path)

        res = []
        for t in targets:
            res.append({
                "target": t,
                "output": "{}/{}/hosts.json".format(output_path, t)
            })

        return res

    def build_cmd(self, args):
        """
        Create the actual command that will be executed. Use {target} and {output} as placeholders.
        """
        cmd = self.binary + " -d {target} "

        if args.tool_args:
            cmd += args.tool_args

        return cmd

    def pre_run(self, args):
        output_path = os.path.join(self.base_config["PROJECT"]["base_path"],
                                   "output")

        self.orig_home = os.environ["HOME"]

        os.environ["HOME"] = output_path

    def process_output(self, cmds):
        """
        Process the output generated by the earlier commands.
        """
        for cmd in cmds:
            try:
                data2 = json.loads(open(cmd["output"]).read())

                for sub, ip in data2.items():
                    created = False
                    new_domain = sub.lower()

                    if new_domain:
                        created, subdomain = self.Domain.find_or_create(
                            domain=new_domain)
            except Exception as e:
                display_error("Couldn't find file: {}".format(cmd["output"]))
        self.Domain.commit()

    def post_run(self, args):

        os.environ["HOME"] = self.orig_home