Esempio n. 1
0
class Report(ReportTemplate):
    """
    This report displays all of the certificates
    from https boxes.
    """

    markdown = ["###", "`"]

    name = "CertReport"

    def __init__(self, db):
        self.Port = PortRepository(db)

    def set_options(self):
        super(Report, self).set_options()
        self.options.add_argument("-t", "--tool", help="Source tool")

    def run(self, args):

        results = []
        services = self.Port.all(service_name="https")
        certs = {}
        for s in services:

            if ((args.scope == "passive" and s.ip_address.passive_scope)
                    or (args.scope == "active" and s.ip_address.in_scope
                        )  # noqa: W503
                    or (args.scope == "all")  # noqa: W503
                ):
                if s.cert:

                    cert = s.cert.split("-----")[0]
                    # pdb.set_trace()
                    if not certs.get(cert, False):
                        certs[cert] = []
                    if s.ip_address.domains:
                        certs[cert].append(s.ip_address.domains[0].domain +
                                           ":" + str(s.port_number))
                    else:
                        certs[cert].append(s.ip_address.ip_address + ":" +
                                           str(s.port_number))

        for k in certs.keys():
            results.append(", ".join(sorted(list(set(certs[k])))))
            for l in k.split("\n"):
                results.append("\t" + l)

        self.process_output(results, args)
