Пример #1
0
    def Parse(self, file_opened, **kwargs):
        """
        Parse a opened file to extract information
        Example file:
        10.0.0.1 - UNKNOWN - no connection - timeout
        10.0.0.2 - VULNERABLE - ?? - ????

        Args:
            file_opened: the open file
            kwargs: port("") and proto("") are valid
        Returns:
            a tuple with 4 values (All set to None if Parsing wrong file): 
                0. notes: notes to be inserted in tool giving direct info to pentester
                1. tags: a list of tags to be added to tool 
                2. lvl: the level of the command executed to assign to given targets
                3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
        """
        # 5. Parse the file has you want.
        # Here add a note to the tool's notes of each warnings issued by this testssl run.
        notes = ""
        tags = ["Neutral"]
        targets = {}
        for line in file_opened:
            # Auto Detect
            infos = line.split(" - ")
            if len(infos) < 3:
                return None, None, None, None
            if not Ip.isIp(infos[0]):
                return None, None, None, None
            if infos[1] not in ["UNKNOWN", "SAFE", "VULNERABLE"]:
                return None, None, None, None
            # Parse
            ip = line.split(" ")[0].strip()
            Ip().initialize(ip).addInDb()
            p_o = Port.fetchObject({"ip": ip, "port": kwargs.get(
                "port", None), "proto": kwargs.get("proto", None)})
            if p_o is not None:
                targets[str(p_o.getId())] = {"ip": ip, "port": kwargs.get(
                    "port", None), "proto": kwargs.get("proto", None)}
            if "VULNERABLE" in line:
                Defect().initialize(ip, kwargs.get("port", None), kwargs.get("proto", None), "Serveur vulnérable à BlueKeep",
                                    "Difficile", "Critique", "Critique", "N/A", ["Socle"], notes=notes, proofs=[]).addInDb()
                tags=["P0wned!"]
                if p_o is not None:
                    p_o.addTag("P0wned!")
                ip_o = Ip.fetchObject({"ip": ip})
                if ip_o is not None:
                    ip_o.addTag("P0wned!")
            elif "UNKNOWN" in line:
                tags = ["todo"]
            notes += line
        return notes, tags, "port", targets
Пример #2
0
 def getActions(self, toolmodel):
     """
     Summary: Add buttons to the tool view.
     Args:
         toolmodel : the tool model opened in the pollenisator client.
     Return:
         A dictionary with buttons text as key and function callback as value.
     """
     self.port_m = Port.fetchObject(
         {"ip": toolmodel.ip, "port": toolmodel.port, "proto": toolmodel.proto})
     if self.port_m is None:
         return {}
     return {"Open 200 in browser": self.openInBrowser}
Пример #3
0
 def openInBrowser(self, _event=None):
     """Callback of action  Open 200 in browser
     Open scanned host port in browser as tabs.
     Args:
         _event: not used but mandatory
     """
     port_m = Port.fetchObject({
         "ip": self.toolmodel.ip,
         "port": self.toolmodel.port,
         "proto": self.toolmodel.proto
     })
     if port_m is None:
         return
     url = port_m.infos.get("URL", None)
     if url is not None:
         webbrowser.open_new_tab(url)
Пример #4
0
 def Parse(self, file_opened, **_kwargs):
     """
     Parse a opened file to extract information
     Args:
         file_opened: the open file
         _kwargs: not used
     Returns:
         a tuple with 4 values (All set to None if Parsing wrong file): 
             0. notes: notes to be inserted in tool giving direct info to pentester
             1. tags: a list of tags to be added to tool 
             2. lvl: the level of the command executed to assign to given targets
             3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
     """
     tags = ["todo"]
     data = file_opened.read()
     notes = ""
     if data.strip() == "":
         return None, None, None, None
     else:
         hosts = parse_dirsearch_file(data)
         if not hosts.keys():
             return None, None, None, None
         targets = {}
         for host in hosts:
             Ip().initialize(host).addInDb()
             for port in hosts[host]:
                 port_o = Port()
                 port_o.initialize(host, port, "tcp",
                                   hosts[host][port]["service"])
                 res, iid = port_o.addInDb()
                 if not res:
                     port_o = Port.fetchObject({"_id": iid})
                 targets[str(port_o.getId())] = {
                     "ip": host, "port": port, "proto": "tcp"}
                 hosts[host][port]["paths"].sort(key=lambda x: int(x[0]))
                 results = "\n".join(hosts[host][port]["paths"])
                 notes += results
                 newInfos = {}
                 for statuscode in hosts[host][port]:
                     if isinstance(statuscode, int):
                         if hosts[host][port].get(statuscode, []):
                             newInfos["Dirsearch_"+str(statuscode)
                                      ] = hosts[host][port][statuscode]
                 newInfos["SSL"] = "True" if hosts[host][port]["service"] == "https" else "False"
                 port_o.updateInfos(newInfos)
     return notes, tags, "port", targets
