Ejemplo n.º 1
0
 def delete(self):
     """
     Deletes the Ip represented by this model in database.
     Also deletes the tools associated with this ip
     Also deletes the ports associated with this ip
     Also deletes the defects associated with this ip and its ports
     """
     mongoInstance = MongoCalendar.getInstance()
     tools = mongoInstance.find("tools", {"ip": self.ip}, True)
     for tool in tools:
         tool_model = Tool(tool)
         tool_model.delete()
     defects = mongoInstance.find(
         "defects", {
             "ip": self.ip,
             "$or": [{
                 "port": {
                     "$exists": False
                 }
             }, {
                 "port": None
             }]
         }, True)
     for defect in defects:
         defect_model = Defect(defect)
         defect_model.delete()
     ports = mongoInstance.find("ports", {"ip": self.ip}, True)
     for port in ports:
         port_model = Port(port)
         port_model.delete()
     mongoInstance.delete("ips", {"_id": self._id})
Ejemplo n.º 2
0
    def addAllTool(self, command_name, wave_name, scope):
        """
        Kind of recursive operation as it will call the same function in its children ports.
        Add the appropriate tools (level check and wave's commands check) for this ip.
        Also add for all registered ports the appropriate tools.

        Args:
            command_name: The command that we want to create all the tools for.
            wave_name: the wave name from where we want to load tools
            scope: a scope object allowing to launch this command. Opt
        """
        # retrieve the command level
        mongoInstance = MongoCalendar.getInstance()
        command = mongoInstance.findInDb(mongoInstance.calendarName,
                                         "commands", {"name": command_name}, False)
        if command["lvl"] == "ip":
            # finally add tool
            newTool = Tool()
            newTool.initialize(command_name, wave_name,
                               "", self.ip, "", "", "ip")
            newTool.addInDb()
            return
        # Do the same thing for all children ports.
        ports = mongoInstance.find("ports", {"ip": self.ip})
        for port in ports:
            p = Port(port)
            p.addAllTool(command_name, wave_name, scope)
Ejemplo n.º 3
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.
     """
     targets = {}
     notes = file_opened.read()
     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()
     Ip().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 = Port()
         p_o.initialize(ip, port, proto, "microsoft-ds")
         res_insert = p_o.addInDb()
         targets[str(p_o.getId())] = {
             "ip": ip,
             "port": port,
             "proto": proto
         }
     if "VULNERABLE" in notes:
         d_o = Defect()
         d_o.initialize(ip,
                        port,
                        proto,
                        "Serveur vulnérable à EternalBlue",
                        "Difficile",
                        "Critique",
                        "Critique",
                        "N/A", ["Socle"],
                        notes=notes,
                        proofs=[])
         d_o.addInDb()
         tags = ["P0wned!"]
         if res_insert is not None:
             p_o.addTag("P0wned!")
     return notes, tags, "port", targets
Ejemplo n.º 4
0
 def loadData(self):
     """
     Fetch data from database
     """
     self.ports = Port.fetchObjects({})
     self.ips = Ip.fetchObjects({})
     self.tools = Tool.fetchObjects({})
Ejemplo n.º 5
0
    def addPort(self, values):
        """
        Add a port object to database associated with this Ip.

        Args:
            values: A dictionary crafted by PortView containg all form fields values needed.

        Returns:ret
                '_id': The mongo ObjectId _idret of the inserted port document or None if insertion failed (unicity broken).
        """
        portToInsert = {"ip": self.ip, "port": str(
            values["Port"]), "proto": str(values["Protocole"]), "service": values["Service"], "product": values["Product"]}
        newPort = Port()
        newPort.initialize(
            self.ip, portToInsert["port"], portToInsert["proto"], portToInsert["service"], portToInsert["product"])
        return newPort.addInDb()
Ejemplo n.º 6
0
 def insertIp(self, ip):
     """Insert a new IP in the summary. Also insert its port
     Args:
         ip: an IP object to be inserted
     """
     treevw = ttk.Treeview(self.frameTw)
     treevw.heading("#0", text=ip, anchor='w')
     treevw.column("#0", anchor='w')
     tags = Settings.getTags()
     for tag, color in tags.items():
         treevw.tag_configure(tag, background=color)
     treevw.bind("<Double-Button-1>", self.OnDoubleClick)
     count = 0
     self.treeviews[ip] = treevw
     ports = Port.fetchObjects({"ip": ip})
     for port in ports:
         if port.proto.strip() != "" and str(port.port).strip() != "":
             port_text = port.port
             if port.proto == "udp":
                 port_text = "udp/" + port_text
             treevw.insert('',
                           'end',
                           str(port.getId()),
                           text=port_text,
                           tags=list(port.getTags()))
             count += 1
     treevw.configure(height=count)
     treevw.update_idletasks()
Ejemplo n.º 7
0
 def _insertChildrenPorts(self, ip_node):
     """Insert every children port in database as DefectView under this node directly"""
     ports = self.controller.getPorts()
     for port in ports:
         port_o = PortController(Port(port))
         port_vw = PortView(self.appliTw, self.appliViewFrame, self.mainApp,
                            port_o)
         port_vw.addInTreeview(ip_node)
Ejemplo n.º 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.
     """
     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