Esempio n. 2
0
class Module(ToolTemplate):
    """
    Module for running nmap. Make sure to pass all nmap-specific arguments at the end, after --tool_args

    """

    name = "Nmap"
    binary_name = "nmap"

    def __init__(self, db):
        self.db = db
        self.BaseDomain = BaseDomainRepository(db, self.name)
        self.Domain = DomainRepository(db, self.name)
        self.IPAddress = IPRepository(db, self.name)
        self.Port = PortRepository(db, self.name)

        self.Vulnerability = VulnRepository(db, self.name)
        self.CVE = CVERepository(db, self.name)
        self.ScopeCIDR = ScopeCIDRRepository(db, self.name)

    def set_options(self):
        super(Module, self).set_options()
        self.options.add_argument(
            "--hosts",
            help=
            "Things to scan separated by a space. DO NOT USE QUOTES OR COMMAS",
            nargs="+",
        )
        self.options.add_argument("--hosts_file", help="File containing hosts")
        self.options.add_argument(
            "-i",
            "--hosts_database",
            help="Use unscanned hosts from the database",
            action="store_true",
        )
        self.options.add_argument("--rescan",
                                  help="Overwrite files without asking",
                                  action="store_true")
        self.options.add_argument(
            "--filename",
            help="Output filename. By default will use the current timestamp.",
        )
        self.options.add_argument(
            "--ssl_cert_mode",
            help=
            "Scan only SSL enabled hosts to collect SSL certs (and domain names)",
            action="store_true",
        )
        self.options.add_argument(
            "--filter_ports",
            help=
            "Comma separated list of protoPort to filter out of results. Useful if firewall returns specific ports open on every host. Ex: t80,u5060"
        )

        self.options.set_defaults(timeout=None)
        self.options.add_argument("--import_file",
                                  help="Import results from an Nmap XML file.")

    def get_targets(self, args):

        self.args = args
        if args.import_file:
            args.no_binary = True
            return [{"target": "", "output": args.import_file}]

        targets = []

        if args.hosts:

            if type(args.hosts) == list:
                for h in args.hosts:
                    if check_if_ip(h):
                        targets.append(h)
                    else:
                        created, domain = self.Domain.find_or_create(domain=h)
                        targets += [i.ip_address for i in domain.ip_addresses]

            else:
                if check_if_ip(h):
                    targets.append(h)
                else:
                    created, domain = self.Domain.find_or_create(domain=h)
                    targets += [i.ip_address for i in domain.ip_addresses]

        if args.hosts_database:
            if args.rescan:
                targets += [
                    h.ip_address
                    for h in self.IPAddress.all(scope_type="active")
                ]
                targets += [h.cidr for h in self.ScopeCIDR.all()]
            else:
                targets += [
                    h.ip_address
                    for h in self.IPAddress.all(tool=self.name,
                                                scope_type="active")
                ]
                targets += [h.cidr for h in self.ScopeCIDR.all(tool=self.name)]

        if args.hosts_file:
            for h in [
                    l for l in open(args.hosts_file).read().split("\n") if l
            ]:
                if check_if_ip(h):
                    targets.append(h)
                else:
                    created, domain = self.Domain.find_or_create(domain=h)
                    targets += [i.ip_address for i in domain.ip_addresses]

        data = []
        if args.ssl_cert_mode:
            ports = self.Port.all(service_name='https')

            data = list(set([i.ip_address.ip_address for i in ports]))

            port_numbers = list(set([str(i.port_number) for i in ports]))
            args.tool_args += " -sV -p {} --script ssl-cert ".format(
                ','.join(port_numbers))

        else:

            # Here we should deduplicate the targets, and ensure that we don't have IPs listed that also exist inside CIDRs
            for t in targets:
                ips = [str(i) for i in list(IPNetwork(t))]
                data += ips

        _, file_name = tempfile.mkstemp()
        open(file_name, "w").write("\n".join(list(set(data))))

        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)

        if args.filename:
            output_path = os.path.join(self.path, args.filename)
        else:
            output_path = os.path.join(
                self.path,
                "nmap-scan-%s.xml" %
                datetime.datetime.now().strftime("%Y.%m.%d-%H.%M.%S"),
            )

        return [{"target": file_name, "output": output_path}]

    def build_cmd(self, args):

        command = "sudo " + self.binary + " -oX {output} -iL {target} "

        if args.tool_args:
            command += args.tool_args

        return command

    def process_output(self, cmds):

        self.import_nmap(cmds[0]["output"])
        if cmds[0]["target"]:
            os.unlink(cmds[0]["target"])

    def parseHeaders(self, httpHeaders):
        bsHeaders = [
            "Pragma",
            "Expires",
            "Date",
            "Transfer-Encoding",
            "Connection",
            "X-Content-Type-Options",
            "Cache-Control",
            "X-Frame-Options",
            "Content-Type",
            "Content-Length",
            "(Request type",
        ]
        keepHeaders = {}
        for i in range(0, len(httpHeaders)):
            if httpHeaders[i].strip() != "" and httpHeaders[i].split(
                    ":")[0].strip() not in " ".join(bsHeaders):
                hName = httpHeaders[i].split(":")[0].strip()
                hValue = "".join(httpHeaders[i].split(":")[1:]).strip()
                keepHeaders[hName] = hValue

        if keepHeaders == {}:
            keepHeaders = ""

        return keepHeaders

    def import_nmap(
            self,
            filename):  # domains={}, ips={}, rejects=[] == temp while no db
        nFile = filename
        # pdb.set_trace()
        try:
            tree = ET.parse(nFile)
            root = tree.getroot()
            hosts = root.findall("host")

        except Exception as e:
            print("Error: {}" % e)
            print(nFile + " doesn't exist somehow...skipping")
            return

        for host in hosts:
            hostIP = host.find("address").get("addr")

            created, ip = self.IPAddress.find_or_create(ip_address=hostIP)

            for hostname in host.findall("hostnames/hostname"):
                hostname = hostname.get("name")
                hostname = hostname.lower().replace("www.", "")

                # reHostname = re.search(
                #     r"\d{1,3}\-\d{1,3}\-\d{1,3}\-\d{1,3}", hostname
                # )  # attempt to not get PTR record
                # if not reHostname:

                created, domain = self.Domain.find_or_create(domain=hostname)
                if ip not in domain.ip_addresses:
                    domain.ip_addresses.append(ip)
                    domain.save()

            for port in host.findall("ports/port"):

                if port.find("state").get("state"):
                    portState = port.find("state").get("state")
                    hostPort = port.get("portid")
                    portProto = port.get("protocol")
                    # pdb.set_trace()
                    if not self.args.filter_ports or int(hostPort) not in [
                            int(p) for p in self.args.filter_ports.split(',')
                    ]:
                        created, db_port = self.Port.find_or_create(
                            port_number=hostPort,
                            status=portState,
                            proto=portProto,
                            ip_address=ip,
                        )

                        if port.find("service") is not None:
                            portName = port.find("service").get("name")
                            if portName == "http" and hostPort == "443":
                                portName = "https"
                        else:
                            portName = "Unknown"

                        if created:
                            db_port.service_name = portName
                        info = db_port.info
                        if not info:
                            info = {}

                        for script in port.findall(
                                "script"):  # just getting commonName from cert
                            if script.get("id") == "ssl-cert":
                                db_port.cert = script.get("output")
                                cert_domains = self.get_domains_from_cert(
                                    script.get("output"))

                                for hostname in cert_domains:
                                    hostname = hostname.lower().replace(
                                        "www.", "")
                                    created, domain = self.Domain.find_or_create(
                                        domain=hostname)
                                    if created:
                                        print("New domain found: %s" %
                                              hostname)

                            elif script.get("id") == "vulners":
                                print("Gathering vuln info for {} : {}/{}\n".
                                      format(hostIP, portProto, hostPort))
                                self.parseVulners(script.get("output"),
                                                  db_port)

                            elif script.get("id") == "banner":
                                info["banner"] = script.get("output")

                            elif script.get("id") == "http-headers":

                                httpHeaders = script.get("output")
                                httpHeaders = httpHeaders.strip().split("\n")
                                keepHeaders = self.parseHeaders(httpHeaders)
                                info["http-headers"] = keepHeaders

                            elif script.get("id") == "http-auth":
                                info["http-auth"] = script.get("output")

                            elif script.get("id") == "http-title":
                                info["http-title"] = script.get("output")

                        db_port.info = info
                        db_port.save()

            self.IPAddress.commit()

    def parseVulners(self, scriptOutput, db_port):
        urls = re.findall(r"(https://vulners.com/cve/CVE-\d*-\d*)",
                          scriptOutput)
        for url in urls:
            vuln_refs = []
            exploitable = False
            cve = url.split("/cve/")[1]
            vulners = requests.get("https://vulners.com/cve/%s" % cve).text
            exploitdb = re.findall(
                r"https://www.exploit-db.com/exploits/\d{,7}", vulners)
            for edb in exploitdb:
                exploitable = True

                if edb.split("/exploits/")[1] not in vuln_refs:
                    vuln_refs.append(edb.split("/exploits/")[1])

            if not self.CVE.find(name=cve):
                # print "Gathering CVE info for", cve
                try:
                    res = json.loads(
                        requests.get("http://cve.circl.lu/api/cve/%s" %
                                     cve).text)
                    cveDescription = res["summary"]
                    cvss = float(res["cvss"])
                    findingName = res["oval"][0]["title"]
                    if int(cvss) <= 3:
                        severity = 1

                    elif (int(cvss) / 2) == 5:
                        severity = 4

                    else:
                        severity = int(cvss) / 2

                    if not self.Vulnerability.find(name=findingName):
                        # print "Creating", findingName
                        created, db_vuln = self.Vulnerability.find_or_create(
                            name=findingName,
                            severity=severity,
                            description=cveDescription,
                        )
                        db_vuln.ports.append(db_port)
                        db_vuln.exploitable = exploitable
                        if vuln_refs:
                            db_vuln.exploit_reference = {"edb-id": vuln_refs}
                            db_vuln.save()

                    else:
                        # print "modifying",findingName
                        db_vuln = self.Vulnerability.find(name=findingName)
                        db_vuln.ports.append(db_port)
                        db_vuln.exploitable = exploitable

                        if vuln_refs:
                            db_vuln.exploitable = exploitable
                            if db_vuln.exploit_reference is not None:
                                if "edb-id" in db_vuln.exploit_reference:
                                    for ref in vuln_refs:
                                        if (ref not in db_vuln.
                                                exploit_reference["edb-id"]):
                                            db_vuln.exploit_reference[
                                                "edb-id"].append(ref)

                                else:
                                    db_vuln.exploit_reference[
                                        "edb-id"] = vuln_refs
                            else:
                                db_vuln.exploit_reference = {
                                    "edb-id": vuln_refs
                                }

                        db_vuln.save()

                    if not self.CVE.find(name=cve):
                        created, db_cve = self.CVE.find_or_create(
                            name=cve,
                            description=cveDescription,
                            temporal_score=cvss)
                        db_cve.vulnerabilities.append(db_vuln)
                        db_cve.save()

                    else:
                        db_cve = self.CVE.find(name=cve)
                        db_cve.vulnerabilities.append(db_vuln)
                        db_cve.save()

                    self.Vulnerability.commit()
                    self.CVE.commit()
                except Exception:
                    print(
                        "something went wrong with the vuln/cve info gathering"
                    )
                    if vulners:
                        print(
                            "Vulners report was found but no exploit-db was discovered"
                        )
                        # "Affected vulners items"
                        # print vulners
                    print("Affected CVE")
                    print(cve)
                    pass

            else:
                db_cve = self.CVE.find(name=cve)
                for db_vulns in db_cve.vulnerabilities:
                    if db_port not in db_vulns.ports:
                        db_vulns.ports.append(db_port)
        return

    def get_domains_from_cert(self, cert):
        # Shamelessly lifted regex from stack overflow
        regex = r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}"

        domains = list(
            set([d for d in re.findall(regex, cert) if "*" not in d]))

        return domains