Пример #5
0
 def openInBrowser(self, _event=None):
     """Callback of action  Open 200 in browser
     Open scanned host port in browser as tabs.
     Args:
         _event: not used but mandatory
     """
     port_m = Port.fetchObject({
         "ip": self.toolmodel.ip,
         "port": self.toolmodel.port,
         "proto": self.toolmodel.proto
     })
     if port_m is None:
         return
     ssl = port_m.infos.get("SSL", None)
     if ssl is not None:
         url = "https://" if ssl == "True" else "http://"
         url += port_m.ip + ":" + str(port_m.port) + "/"
         webbrowser.open_new_tab(url)
Пример #6
0
def editScopeIPs(hostsInfos):
    """
    Add all the ips and theirs ports found after parsing the file to the scope object in database.
    Args:
        hostsInfos: the dictionnary with ips as keys and a list of dictionnary containing ports informations as value.
    """
    # Check if any ip has been found.
    if hostsInfos is not None:
        for infos in hostsInfos:
            tags = []
            if infos.get("powned", False):
                tags.append("P0wned!")
            infosToAdd = {}
            OS = infos.get("OS", "")
            if OS != "":
                infosToAdd["OS"] = OS
            creds = infos.get("creds", "")
            if creds != "":
                infosToAdd["creds"] = creds
            powned = infos.get("powned", False)
            if powned:
                infosToAdd["powned"] = "True"
            ip_m = Ip().initialize(str(infos["ip"]))
            res, iid = ip_m.addInDb()
            if not res:
                ip_m = Ip.fetchObject({"_id": iid})
            infosToAdd["hostname"] = list(
                set(ip_m.infos.get("hostname", []) + [infos["hostname"]]))
            ip_m.notes = "hostname:" + \
                infos["hostname"] + "\n"+infos.get("OS", "")
            ip_m.tags = tags
            ip_m.update()
            port_m = Port().initialize(str(infos["ip"]), str(infos["port"]),
                                       "tcp", "netbios-ssn")
            res, iid = port_m.addInDb()
            if not res:
                port_m = Port.fetchObject({"_id": iid})
            port_m.updateInfos(infosToAdd)
            port_m.tags = tags
            port_m.update()
Пример #7
0
    def Parse(self, file_opened, **_kwargs):
        """
        Parse a opened file to extract information
        Args:
            file_opened: the open file
            _kwargs: not used
        Returns:
            a tuple with 4 values (All set to None if Parsing wrong file): 
                0. notes: notes to be inserted in tool giving direct info to pentester
                1. tags: a list of tags to be added to tool 
                2. lvl: the level of the command executed to assign to given targets
                3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
        """
        notes = file_opened.read()
        targets = {}
        tags = []
        if "| http-methods:" not in notes:
            return None, None, None, None
        host, port, proto, service, risky_methods, supported_methods = parse(
            notes)
        if host == "":
            return None, None, None, None
        Ip().initialize(host).addInDb()
        p_o = Port().initialize(host, port, proto, service)
        res, iid = p_o.addInDb()
        if not res:
            p_o = Port.fetchObject({"_id": iid})

        p_o.updateInfos({"Methods": ", ".join(supported_methods)})
        targets[str(p_o.getId())] = {"ip": host, "port": port, "proto": proto}
        if "TRACE" in risky_methods:
            Defect().initialize(host, port, proto, "Méthode TRACE activée", "Difficile", "Important", "Important",
                                 "N/A", ["Socle"], notes="TRACE detected", proofs=[]).addInDb()
            risky_methods.remove("TRACE")
        if len(risky_methods) > 0:
            notes = "RISKY HTTP METHODS ALLOWED : " + " ".join(risky_methods)
            tags = []
            tags.append("Interesting")
        return notes, tags, "port", targets