Ejemplo n.º 9
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
Ejemplo n.º 10
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}
Ejemplo n.º 11
0
    def addPortCallback(self, _event):
        """
        Create an empty port model and its attached view. Open this view insert window.

        Args:
            _event: Automatically generated with a button Callback, not used.
        """
        for widget in self.appliViewFrame.winfo_children():
            widget.destroy()
        modelData = self.controller.getData()
        pv = PortView(self.appliTw, self.appliViewFrame, self.mainApp,
                      PortController(Port(modelData)))
        pv.openInsertWindow()
Ejemplo n.º 12
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()
Ejemplo n.º 13
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)
Ejemplo n.º 14
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)
Ejemplo n.º 15
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
Ejemplo n.º 16
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
Ejemplo n.º 17
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
Ejemplo n.º 18
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
Ejemplo n.º 19
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
Ejemplo n.º 20
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
Ejemplo n.º 21
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
Ejemplo n.º 22
0
def smbmap_format(smbmap_output):
    """Parse raw smbmap file
    Args:
        smbmap_output: raw smbmap file content
    Returns:
        A tuple with values:
            0. a string formated where each line are : fullpath  permissions  date
            1. a list of interesting name file found
            2. targets as described in Parse
    """
    targets = {}
    regex_only_match_serv = re.compile(
        r"^\[\+\] IP: ([^:\s]+)(?::\d+)?\sName: \S+\s+$")
    # group 1 = SHARE NAME group 2 = PERMISSIONS
    regex_only_match_share_header = re.compile(r"^\t(\S+)\s+([A-Z , ]+)$")
    # group 1 = directory full path
    regex_only_match_dir = re.compile(r"^\t(\S+)$")
    # group 1 = d ou -, group 2 = permissions, group 3 = date, group 4 = filename
    regex_only_match_files = re.compile(
        r"^\s+([d-])([xrw-]{9})\s+([^\t]+)\t(.+)$")
    ret = ""
    interesting_files = {}
    interesting_name_list = [
        "passwd", "password", "pwd", "mot_de_passe", "motdepasse", "auth",
        "creds", "confidentiel", "confidential", "backup", ".xml", ".conf",
        ".cfg", "unattended"
    ]
    current_serv = ""
    current_share = ""
    current_dir = ""
    ip_states = []
    lines = smbmap_output.split("\n")
    for line in lines:
        result = regex_only_match_serv.match(line)
        if result is not None:
            ip = str(result.group(1))
            current_serv = ip
            if ip not in ip_states:
                ip_o = Ip().initialize(ip)
                ip_o.addInDb()
                Port().initialize(ip, "445", "tcp", "samba").addInDb()
                targets[str(ip_o.getId())] = {
                    "ip": ip,
                    "port": "445",
                    "proto": "tcp"
                }

                ip_states.append(ip)
            continue
        result = regex_only_match_share_header.match(line)
        if result is not None:
            share_name = str(result.group(1))
            permissions = str(result.group(2))
            current_share = share_name
            continue
        result = regex_only_match_dir.match(line)
        if result is not None:
            dir_path = str(result.group(1))
            current_dir = dir_path
            continue
        result = regex_only_match_files.match(line)
        if result is not None:
            # isDirectory = (str(result.group(1)) == "d")
            permissions = str(result.group(2))
            date = str(result.group(3))
            file_name = str(result.group(4))
            fullpath = "\\\\"+current_serv+"\\" + \
                current_share+current_dir[1:]+file_name
            for interesting_names in interesting_name_list:
                if interesting_names.lower() in file_name.lower():
                    interesting_files[
                        "Shared " + interesting_names] = interesting_files.get(
                            "Shared " + interesting_names, [])
                    interesting_files["Shared " +
                                      interesting_names].append(fullpath +
                                                                "\t" +
                                                                permissions +
                                                                "\t" + date)
            ret += fullpath + "\t" + permissions + "\t" + date + "\n"
            continue
    return ret, interesting_files, targets