Esempio n. 3
0
class Module(ToolTemplate):

    name = "Hydra"
    binary_name = "hydra"

    def __init__(self, db):
        self.db = db
        self.Domain = DomainRepository(db, self.name)
        self.IPAddress = IPRepository(db, self.name)
        self.Port = PortRepository(db, self.name)

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

        self.options.add_argument("-ho",
                                  "--host",
                                  help="Host to scan (service://host:port)")
        self.options.add_argument("-hw",
                                  "--host_wordlist",
                                  help="Wordlist to use for one off host")
        self.options.add_argument("-f",
                                  "--file",
                                  help="Import hosts from file")
        self.options.add_argument(
            "-s",
            "--rescan",
            help="Rescan domains that have already been scanned",
            action="store_true",
        )

        self.options.add_argument(
            "--scan_defaults",
            help="Pull hosts out of database and scan default passwords",
            action="store_true",
        )

        self.options.add_argument("--ftp_wordlist",
                                  help="Wordlist for FTP services")
        self.options.add_argument("--telnet_wordlist",
                                  help="Wordlist for Telnet")
        self.options.add_argument("--email_wordlist",
                                  help="Wordlist for email (smtp, pop3, imap)")
        self.options.add_argument("--ssh_wordlist", help="Wordlist for SSH")
        self.options.add_argument("--vnc_wordlist", help="Wordlist for VNC")

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

        if args.host:
            service, hp = args.host.split("://")
            host, port = hp.split(":")[-2:]
            targets.append({
                "target": host,
                "service": service,
                "port": port,
                "wordlist": args.host_wordlist,
            })

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

        elif args.scan_defaults:
            lists = {}
            if args.ftp_wordlist:
                for p in ["ftps", "ftp"]:
                    lists[args.ftp_wordlist] = [
                        s
                        for s in self.Port.all(tool=self.name, service_name=p)
                    ]

            if args.telnet_wordlist:
                for p in ["telnet"]:
                    lists[args.telnet_wordlist] = [
                        s
                        for s in self.Port.all(tool=self.name, service_name=p)
                    ]

            if args.email_wordlist:
                for p in ["smtps", "smtp", "pop3", "pop3s", "imap", "imaps"]:
                    lists[args.email_wordlist] = [
                        s
                        for s in self.Port.all(tool=self.name, service_name=p)
                    ]

            if args.ssh_wordlist:
                for p in ["ssh"]:
                    lists[args.ssh_wordlist] = [
                        s
                        for s in self.Port.all(tool=self.name, service_name=p)
                    ]

            if args.vnc_wordlist:
                for p in ["vnc"]:
                    lists[args.vnc_wordlist] = [
                        s
                        for s in self.Port.all(tool=self.name, service_name=p)
                    ]

            for k in lists.keys():
                for s in lists[k]:

                    port_number = s.port_number
                    ip_address = s.ip_address.ip_address
                    name = s.service_name

                    targets.append({
                        "service": name,
                        "target": ip_address,
                        "port": port_number,
                        "wordlist": k,
                    })

        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, "{}-{}.txt".format(t["target"], t["port"]))

        return targets

    def build_cmd(self, args):

        cmd = self.binary + " -o {output} -C {wordlist} "
        if args.tool_args:
            cmd += args.tool_args

        cmd += " {service}://{target}:{port} "

        return cmd