Пример #8
0
 def Parse(self, file_opened, **_kwargs):
     """
     Parse a opened file to extract information
     Args:
         file_opened: the open file
         _kwargs: not used
     Returns:
         a tuple with 4 values (All set to None if Parsing wrong file): 
             0. notes: notes to be inserted in tool giving direct info to pentester
             1. tags: a list of tags to be added to tool 
             2. lvl: the level of the command executed to assign to given targets
             3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
     """
     notes = ""
     tags = ["todo"]
     notes = file_opened.read()
     if not notes.startswith("[+] Finding open SMB ports...."):
         return None, None, None, None
     if "[!] Authentication error occured" in notes:
         targets = {}
     else:
         full_notes, interesting_files, targets = smbmap_format(notes)
         for target in targets:
             port_m = Port.fetchObject({
                 "ip": targets[target]["ip"],
                 "port": targets[target]["port"],
                 "proto": "tcp"
             })
             port_m.updateInfos(interesting_files)
         if interesting_files:
             tags = ["Interesting"]
         notes = "=====================Interesting files:=====================\n"
         for type_shared in interesting_files:
             notes = "\n" + type_shared + ":\n"
             notes += ("\n".join(interesting_files[type_shared])) + "\n"
         notes += "=====================Other files:=====================\n" + full_notes
     return notes, tags, "port", targets
Пример #9
0
 def Parse(self, file_opened, **_kwargs):
     """
     Parse a opened file to extract information
     Args:
         file_opened: the open file
         _kwargs: not used
     Returns:
         a tuple with 4 values (All set to None if Parsing wrong file): 
             0. notes: notes to be inserted in tool giving direct info to pentester
             1. tags: a list of tags to be added to tool 
             2. lvl: the level of the command executed to assign to given targets
             3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
     """
     tags = ["todo"]
     targets = {}
     notes = file_opened.read()
     if notes == "":
         return None, None, None, None
     if not notes.startswith("- Nikto v"):
         return None, None, None, None
     host, port, service, infos = parse_nikto_plain_text(notes)
     if host:
         if port:
             Ip().initialize(host).addInDb()
             p_o = Port().initialize(host, port, "tcp", service)
             res, iid = p_o.addInDb()
             if not res:
                 p_o = Port.fetchObject({"_id": iid})
             p_o.updateInfos({
                 "Nikto":
                 infos,
                 "SSL":
                 "True" if service == "https" else "False"
             })
             targets[str(iid)] = {"ip": host, "port": port, "proto": "tcp"}
     return notes, tags, "port", targets
Пример #10
0
def getIpPortsNmap(nmapFile):
    """
    Read the given nmap .nmap file results and return a dictionnary with ips and a list of their open ports.
        Args:
            nmapFile:  the path to the .nmap file generated by an nmap scan

        Returns:
            notes about inseted ip and ports
    """
    notes = ""
    countOpen = 0
    all_text = nmapFile.read().strip()
    lines = all_text.split("\n")
    if len(lines) <= 3:
        # print("Not enough lines to be nmap")
        return None
    if not lines[0].startswith("# Nmap"):
        # print("Not starting with # Nmap")
        return None
    if "scan initiated" not in lines[0]:
        # print("Not scan initiated on first line")
        return None
    if "# Nmap done at" not in lines[-1]:
        # print("Not # Nmap done at at the end : "+str(lines[-1]))
        return None
    ipCIDR_m = None
    ipDom_m = None
    for line in lines:
        # Search ip in file
        # match an ip
        ip = re.search(
            r"^Nmap scan report for (\S+)(?: \(((?:[0-9]{1,3}\.){3}[0-9]{1,3})\))?$",
            line)
        if ip is not None:  # regex match
            lastIp = [
                ip.group(1),
                ip.group(2) if ip.group(2) is not None else ""
            ]
            notes_ip = "ip:" + \
                str(lastIp[1]) if lastIp[1] != "" and lastIp[1] is not None else ""
            ipCIDR_m = Ip().initialize(str(lastIp[0]), notes=notes_ip)
            if lastIp[1].strip() != "" and lastIp[1] is not None:
                ipDom_m = Ip().initialize(str(lastIp[1]),
                                          notes="domain:" + str(lastIp[0]))

            else:
                ipDom_m = None
        if " open " in line:
            if ipCIDR_m is None:  # Probably a gnmap
                return None
            notes += line + "\n"
            # regex to find open ports in gnmap file
            port_search = re.search(
                r"^(\d+)\/(\S+)\s+open\s+(\S+)(?: +(.+))?$", line)
            if port_search is not None:
                port_number = str(port_search.group(1))
                proto = str(port_search.group(2))
                service = "unknown" if str(
                    port_search.group(3)) == "" else str(port_search.group(3))
                product = str(port_search.group(4))
                # a port unique key is its protocole/number.
                countOpen += 1
                validIps = []
                if ipCIDR_m is not None:
                    ipCIDR_m.addInDb()
                    validIps.append(ipCIDR_m.ip)
                    if ipDom_m is not None:
                        res, iid = ipDom_m.addInDb()
                        if not res:
                            ipDom_m = Ip.fetchObject({"_id": iid})
                        ipDom_m.updateInfos({
                            "hostname":
                            list(
                                set(
                                    list(ipDom_m.infos.get("hostname", [])) +
                                    [str(ipCIDR_m.ip)]))
                        })
                        validIps.append(ipDom_m.ip)
                for ipFound in validIps:
                    if ip == "":
                        continue
                    port_o = Port().initialize(ipFound, port_number, proto,
                                               service, product)
                    res_insert, iid = port_o.addInDb()
                    if not res_insert:
                        port_o = Port.fetchObject({"_id": iid})
                    port_o.service = service
                    port_o.update()

    notes = str(countOpen) + " open ports found\n" + notes
    return notes