Ejemplo n.º 23
0
    def displayData(self):
        """
        Display loaded data in treeviews
        """
        dialog = ChildDialogProgress(
            self.parent, "Loading dashboard ",
            "Refreshing dashboard. Please wait for a few seconds.", 200,
            "determinate")
        dialog.show(10)

        # Reset Ip treeview
        for children in self.treevw.get_children():
            self.treevw.delete(children)
        dialog.update(1)
        listOfip = []
        for ip in self.ips:
            servicesCount = len([x for x in Port.fetchObjects({"ip": ip.ip})])
            listOfip.append((ip.ip, servicesCount))
        dialog.update(2)
        listOfip.sort(key=lambda tup: tup[1], reverse=True)
        for i in range(len(listOfip)):
            self.treevw.insert('',
                               'end',
                               i,
                               text=listOfip[i][0],
                               values=(listOfip[i][1]))
        dialog.update(3)
        # Reset Port treeview
        for children in self.treevwport.get_children():
            self.treevwport.delete(children)
        dialog.update(4)
        portCounts = {}
        for port in self.ports:
            if port.port not in portCounts.keys():
                portCounts[port.port] = 1
            else:
                portCounts[port.port] += 1
        dialog.update(5)

        port_id = 0
        # Ordering dictionnary
        portCounts = {
            k: v
            for k, v in sorted(
                portCounts.items(), key=lambda item: item[1], reverse=True)
        }
        for portCount in portCounts:
            self.treevwport.insert('',
                                   'end',
                                   port_id,
                                   text=str(portCount),
                                   values=(portCounts[portCount]))
            port_id += 1
        dialog.update(6)
        # Tool part
        # Reset Tools treeview
        for children in self.treevwtools.get_children():
            self.treevwtools.delete(children)
        dialog.update(7)
        listOfTools = [_ for _ in self.tools]
        listOfTools.sort(key=lambda x: x.status, reverse=True)

        result = MongoCalendar.getInstance().aggregate("tools", [{
            "$group": {
                "_id": {
                    "name": "$name",
                    "status": "$status",
                    "wave": "$wave"
                },
                "count": {
                    "$sum": 1
                }
            }
        }])

        result = [_ for _ in result]
        result.sort(key=lambda x: x["_id"]["name"])
        dialog.update(8)
        tools_dashboard = {}
        for tool in result:
            toolName = tool["_id"]["name"]
            toolWave = tool["_id"]["wave"]
            tools_dashboard[toolWave] = tools_dashboard.get(toolWave, {})
            tools_dashboard[toolWave][toolName] = tools_dashboard[
                toolWave].get(toolName, {})
            toolStatus = "Not ready" if len(
                tool["_id"]["status"]) == 0 else tool["_id"]["status"][0]
            tools_dashboard[toolWave][toolName][
                toolStatus] = tools_dashboard[toolWave][toolName].get(
                    toolStatus, 0) + 1
        for wave in tools_dashboard.keys():
            for toolName in tools_dashboard[wave].keys():
                self.treevwtools.insert(
                    '',
                    'end',
                    None,
                    text=str(toolName),
                    values=(wave, tools_dashboard[wave][toolName].get(
                        "ready",
                        0), tools_dashboard[wave][toolName].get("running", 0),
                            tools_dashboard[wave][toolName].get("done", 0)))
        dialog.update(9)
        # Defect Part
        # reset defect TW
        for children in self.treevwDefaults.get_children():
            self.treevwDefaults.delete(children)

        result = MongoCalendar.getInstance().aggregate("defects", [{
            "$group": {
                "_id": {
                    "risk": "$risk",
                    "type": "$type"
                },
                "count": {
                    "$sum": 1
                }
            }
        }])
        dialog.update(10)
        result = [_ for _ in result]
        result.sort(key=lambda x: x["count"], reverse=True)
        for defect in result:
            defectRisk = defect["_id"]["risk"]
            defectType = " ".join(defect["_id"]["type"])
            defectCount = defect["count"]
            self.treevwDefaults.insert('',
                                       'end',
                                       None,
                                       text=str(defectRisk),
                                       values=(defectType, defectCount))
        dialog.destroy()
    def notify(self, db, collection, iid, action, _parent):
        """
        Callback for the observer implemented in mongo.py.
        Each time an object is inserted, updated or deleted the standard way, this function will be called.

        Args:
            collection: the collection that has been modified
            iid: the mongo ObjectId _id that was modified/inserted/deleted
            action: string "update" or "insert" or "delete". It was the action performed on the iid
            _parent: Not used. the mongo ObjectId of the parent. Only if action in an insert. Not used anymore
        """
        mongoInstance = MongoCalendar.getInstance()
        if not mongoInstance.hasACalendarOpen():
            return
        if mongoInstance.calendarName != db:
            return
        # Delete
        if action == "delete":
            if collection == "defects":
                view = self.getViewFromId(str(iid))
                if view is not None:
                    view.beforeDelete()
                    self.appli.statusbar.notify([],view.controller.getTags())
            try:
                self.delete(ObjectId(iid))
            except tk.TclError:
                pass  # item was not inserted in the treeview

        # Insert
        if action == "insert":
            view = None
            res = mongoInstance.find(collection, {"_id": ObjectId(iid)}, False)
            if collection == "tools":
                view = ToolView(self, self.appli.viewframe,
                                self.appli, ToolController(Tool(res)))
            elif collection == "waves":
                view = WaveView(self, self.appli.viewframe,
                                self.appli, WaveController(Wave(res)))
            elif collection == "scopes":
                view = ScopeView(self, self.appli.viewframe,
                                 self.appli, ScopeController(Scope(res)))
            elif collection == "ports":
                view = PortView(self, self.appli.viewframe,
                                self.appli, PortController(Port(res)))
            elif collection == "ips":
                view = IpView(self, self.appli.viewframe,
                              self.appli, IpController(Ip(res)))
            elif collection == "intervals":
                view = IntervalView(self, self.appli.viewframe,
                                    self.appli, IntervalController(Interval(res)))
            elif collection == "defects":
                view = DefectView(self, self.appli.viewframe,
                                self.appli, DefectController(Defect(res)))
            try:
                if view is not None:
                    view.addInTreeview()
                    view.insertReceived()
                    self.appli.statusbar.notify(view.controller.getTags())
            except tk.TclError:
                pass

        if action == "update":
            try:
                view = self.getViewFromId(str(iid))
                if view is not None:
                    oldTags = self.item(str(iid))["tags"]
                    view.controller.actualize()
                    self.appli.statusbar.notify(view.controller.getTags(), oldTags)
                    self.item(str(iid), text=str(
                        view.controller.getModelRepr()), image=view.getIcon())
            except tk.TclError:
                if view is not None:
                    view.addInTreeview()
            if str(self.appli.openedViewFrameId) == str(iid):
                for widget in self.appli.viewframe.winfo_children():
                    widget.destroy()
                view.openModifyWindow()
            if view is not None:
                view.updateReceived()
        self.appli.statusbar.update()
 def _load(self):
     """
     Load the treeview with database information
     """
     mongoInstance = MongoCalendar.getInstance()
     dialog = ChildDialogProgress(self.appli, "Loading "+str(
         mongoInstance.calendarName), "Opening "+str(mongoInstance.calendarName) + ". Please wait for a few seconds.", 200, "determinate")
     step = 0
     dialog.show(100)
     nbObjects = mongoInstance.find("waves").count()
     nbObjects += mongoInstance.find("scopes").count()
     nbObjects += mongoInstance.find("intervals").count()
     nbObjects += mongoInstance.find("scopes").count()
     nbObjects += mongoInstance.find("ips").count()
     nbObjects += mongoInstance.find("ports").count()
     nbObjects += mongoInstance.find("tools").count()
     onePercentNbObject = nbObjects//100 if nbObjects > 100 else 1
     nbObjectTreated = 0
     for child in self.get_children():
         self.delete(child)
     self._hidden = []
     self._detached = []
     self.waves_node = self.insert("", "end", str(
         "waves"), text="Waves", image=WaveView.getClassIcon())
     # Loading every category separatly is faster than recursivly.
     # This is due to cursor.next function calls in pymongo
     # Adding wave objects
     waves = Wave.fetchObjects({})
     for wave in waves:
         wave_o = WaveController(wave)
         wave_vw = WaveView(self, self.appli.viewframe, self.appli, wave_o)
         wave_vw.addInTreeview(self.waves_node, False)
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     scopes = Scope.fetchObjects({})
     for scope in scopes:
         scope_o = ScopeController(scope)
         scope_vw = ScopeView(self, self.appli.viewframe, self.appli, scope_o)
         scope_vw.addInTreeview(None, False)
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     intervals = Interval.fetchObjects({})
     for interval in intervals:
         interval_o = IntervalController(interval)
         interval_vw = IntervalView(self, self.appli.viewframe, self.appli, interval_o)
         interval_vw.addInTreeview(None, False)
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     # Adding ip objects
     self.ips_node = self.insert("", "end", str(
         "ips"), text="IPs", image=IpView.getClassIcon())
     ips = Ip.fetchObjects({})
     for ip in ips:
         ip_o = IpController(ip)
         ip_vw = IpView(self, self.appli.viewframe, self.appli, ip_o)
         ip_vw.addInTreeview(None, False)
         self.appli.statusbar.notify(ip_vw.controller.getTags())
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     # Adding port objects
     ports = Port.fetchObjects({})
     for port in ports:
         port_o = PortController(port)
         port_vw = PortView(self, self.appli.viewframe, self.appli, port_o)
         port_vw.addInTreeview(None, False)
         self.appli.statusbar.notify(port_vw.controller.getTags())
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     # Adding defect objects
     defects = Defect.fetchObjects({"ip":{"$ne":""}})
     for defect in defects:
         defect_o = DefectController(defect)
         defect_vw = DefectView(
             self, self.appli.viewframe, self.appli, defect_o)
         defect_vw.addInTreeview(None)
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     # Adding tool objects
     tools = Tool.fetchObjects({})
     for tool in tools:
         tool_o = ToolController(tool)
         tool_vw = ToolView(self, self.appli.viewframe, self.appli, tool_o)
         tool_vw.addInTreeview(None, False)
         self.appli.statusbar.notify(tool_vw.controller.getTags())
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     self.sort(self.ips_node)
     self.appli.statusbar.update()
     dialog.destroy()