Esempio n. 4
0
class Module(ToolTemplate):

    name = "SSLScan"
    binary_name = "sslscan"

    def __init__(self, db):
        self.db = db
        self.Domain = DomainRepository(db, self.name)
        self.IPAddress = IPRepository(db, self.name)
        self.Port = PortRepository(db, self.name)

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

        self.options.add_argument("--host", help="Host to scan (host:port)")
        self.options.add_argument("-f",
                                  "--file",
                                  help="Import hosts from file")
        self.options.add_argument(
            "-i",
            "--import_database",
            help="Import hosts 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.host:
            if "http" in args.host:
                if args.host.count(":") == 2:
                    service, host, port = args.host.split(":")
                else:
                    service, host = args.host.split(":")
                    port = "443"
                host = host.split("/")[-1]
                targets.append({
                    "option": "",
                    "target": "{}:{}".format(host, port)
                })
            else:
                targets.append({"option": "", "target": args.host})

        if args.file:
            hosts = open(args.file).read().split("\n")
            for h in hosts:
                if h:
                    if "http" in h:
                        if h.count(":") == 2:
                            service, host, port = h.split(":")
                        else:
                            service, host = h.split(":")
                            port = "443"
                        host = host.split("/")[-1]
                        targets.append({
                            "option": "",
                            "target": "{}:{}".format(host, port)
                        })
                    else:
                        targets.append({"option": "", "target": h})

        if args.import_database:

            hosts = []
            svc = []

            if args.rescan:

                for p in [
                        "https", "ftps", "imaps", "sip-tls", "imqtunnels",
                        "smtps"
                ]:
                    svc += [
                        (s, "")
                        for s in self.Port.all(service_name=p, status="open")
                        if s.ip_address.in_scope
                    ]
                for p in [
                        "ftp",
                        "imap",
                        "irc",
                        "ldap",
                        "pop3",
                        "smtp",
                        "mysql",
                        "xmpp",
                        "psql",
                ]:
                    svc += [
                        (s, "--starttls-%s" % p)
                        for s in self.Port.all(service_name=p, status="open")
                        if s.ip_address.in_scope
                    ]
            else:
                for p in [
                        "https", "ftps", "imaps", "sip-tls", "imqtunnels",
                        "smtps"
                ]:
                    svc += [(s, "") for s in self.Port.all(
                        tool=self.name, service_name=p, status="open")
                            if s.ip_address.in_scope]
                for p in [
                        "ftp",
                        "imap",
                        "irc",
                        "ldap",
                        "pop3",
                        "smtp",
                        "mysql",
                        "xmpp",
                        "psql",
                ]:
                    svc += [(s, "--starttls-%s" % p) for s in self.Port.all(
                        tool=self.name, service_name=p, status="open")
                            if s.ip_address.in_scope]

            for s, option in svc:

                port_number = s.port_number
                ip_address = s.ip_address.ip_address

                targets.append({
                    "target": "%s:%s" % (ip_address, port_number),
                    "option": option
                })

                for d in s.ip_address.domains:
                    targets.append({
                        "target": "%s:%s" % (d.domain, port_number),
                        "option": option
                    })

        for t in targets:
            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,
                "{}-sslscan.xml".format(t["target"].replace(":", "_")))
            t["output"] = output_path

        return targets

    def build_cmd(self, args):

        cmd = self.binary + " --xml={output} {option} {target} "

        if args.tool_args:
            cmd += args.tool_args

        return cmd