Пример #11
0
 def Parse(self, file_opened, **_kwargs):
     """
     Parse a opened file to extract information
     Args:
         file_opened: the open file
         _kwargs: not used
     Returns:
         a tuple with 4 values (All set to None if Parsing wrong file): 
             0. notes: notes to be inserted in tool giving direct info to pentester
             1. tags: a list of tags to be added to tool 
             2. lvl: the level of the command executed to assign to given targets
             3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
     """
     notes = ""
     tags = []
     content = file_opened.read()
     targets = {}
     try:
         notes_json = json.loads(content)
     except json.decoder.JSONDecodeError:
         return None, None, None, None
     oneScanIsValid = False
     for scan in notes_json:
         try:
             if scan.get('ssh_scan_version', None) is None:
                 continue
             ips = [scan["hostname"], scan["ip"]]
             port = str(scan["port"])
             for ip in ips:
                 if ip.strip() == "":
                     continue
                 Ip().initialize(ip).addInDb()
                 port_o = Port().initialize(ip, port, "tcp", "ssh")
                 res, iid = port_o.addInDb()
                 if not res:
                     port_o = Port.fetchObject({"_id": iid})
                 notes = "\n".join(scan["compliance"].get(
                     "recommendations", []))
                 targets[str(port_o.getId())] = {
                     "ip": ip,
                     "port": port,
                     "proto": "tcp"
                 }
                 oneScanIsValid = True
                 if "nopassword" in scan["auth_methods"]:
                     tags = ["P0wned!"]
                 # Will not exit if port was not ssh
                 is_ok = scan["compliance"]["compliant"]
                 if str(is_ok) == "False":
                     port_o.updateInfos({"compliant": "False"})
                     port_o.updateInfos(
                         {"auth_methods": scan["auth_methods"]})
                     Defect().initialize(
                         ip,
                         port,
                         "tcp",
                         "Défauts d’implémentation de la configuration SSH",
                         "Très difficile",
                         "Majeur",
                         "Important",
                         "N/A", ["Socle"],
                         notes=notes,
                         proofs=[]).addInDb()
         except KeyError:
             continue
     if not oneScanIsValid:
         return None, None, None, None
     return notes, tags, "port", targets
Пример #12
0
 def Parse(self, file_opened, **_kwargs):
     """
     Parse a opened file to extract information
     Args:
         file_opened: the open file
         _kwargs: not used
     Returns:
         a tuple with 4 values (All set to None if Parsing wrong file): 
             0. notes: notes to be inserted in tool giving direct info to pentester
             1. tags: a list of tags to be added to tool 
             2. lvl: the level of the command executed to assign to given targets
             3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
     """
     tags = ["todo"]
     targets = {}
     notes = file_opened.read()
     if notes == "":
         return None, None, None, None
     try:
         data = json.loads(notes)
     except json.decoder.JSONDecodeError:
         return None, None, None, None
     regex_host = r"https?://([^\/]+)"
     oneValidWhatweb = False
     for website in data:
         keys = website.keys()
         expected_keys = [
             'target', 'http_status', 'request_config', 'plugins'
         ]
         all_keys = True
         for expected in expected_keys:
             if expected not in keys:
                 all_keys = False
                 break
         if not all_keys:
             continue
         host_port_groups = re.search(regex_host, website["target"])
         if host_port_groups is None:
             continue
         host_port = host_port_groups.group(1)
         service = "https" if "https://" in website["target"] else "http"
         if len(host_port.split(":")) == 2:
             port = host_port.split(":")[1]
             host = host_port.split(":")[0]
         else:
             host = host_port
             port = "443" if "https://" in website["target"] else "80"
         Ip().initialize(host).addInDb()
         p_o = Port().initialize(host, port, "tcp", service)
         inserted, iid = p_o.addInDb()
         if not inserted:
             p_o = Port.fetchObject({"_id": iid})
         infosToAdd = {"URL": website["target"]}
         for plugin in website.get("plugins", {}):
             item = website["plugins"][plugin].get("string")
             if isinstance(item, list):
                 if item:
                     infosToAdd[plugin] = item
             else:
                 item = str(item)
                 if item != "":
                     infosToAdd[plugin] = item
         p_o.updateInfos(infosToAdd)
         targets[str(p_o.getId())] = {
             "ip": host,
             "port": port,
             "proto": "tcp"
         }
         oneValidWhatweb = True
     if not oneValidWhatweb:
         return None, None, None, None
     return notes, tags, "port", targets
