Beispiel #1
0
def insert(pentest, body):
    mongoInstance = MongoCalendar.getInstance()
    mongoInstance.connectToDb(pentest)
    scope_o = ServerScope(pentest, body)
    # Checking unicity
    base = scope_o.getDbKey()
    existing = mongoInstance.find("scopes", base, False)
    if existing is not None:
        return {"res": False, "iid": existing["_id"]}
    if "_id" in body:
        del body["_id"]
    # Inserting scope
    parent = scope_o.getParentId()
    res_insert = mongoInstance.insert("scopes", base, parent)
    ret = res_insert.inserted_id
    scope_o._id = ret
    # adding the appropriate tools for this scope.
    wave = mongoInstance.find("waves", {"wave": scope_o.wave}, False)
    commands = wave["wave_commands"]
    for commName in commands:
        if commName.strip() != "":
            scope_o.addAllTool(commName)
    # Testing this scope against every ips
    ips = mongoInstance.find("ips", {})
    for ip in ips:
        ip_o = ServerIp(pentest, ip)
        if scope_o._id not in ip_o.in_scopes:
            if ip_o.fitInScope(scope_o.scope):
                ip_o.addScopeFitting(pentest, scope_o.getId())
    return {"res": True, "iid": ret}
Beispiel #2
0
 def addAllTool(self, command_name):
     """
     Add the appropriate tools (level check and wave's commands check) for this scope.
     Args:
         command_name: The command that we want to create all the tools for.
     """
     mongoInstance = MongoCalendar.getInstance()
     mongoInstance.connectToDb(self.pentest)
     command = mongoInstance.findInDb(self.pentest, "commands",
                                      {"name": command_name}, False)
     if command["lvl"] == "network":
         newTool = ServerTool(self.pentest)
         newTool.initialize(command["name"], self.wave, self.scope, "", "",
                            "", "network")
         newTool.addInDb()
         return
     if command["lvl"] == "domain":
         if not isNetworkIp(self.scope):
             newTool = ServerTool(self.pentest)
             newTool.initialize(command["name"], self.wave, self.scope, "",
                                "", "", "domain")
             newTool.addInDb()
         return
     ips = self.getIpsFitting()
     for ip in ips:
         i = ServerIp(self.pentest, ip)
         i.addAllTool(command_name, self.wave, self.scope)