Esempio n. 5
0
class Module(ModuleTemplate):

    name = "HeaderScanner"

    def __init__(self, db):
        self.db = db
        self.Port = PortRepository(db, self.name)
        self.Domain = DomainRepository(db, self.name)
        self.IPAddress = IPRepository(db, self.name)

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

        self.options.add_argument("-t",
                                  "--timeout",
                                  help="Connection timeout (default 5)",
                                  default="5")
        self.options.add_argument("-u", "--url", help="URL to get headers")
        self.options.add_argument("--file", help="Import URLs from file")
        self.options.add_argument(
            "-i",
            "--import_db",
            help="Import URLs from the database",
            action="store_true",
        )
        self.options.add_argument("-th",
                                  "--threads",
                                  help="Number of threads to run",
                                  default="10")
        self.options.add_argument("--rescan",
                                  help="Rescan URLs already processed",
                                  action="store_true")

    def run(self, args):
        data = []
        if args.url:
            service = args.url.split(":")[0]
            host = args.url.split("/")[2]

            if args.url.count(":") == 2:
                port = args.url.split(":")[2].split("/")[0]
            elif service == "http":
                port = "80"
            elif service == "https":
                port = "443"
            else:
                display_error(
                    "Could not figure out port number for url: {}".format(
                        args.url))
                sys.exit(1)

            if check_if_ip(host):
                created, ip = self.IPAddress.find_or_create(ip_address=host)
            else:

                created, domain = self.Domain.find_or_create(domain=host)
                ip = domain.ip_addresses[0]

            created, service_id = self.Port.find_or_create(ip_address=ip,
                                                           port_number=port)
            service_id.service_name = service

            data.append([service_id.id, [args.url], args.timeout])

        if args.file:
            url = open(args.file).read().split("\n")
            for u in url:
                if u:
                    service = u.split(":")[0]
                    host = u.split("/")[2]

                    if u.count(":") == 2:
                        port = u.split(":")[2].split("/")[0]
                    elif service == "http":
                        port = "80"
                    elif service == "https":
                        port = "443"
                    else:
                        display_error(
                            "Could not figure out port number for url: {}".
                            format(args.url))
                        sys.exit(1)

                    if check_if_ip(host):
                        created, ip = self.IPAddress.find_or_create(
                            ip_address=host)
                    else:

                        created, domain = self.Domain.find_or_create(
                            domain=host)
                        ip = domain.ip_addresses[0]

                    created, service_id = self.Port.find_or_create(
                        ip_address=ip, port_number=port)
                    service_id.service_name = service

                    data.append([service_id.id, [u], args.timeout])

        if args.import_db:

            if args.rescan:
                svc = self.Port.all(service_name="http")
                svc += self.Port.all(service_name="https")
            else:
                svc = self.Port.all(service_name="http", tool=self.name)
                svc += self.Port.all(service_name="https", tool=self.name)

            for s in svc:
                if s.ip_address.in_scope:
                    urls = [
                        "%s://%s:%s" % (s.service_name,
                                        s.ip_address.ip_address, s.port_number)
                    ]

                    for d in s.ip_address.domains:
                        urls.append("%s://%s:%s" %
                                    (s.service_name, d.domain, s.port_number))

                    data.append([s.id, urls, args.timeout])

        if data:
            pool = ThreadPool(int(args.threads))

            results = pool.map(process_urls, data)
            display_new("Adding headers to the database")
            for i, headers, cookies in results:
                created, svc = self.Port.find_or_create(id=i)

                svc.meta["headers"] = headers

                svc.meta["cookies"] = cookies
                svc.update()

            self.Port.commit()