Пример #13
0
def parseWarnings(file_opened):
    """
    Parse the result of a testssl json output file
        Args:
            file_opened:  the opened file reference

        Returns:
            Returns a tuple with (None values if not matching a testssl output):
                - a list of string for each testssl NOT ok, WARN, or MEDIUM warnings
                - a dict of targeted objects with database id as key and a unique key as a mongo search pipeline ({})
    """
    targets = {}
    missconfiguredHosts = {}
    firstLine = True
    for line in file_opened:
        if firstLine:
            if line.strip() != '"id", "fqdn/ip", "port", "severity", "finding", "cve", "cwe"' and \
                    line.strip() != '"id","fqdn/ip","port","severity","finding","cve","cwe"':
                return None, None
            firstLine = False
            continue
        # Search ip in file
        warn = re.search(
            r"^\"[^\"]*\", ?\"([^\"]*)\", ?\"([^\"]*)\", ?\"(OK|INFO|NOT ok|WARN|LOW|MEDIUM|HIGH|CRITICAL)\", ?\"[^\"]*\", ?\"[^\"]*\", ?\"[^\"]*\"$",
            line)
        if warn is not None:
            ip = warn.group(1)
            domain = None
            port = warn.group(2)
            notes = warn.group(3)
            if "/" in ip:
                domain = ip.split("/")[0]
                ip = "/".join(ip.split("/")[1:])
                Ip().initialize(domain).addInDb()
                Port().initialize(domain, port, "tcp", "ssl").addInDb()
            Ip().initialize(ip).addInDb()
            Port().initialize(ip, port, "tcp", "ssl").addInDb()
            if notes not in ["OK", "INFO"]:
                missconfiguredHosts[ip] = missconfiguredHosts.get(ip, {})
                missconfiguredHosts[ip][port] = missconfiguredHosts[ip].get(
                    port, [])
                missconfiguredHosts[ip][port].append(notes + " : " + line)
                if domain is not None:
                    missconfiguredHosts[domain] = missconfiguredHosts.get(
                        domain, {})
                    missconfiguredHosts[domain][port] = missconfiguredHosts[
                        domain].get(port, [])
                    missconfiguredHosts[domain][port].append(notes + " : " +
                                                             line)
    for ip in missconfiguredHosts.keys():
        for port in missconfiguredHosts[ip].keys():
            p_o = Port.fetchObject({"ip": ip, "port": port, "proto": "tcp"})
            targets[str(p_o.getId())] = {
                "ip": ip,
                "port": port,
                "proto": "tcp"
            }
            missconfiguredHosts[ip][port].sort()
            notes = "\n".join(missconfiguredHosts[ip][port])
            res, _ = Defect().initialize(ip,
                                         port,
                                         "tcp",
                                         "Défauts d'implémentation du SSL/TLS",
                                         "Très difficile",
                                         "Majeur",
                                         "Important",
                                         "N/A", ["Socle"],
                                         notes=notes,
                                         proofs=[]).addInDb()
            if not res:
                p_o.updateInfos({"compliant": "False"})
                defect_o = Defect.fetchObject({
                    "ip": ip,
                    "title": "Défauts d'implémentation du SSL/TLS",
                    "port": port,
                    "proto": "tcp"
                })
                defect_o.notes += notes
                defect_o.update()
    if firstLine:
        return None, None
    return str(len(missconfiguredHosts.keys())
               ) + " misconfigured hosts found. Defects created.", targets