Beispiel #3
0
 def Parse(self, pentest, 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.
     """
     targets = {}
     notes = file_opened.read().decode("utf-8")
     regex_ip = r"Nmap scan report for (\S+)"
     ip_group = re.search(regex_ip, notes)
     if ip_group is None:
         return None, None, None, None
     # Auto Detect:
     if "smb-vuln-ms17-010:" not in notes:
         return None, None, None, None
     # Parsing
     ip = ip_group.group(1).strip()
     ServerIp().initialize(ip).addInDb()
     port_re = r"(\d+)\/(\S+)\s+open\s+microsoft-ds"
     res_search = re.search(port_re, notes)
     res_insert = None
     if res_search is None:
         port = None
         proto = None
     else:
         port = res_search.group(1)
         proto = res_search.group(2)
         p_o = ServerPort()
         p_o.initialize(ip, port, proto, "microsoft-ds")
         insert_res = p_o.addInDb()
         res_insert = insert_res["res"]
         targets[str(p_o.getId())] = {
             "ip": ip,
             "port": port,
             "proto": proto
         }
     if "VULNERABLE" in notes:
         d_o = ServerDefect()
         d_o.initialize(ip,
                        port,
                        proto,
                        "EternalBlue",
                        "Difficult",
                        "Critical",
                        "Critical",
                        "N/A", ["Base"],
                        notes=notes,
                        proofs=[])
         d_o.addInDb()
         tags = ["P0wned!"]
         if res_insert is not None:
             p_o.addTag("P0wned!")
     return notes, tags, "port", targets
def getNotDoneTools(pentest, waveName):
    """Returns a set of tool mongo ID that are not done yet.
    """
    notDoneTools = set()
    tools = ServerTool.fetchObjects(pentest, {
        "wave": waveName,
        "ip": "",
        "dated": "None",
        "datef": "None"
    })
    for tool in tools:
        notDoneTools.add(tool.getId())
    scopes = ServerScope.fetchObjects(pentest, {"wave": waveName})
    for scope in scopes:
        scopeId = scope.getId()
        ips = ServerIp.getIpsInScope(pentest, scopeId)
        for ip in ips:
            tools = ServerTool.fetchObjects(pentest, {
                "wave": waveName,
                "ip": ip.ip,
                "dated": "None",
                "datef": "None"
            })
            for tool in tools:
                notDoneTools.add(tool.getId())
    return notDoneTools
Beispiel #5
0
 def getIpsFitting(self):
     """Returns a list of ip mongo dict fitting this scope
     Returns:
         A list ip IP dictionnary from mongo db
     """
     mongoInstance = MongoCalendar.getInstance()
     mongoInstance.connectToDb(self.pentest)
     ips = mongoInstance.find("ips", )
     ips_fitting = []
     isdomain = self.isDomain()
     for ip in ips:
         if isdomain:
             my_ip = performLookUp(self.scope)
             my_domain = self.scope
             ip_isdomain = not isIp(ip["ip"])
             if ip_isdomain:
                 if my_domain == ip["ip"]:
                     ips_fitting.append(ip)
                 if ServerScope.isSubDomain(my_domain, ip["ip"]):
                     ips_fitting.append(ip)
             else:
                 if my_ip == ip["ip"]:
                     ips_fitting.append(ip)
         else:
             if ServerIp.checkIpScope(self.scope, ip["ip"]):
                 ips_fitting.append(ip)
     return ips_fitting
Beispiel #6
0
def delete(pentest, scope_iid):
    mongoInstance = MongoCalendar.getInstance()
    mongoInstance.connectToDb(pentest)
    # deleting tool with scope lvl
    scope_o = ServerScope(
        pentest,
        mongoInstance.find("scopes", {"_id": ObjectId(scope_iid)}, False))
    tools = mongoInstance.find(
        "tools", {
            "scope": scope_o.scope,
            "wave": scope_o.wave,
            "$or": [{
                "lvl": "network"
            }, {
                "lvl": "domain"
            }]
        })
    for tool in tools:
        tool_delete(pentest, tool["_id"])
    # Deleting this scope against every ips
    ips = ServerIp.getIpsInScope(pentest, scope_iid)
    for ip in ips:
        ip.removeScopeFitting(pentest, scope_iid)
    res = mongoInstance.delete("scopes", {"_id": ObjectId(scope_iid)}, False)
    parent_wave = mongoInstance.find("waves", {"wave": scope_o.wave}, False)
    if parent_wave is None:
        return
    mongoInstance.notify(pentest, "waves", parent_wave["_id"], "update", "")
    # Finally delete the selected element
    if res is None:
        return 0
    else:
        return res.deleted_count
Beispiel #7
0
 def Parse(self, pentest, 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().decode("utf-8")
     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:
             ServerIp().initialize(host).addInDb()
             p_o = ServerPort().initialize(host, port, "tcp", service)
             insert_res = p_o.addInDb()
             if not insert_res["res"]:
                 p_o = ServerPort.fetchObject(pentest, {"_id": insert_res["iid"]})
             p_o.updateInfos(
                 {"Nikto": infos, "SSL": "True" if service == "https" else "False"})
             targets[str(insert_res["iid"])] = {
                 "ip": host, "port": port, "proto": "tcp"}
     return notes, tags, "port", targets
 def Parse(self, pentest, 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 = []
     targets = {}
     result_socket = file_opened.read().decode("utf-8")
     domain, ip = parse_reverse_python(result_socket)
     if domain is None:
         return None, None, None, None
     ServerIp().initialize(domain).addInDb()
     ip_m = ServerIp().initialize(ip)
     insert_res = ip_m.addInDb()
     if not insert_res["res"]:
         ip_m = ServerIp.fetchObject(pentest, {"_id": insert_res["iid"]})
     existing_hostnames = ip_m.infos.get("hostname", [])
     if not isinstance(existing_hostnames, list):
         existing_hostnames = [existing_hostnames]
     hostnames = list(set(existing_hostnames + [domain]))
     ip_m.updateInfos({"hostname": hostnames})
     targets["ip"] = {"ip": ip}
     notes += "Domain found :" + domain + "\n"
     if notes == "":
         notes = "No domain found\n"
     return notes, tags, "ip", targets
Beispiel #9
0
 def Parse(self, pentest, 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"]
     marker = "- scanning for subdomain..."
     markerFound = False
     countFound = 0
     for line in file_opened:
         line = line.decode("utf-8")
         if marker == line.strip():
             markerFound = True
         if not markerFound:
             continue
         ip, domain, alias = parse_knockpy_line(line)
         if ip is not None and domain is not None:
             # a domain has been found
             insert_res = ServerIp().initialize(domain).addInDb()
             if insert_res["res"]:
                 ServerIp().initialize(ip).addInDb()
                 notes += line+"\n"
                 countFound += 1
             # failed, domain is out of scope
             else:
                 notes += domain+" exists but already added.\n"
             ip_m = ServerIp.fetchObject(pentest, {"_id": insert_res["iid"]})
             if alias:
                 ip_m.updateInfos({"alias": ip})
     if notes.strip() == "":
         return None, None, None, None
     return notes, tags, "wave", {"wave": None}
Beispiel #10
0
    def Parse(self, pentest, 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().decode("utf-8")
        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
        ServerIp().initialize(host).addInDb()
        p_o = ServerPort().initialize(host, port, proto, service)
        insert_res = p_o.addInDb()
        if not insert_res["res"]:
            p_o = ServerPort.fetchObject(pentest, {"_id": insert_res["iid"]})

        p_o.updateInfos({"Methods": ", ".join(supported_methods)})
        targets[str(p_o.getId())] = {"ip": host, "port": port, "proto": proto}
        if "TRACE" in risky_methods:
            ServerDefect().initialize(host,
                                      port,
                                      proto,
                                      "TRACE Method activated",
                                      "Difficult",
                                      "Important",
                                      "Important",
                                      "N/A", ["Base"],
                                      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
Beispiel #11
0
 def Parse(self, pentest, 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"]
     countInserted = 0
     markerSublister = "# Coded By Ahmed Aboul-Ela - @aboul3la"
     markerFound = False
     for line in file_opened:
         line = line.decode("utf-8")
         if markerSublister in line:
             markerFound = True
         if not markerFound:
             continue
         if line.startswith("\x1b[92m"):
             line = line[len("\x1b[92m"):]
         if line.endswith("\x1b[0m"):
             line = line[:-1 * len("\x1b[0m")]
         domainGroup = re.search(
             r"((?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9])",
             line.strip())
         if domainGroup is not None:
             # a domain has been found
             domain = domainGroup.group(1)
             insert_res = ServerIp().initialize(domain).addInDb()
             # failed, domain is out of wave, still noting thi
             if not insert_res["res"]:
                 notes += domain + " exists but already added.\n"
             else:
                 countInserted += 1
                 notes += domain + " inserted.\n"
     if notes.strip() == "":
         return None, None, None, None
     if not markerFound:
         return None, None, None, None
     return notes, tags, "wave", {"wave": None}
Beispiel #12
0
 def Parse(self, pentest, 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().decode("utf-8")
     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:
             ServerIp().initialize(host).addInDb()
             for port in hosts[host]:
                 port_o = ServerPort()
                 port_o.initialize(host, port, "tcp",
                                   hosts[host][port]["service"])
                 insert_ret = port_o.addInDb()
                 if not insert_ret["res"]:
                     port_o = ServerPort.fetchObject(pentest, {"_id": insert_ret["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
Beispiel #13
0
def editScopeIPs(pentest, 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 = []

            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 = ServerIp().initialize(str(infos["ip"]))
            insert_ret = ip_m.addInDb()
            if not insert_ret["res"]:
                ip_m = ServerIp.fetchObject(pentest,
                                            {"_id": insert_ret["iid"]})
            infosToAdd["hostname"] = list(
                set(ip_m.infos.get("hostname", []) + [infos["hostname"]]))
            ip_m.notes = "hostname:" + \
                infos["hostname"] + "\n"+infos.get("OS", "")
            if infos.get("powned", False):
                ip_m.addTag("P0wned!")
            port_m = ServerPort().initialize(str(infos["ip"]),
                                             str(infos["port"]), "tcp",
                                             "netbios-ssn")
            insert_ret = port_m.addInDb()
            if not insert_ret["res"]:
                port_m = ServerPort.fetchObject(pentest,
                                                {"_id": insert_ret["iid"]})
            port_m.updateInfos(infosToAdd)
            if infos.get("powned", False):
                port_m.addTag("P0wned!")
Beispiel #14
0
    def Parse(self, pentest, 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.
        """
        parsed_by_hosts = parse(file_opened)
        if parsed_by_hosts is None:
            return None, None, None, None
        tags = ["todo"]
        cumulative_notes = []
        targets = {}
        for parsed_host in parsed_by_hosts:
            host = parsed_host
            findings = parsed_by_hosts[parsed_host]
            targets["ip"] = {"ip": host}
            notes = "host:" + str(host) + "\n"
            for finding in findings:
                notes += finding["info"]["name"] + " (" + finding["info"][
                    "severity"] + ") " + finding["info"].get(
                        "description", "") + "\n"
            for finding in findings:
                if finding["info"]["severity"] in [
                        "medium", "high", "critical"
                ]:
                    tags = ["Interesting"]
            ip_o = ServerIp().initialize(host, notes)
            inserted = ip_o.addInDb()
            if not inserted["res"]:
                ip_o = ServerIp.fetchObject(pentest, {"_id": inserted["iid"]})
                ip_o.notes += "\nNuclei:\n" + notes
                ip_o.update()
            cumulative_notes.append(notes + "\n")

        notes = "\n".join(cumulative_notes)

        return notes, tags, "ip", targets
Beispiel #15
0
    def Parse(self, pentest, file_opened, **_kwargs):
        """
        Parse a opened file to extract information

        foe.test.fr.	801	IN	A	18.19.20.21
        blog.test.fr.	10800	IN	CNAME	22.33.44.55
        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 = []
        countInserted = 0
        for line in file_opened:
            line = line.decode("utf-8")
            domain, _record_type, ip = parse_crtsh_line(line)
            if domain is not None:
                # a domain has been found
                infosToAdd = {"hostname": ip}
                ip_m = ServerIp().initialize(domain, infos=infosToAdd)
                insert_ret = ip_m.addInDb()
                # failed, domain is out of scope
                if not insert_ret["res"]:
                    notes += domain+" exists but already added.\n"
                    ip_m = ServerIp.fetchObject(pentest, {"_id": insert_ret["iid"]})
                    hostname = ip_m.infos.get("hostname", [])
                    if not isinstance(hostname, list):
                        hostname = [hostname]
                    infosToAdd = {"hostname": list(set([ip] + hostname))}
                    ip_m.updateInfos(infosToAdd)
                else:
                    countInserted += 1
                    notes += domain+" inserted.\n"
        if notes.strip() == "":
            return None, None, None, None
        elif countInserted != 0:
            tags.append("todo")
        return notes, tags, "wave", {"wave": None}
Beispiel #16
0
    def Parse(self, pentest, 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
            line = line.decode("utf-8")
            infos = line.split(" - ")
            if len(infos) < 3:
                return None, None, None, None
            if not ServerIp.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()
            ServerIp().initialize(ip).addInDb()
            p_o = ServerPort.fetchObject(
                pentest, {
                    "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:
                ServerDefect().initialize(ip,
                                          kwargs.get("port", None),
                                          kwargs.get("proto", None),
                                          "BlueKeep",
                                          "Difficult",
                                          "Critical",
                                          "Critical",
                                          "N/A", ["Base"],
                                          notes=notes,
                                          proofs=[]).addInDb()
                tags = ["P0wned!"]
                if p_o is not None:
                    p_o.addTag("P0wned!")
                ip_o = ServerIp.fetchObject(pentest, {"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
Beispiel #17
0
    def Parse(self, pentest, file_opened, **_kwargs):
        """
        Parse a opened file to extract information
        Example:
[       
    {
        "arguments": "./dnsrecon.py -r 10.0.0.0/24 -j /home/barre/test.json",
        "date": "2020-01-06 11:43:37.701513",
        "type": "ScanInfo"
    },
    {
        "address": "10.0.0.1",
        "name": "_gateway",
        "type": "PTR"
    },
    {
        "address": "10.0.0.77",
        "name": "barre-ThinkPad-E480",
        "type": "PTR"
    },
    {
        "address": "10.0.0.77",
        "name": "barre-ThinkPad-E480.local",
        "type": "PTR"
    }
]
        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 = []
        countInserted = 0
        try:
            dnsrecon_content = json.loads(file_opened.read().decode("utf-8"))
        except json.decoder.JSONDecodeError:
            return None, None, None, None
        if len(dnsrecon_content) == 0:
            return None, None, None, None
        if not isinstance(dnsrecon_content[0], dict):
            return None, None, None, None
        if dnsrecon_content[0].get("type", "") != "ScanInfo":
            return None, None, None, None
        if dnsrecon_content[0].get("date", "") == "":
            return None, None, None, None
        for record in dnsrecon_content[1:]:
            ip = record["address"]
            name = record["name"]
            infosToAdd = {"hostname": [name]}
            ip_m = ServerIp().initialize(ip, infos=infosToAdd)
            ip_m.addInDb()
            infosToAdd = {"ip": [ip]}
            ip_m = ServerIp().initialize(name, infos=infosToAdd)
            insert_ret = ip_m.addInDb()
            # failed, domain is out of scope
            if not insert_ret["res"]:
                notes += name + " exists but already added.\n"
                ip_m = ServerIp.fetchObject(pentest,
                                            {"_id": insert_ret["iid"]})
                existing_ips = ip_m.infos.get("ip", [])
                if not isinstance(existing_ips, list):
                    existing_ips = [existing_ips]
                infosToAdd = {"ip": list(set([ip] + existing_ips))}
                ip_m.updateInfos(infosToAdd)
            else:
                countInserted += 1
                notes += name + " inserted.\n"
        return notes, tags, "wave", {"wave": None}
Beispiel #18
0
 def Parse(self, pentest, 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().decode("utf-8")
     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
                 ServerIp().initialize(ip).addInDb()
                 port_o = ServerPort().initialize(ip, port, "tcp", "ssh")
                 insert_res = port_o.addInDb()
                 if not insert_res["res"]:
                     port_o = ServerPort.fetchObject(
                         pentest, {"_id": insert_res["iid"]})
                 if port_o is None:
                     continue
                 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"]})
                     ServerDefect().initialize(
                         ip,
                         port,
                         "tcp",
                         "SSH configuration implementation flaws",
                         "Arduous",
                         "Major",
                         "Important",
                         "N/A", ["Base"],
                         notes=notes,
                         proofs=[]).addInDb()
         except KeyError:
             continue
     if not oneScanIsValid:
         return None, None, None, None
     return notes, tags, "port", targets
Beispiel #19
0
def parseWarnings(pentest, 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:
        line = line.decode("utf-8")
        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:])
                ServerIp().initialize(domain).addInDb()
                ServerPort().initialize(domain, port, "tcp", "ssl").addInDb()
            ServerIp().initialize(ip).addInDb()
            ServerPort().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():
        if ip.strip() != "":
            for port in missconfiguredHosts[ip].keys():
                p_o = ServerPort.fetchObject(pentest, {
                    "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, _ = ServerDefect().initialize(
                    ip,
                    port,
                    "tcp",
                    "SSL/TLS implementation flaws",
                    "Arduous",
                    "Major",
                    "Important",
                    "N/A", ["Base"],
                    notes=notes,
                    proofs=[]).addInDb()
                if not res:
                    p_o.updateInfos({"compliant": "False"})
                    defect_o = ServerDefect.fetchObject({
                        "ip": ip,
                        "title": "SSL/TLS implementation flaws",
                        "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
Beispiel #20
0
def getIpPortsNmap(pentest, 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().decode("utf-8").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 = ServerIp(pentest).initialize(str(lastIp[0]),
                                                    notes=notes_ip)
            if lastIp[1].strip() != "" and lastIp[1] is not None:
                ipDom_m = ServerIp(pentest).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:
                        insert_res = ipDom_m.addInDb()
                        if not insert_res["res"]:
                            ipDom_m = ServerIp.fetchObject(
                                pentest, {"_id": insert_res["iid"]})
                        hostnames = ipDom_m.infos.get("hostname", [])
                        if isinstance(hostnames, str):
                            hostnames = [hostnames]
                        ipDom_m.updateInfos({
                            "hostname":
                            list(set(list(hostnames) + [str(ipCIDR_m.ip)]))
                        })
                        validIps.append(ipDom_m.ip)
                for ipFound in validIps:
                    if ip == "":
                        continue
                    port_o = ServerPort(pentest).initialize(
                        ipFound, port_number, proto, service, product)
                    insert_res = port_o.addInDb()
                    if not insert_res["res"]:
                        port_o = ServerPort.fetchObject(
                            pentest, {"_id": insert_res["iid"]})
                    port_o.service = service
                    port_o.update()

    notes = str(countOpen) + " open ports found\n" + notes
    return notes
Beispiel #21
0
 def Parse(self, pentest, 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().decode("utf-8")
     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"
         ServerIp().initialize(host).addInDb()
         p_o = ServerPort().initialize(host, port, "tcp", service)
         insert_res = p_o.addInDb()
         if not insert_res["res"]:
             p_o = ServerPort.fetchObject(pentest,
                                          {"_id": insert_res["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