Esempio n. 6
0
class Report(ReportTemplate):
    """
    This report displays all of the hosts sorted by service.
    """

    markdown = ["", "# ", "- "]

    name = ""

    def __init__(self, db):
        self.Ports = PortRepository(db)

    def run(self, args):
        # Cidrs = self.CIDR.

        ports = self.Ports.all()
        services = {}

        for p in ports:

            if (
                (args.scope == "active" and p.ip_address.in_scope)
                or (  # noqa: W503
                    args.scope == "passive" and p.ip_address.passive_scope
                )
                or (args.scope == "all")  # noqa: W503
                and p.status == "open"  # noqa: W503
            ):
                if not services.get(p.proto, False):
                    services[p.proto] = {}

                if not services[p.proto].get(p.port_number, False):
                    services[p.proto][p.port_number] = {}

                services[p.proto][p.port_number][p.ip_address.ip_address] = {
                    "domains": [d.domain for d in p.ip_address.domains],
                    "svc": p.service_name,
                }

        res = []

        for p in sorted(services):
            for s in sorted(services[p]):

                res.append("\tProtocol: {} Port: {}".format(p, s))
                res.append("\n")
                for ip in sorted(services[p][s].keys()):
                    if services[p][s][ip]["domains"]:
                        res.append(
                            "\t\t{} ({}): {}".format(
                                ip,
                                services[p][s][ip]["svc"],
                                ", ".join(services[p][s][ip]["domains"]),
                            )
                        )
                    else:
                        res.append(
                            "\t\t{} ({}) (No domain)".format(
                                ip, services[p][s][ip]["svc"]
                            )
                        )
                res.append("\n")

        self.process_output(res, args)