Beispiel #1
0
    def addInDb(self):
        """
        Add this IP in database.

        Returns: a tuple with :
                * bool for success
                * mongo ObjectId : already existing object if duplicate, create object id otherwise 
        """
        # Checking unicity
        if self.ip.strip() == "":
            raise ValueError("Ip insertion error: Cannot insert empty ip")
        base = self.getDbKey()
        apiclient = APIClient.getInstance()
        # Add ip as it is unique
        base["notes"] = self.notes
        base["tags"] = self.tags
        base["in_scopes"] = self.in_scopes
        base["infos"] = self.infos
        resInsert, idInsert = apiclient.insert("ips", base)
        self._id = idInsert
        # adding the appropriate tools for this port.
        # 1. fetching the wave's commands
        return resInsert, self._id
Beispiel #2
0
 def addUser(self):
     apiclient = APIClient.getInstance()
     if self.confirmpassword.get() != self.password.get():
         tk.messagebox.showerror(
             "Add user failed",
             "The password does not match the confirmation")
     username = self.entryAddUser.get()
     passw = self.password.get()
     name = self.name.get()
     surname = self.surname.get()
     email = self.email.get()
     apiclient.registerUser(username, passw, name, surname, email)
     self.userTv.insert('',
                        'end',
                        username,
                        text=username,
                        values=(
                            "Change pass",
                            '',
                            name,
                            surname,
                            email,
                        ))
Beispiel #3
0
    def addDomainInDb(self, checkDomain=True):
        """
        Add this scope domain in database.

        Args:
            checkDomain: boolean. If true (Default), checks that the domain IP is in scope

        Returns: a tuple with :
                * bool for success
                * mongo ObjectId : already existing object if duplicate, create object id otherwise 
        """
        # Checking unicity
        base = self.getDbKey()
        apiclient = APIClient.getInstance()
        # Check if domain's ip fit in one of the Scope of the wave
        if checkDomain:
            if not Scope.checkDomainFit(self.wave, self.scope):
                return -1, None
        # insert the domains in the scopes
        res_insert, iid = apiclient.insert("scopes", base)
        self._id = iid
        # Adding appropriate tools for this scopes
        return 1, iid
 def addDCinDb(self, ip):
     apiclient = APIClient.getInstance()
     existing = apiclient.findInDb(apiclient.getCurrentPentest(),
                                   ActiveDirectory.collName, {
                                       "type": "computer",
                                       "ip": ip
                                   }, False)
     if existing is None:
         apiclient.insertInDb(apiclient.getCurrentPentest(),
                              ActiveDirectory.collName, {
                                  "type": "computer",
                                  "domain": "",
                                  "isDC": True,
                                  "name": "",
                                  "ip": ip,
                                  "OS": "",
                                  "signing": True,
                                  "SMBv1": "",
                                  "users": [],
                                  "admins": []
                              },
                              notify=True)
     else:
         apiclient.updateInDb(apiclient.getCurrentPentest(),
                              ActiveDirectory.collName,
                              {"_id": ObjectId(existing["_id"])},
                              {"$set": {
                                  "isDC": True
                              }},
                              notify=True)
         if not existing.get("isDC", False):
             if len(existing.get("users", [])) > 0:
                 self.newComputerEvent("OnDCFirstUser",
                                       existing.get("users", [])[0], ip)
             if len(existing.get("admins", [])) > 0:
                 self.newComputerEvent("OnDCFirstAdmin",
                                       existing.get("admins", [])[0], ip)
 def _commonWindowForms(self, default={}):
     """Construct form parts identical between Modify and Insert forms
     Args:
         default: a dict of default values for inputs (sleep_between, priority, max_thread). Default to empty respectively "0", "0", "1"
     """
     self.form.addFormHidden("owner", default.get("owner", ""))
     panel_bottom = self.form.addFormPanel(grid=True)
     row = 0
     panel_bottom.addFormLabel("Binary path", row=row)
     panel_bottom.addFormStr("Bin path", r"", default.get("bin_path", ""), width=30, column=1, row=row)
     panel_bottom.addFormHelper(
         "The local binary path to use for this command.", column=2, row=row)
     row += 1
     panel_bottom.addFormLabel("Plugin", row=row)
     panel_bottom.addFormCombo("Plugin", APIClient.getInstance().getPlugins(), default.get("plugin", "Default") ,width=30, column=1, row=row)
     panel_bottom.addFormHelper(
         "The plugin handling this command.", column=2, row=row)
     row += 1
     panel_bottom.addFormLabel("Timeout (in secondes)", row=row)
     panel_bottom.addFormStr("Timeout", r"\d+", default.get("timeout", "300"), width=10, column=1, row=row)
     panel_bottom.addFormHelper(
         "The tool will cancel itself when this duration in second is reached to be run again later.", column=2, row=row)
     row += 1
     panel_bottom.addFormLabel("Delay", row=row)
     panel_bottom.addFormStr("Delay", r"\d+", default.get("sleep_between", "0"), width=5, column=1, row=row)
     panel_bottom.addFormHelper(
         "Delay in-between two launch of this command (in seconds)", column=2, row=row)
     panel_bottom.addFormLabel("Priority", row=row)
     panel_bottom.addFormStr("Priority", r"\d+", default.get("priority", "0"),
                             width=2, row=row, column=1)
     panel_bottom.addFormHelper(
         "Priority in queue (0 is HIGHEST)", row=row, column=2)
     panel_bottom.addFormLabel("Threads", row=row)
     panel_bottom.addFormStr("Threads", r"\d+", default.get("max_thread", "1"),
                             width=2, row=row, column=1)
     panel_bottom.addFormHelper(
         "Number of authorized parallel running of this command on one worker.", row=row, column=2)
    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
        """
        apiclient = APIClient.getInstance()
        if not apiclient.getCurrentPentest() != "":
            return
        if apiclient.getCurrentPentest() != db:
            return
        if collection == ActiveDirectory.collName:
            self.handleActiveDirectoryNotif(iid, action)
        elif collection == "ports" and action != "delete":
            port_o = Port.fetchObject({"_id": ObjectId(iid)})
            if int(port_o.port) == 445:
                self.loadInfoFromPort(port_o)
            if int(port_o.port) == 88:
                self.addDCinDb(port_o.ip)
Beispiel #7
0
 def onOk(self, event=None):
     """
     Called when the user clicked the validation button.
     Try a full connection with authentication to the host given.
     Side effects:
         - Open dialogs if the connection failed. Does not close this dialog.
         - If the connections succeeded : write the client.cfg file accordingly.
     """
     # send the data to the parent
     config = self.getForm()
     apiclient = APIClient.getInstance()
     apiclient.reinitConnection()
     res = apiclient.tryConnection(config)
     self.rvalue = False
     if res:
         #  pylint: disable=len-as-condition
         loginRes = apiclient.login(self.ent_login.get(), self.password.get())
         if loginRes:
             self.rvalue = True
             self.app.destroy()
         else:
             tk.messagebox.showerror("Connection failure", "The login/password you entered does not exists")
     else:
         tk.messagebox.showerror("Connection failure", "The host is not responding. Check if server is alive or if you have a local proxy configured.")
Beispiel #8
0
    def launchCallback(self, _event=None):
        """
        Callback for the launch tool button. Will queue this tool to a worker. #TODO move to ToolController
        Will try to launch respecting limits first. If it does not work, it will asks the user to force launch.

        Args:
            _event: Automatically generated with a button Callback, not used.
        """
        res = self.safeLaunchCallback()
        if not res:
            dialog = ChildDialogQuestion(
                self.appliViewFrame, "Safe queue failed",
                "This tool cannot be launched because no worker add space for its thread.\nDo you want to launch it anyway?"
            )
            self.appliViewFrame.wait_window(dialog.app)
            answer = dialog.rvalue
            if answer == "Yes":
                apiclient = APIClient.getInstance()
                apiclient.sendLaunchTask(self.controller.model.getId(), False)
        if res:
            self.form.clear()
            for widget in self.appliViewFrame.winfo_children():
                widget.destroy()
            self.openModifyWindow()
Beispiel #9
0
 def savePentestSettings(self):
     apiclient = APIClient.getInstance()
     settings = apiclient.find("settings")
     existing_settings = {}
     for setting in settings:
         existing_settings[setting["key"]] = setting
     for k, v in self.db_settings.items():
         if k in existing_settings:
             if k == "tags":
                 for line_key, line_value in v.items():
                     tag, color = line_key, line_value
                     if tag not in existing_settings["tags"]["value"]:
                         apiclient.registerTag(tag, color, False)
                     else:
                         apiclient.updateTag(tag, color, False)
                 for tag in existing_settings["tags"].get("value", {}):
                     if tag not in v:
                         apiclient.unregisterTag(tag, False)
             else:
                 apiclient.updateInDb(apiclient.getCurrentPentest(),
                                      "settings", {"key": k},
                                      {"$set": {
                                          "value": v
                                      }})
Beispiel #10
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 = APIClient.getInstance().aggregate("tools", [{
            "$group": {
                "_id": {
                    "name": "$name",
                    "status": "$status",
                    "wave": "$wave"
                },
                "count": {
                    "$sum": 1
                }
            }
        }])

        result = [_ for _ in result]
        tools_dashboard = {}
        for tool_result in result:
            tool_id = tool_result["_id"].get(
                "wave", "") + "::" + tool_result["_id"]["name"]
            tools_dashboard[tool_id] = tools_dashboard.get(tool_id, {})
            tool_status = list(tool_result["_id"].get("status", "ready"))
            if not tool_status:
                tool_status = ["ready"]
            tools_dashboard[tool_id][tool_status[0]] = tool_result["count"]
        dialog.update(8)
        for tool_id in sorted(list(tools_dashboard.keys())):
            self.treevwtools.insert(
                '',
                'end',
                None,
                text=str(tool_id),
                values=(tools_dashboard[tool_id].get("ready", 0),
                        tools_dashboard[tool_id].get("running", 0),
                        tools_dashboard[tool_id].get("done", 0),
                        tools_dashboard[tool_id].get("error", 0) +
                        tools_dashboard[tool_id].get("timedout", 0)))
        dialog.update(9)
        # Defect Part
        # reset defect TW
        for children in self.treevwDefaults.get_children():
            self.treevwDefaults.delete(children)

        result = APIClient.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()
Beispiel #11
0
 def open(self):
     apiclient = APIClient.getInstance()
     if apiclient.getCurrentPentest() is not None:
         self.refreshUI()
     return True
Beispiel #12
0
 def openModifyWindow(self):
     """
     Creates a tkinter form using Forms classes. This form aims to update or delete an existing Port
     """
     modelData = self.controller.getData()
     top_panel = self.form.addFormPanel(grid=True)
     top_panel.addFormLabel("IP", row=0, column=0)
     top_panel.addFormStr("IP",
                          '',
                          modelData["ip"],
                          None,
                          column=1,
                          row=0,
                          state="readonly")
     top_panel.addFormLabel("Number", column=0, row=1)
     top_panel.addFormStr("Number",
                          '',
                          modelData["port"],
                          None,
                          column=1,
                          row=1,
                          state="readonly")
     top_panel.addFormLabel("Proto", row=2, column=0)
     top_panel.addFormStr("Proto",
                          '',
                          modelData["proto"],
                          None,
                          column=1,
                          row=2,
                          state="readonly")
     top_panel.addFormLabel("Service", row=3)
     top_panel.addFormStr("Service",
                          r"",
                          modelData["service"],
                          column=1,
                          row=3)
     if "http" in modelData["service"]:
         top_panel.addFormButton("Open in browser",
                                 self.openInBrowser,
                                 column=2,
                                 row=3)
     top_panel.addFormLabel("Product", row=4)
     top_panel.addFormStr("Product",
                          r"",
                          modelData["product"],
                          width=40,
                          row=4,
                          column=1)
     top_panel = self.form.addFormPanel()
     top_panel.addFormLabel("Notes", side="top")
     top_panel.addFormText("Notes",
                           r"",
                           modelData["notes"],
                           None,
                           side="top",
                           height=10)
     top_panel.addFormLabel("Infos", side="left")
     top_panel.addFormText("Infos",
                           is_json,
                           json.dumps(modelData["infos"], indent=4),
                           side="left",
                           fill="both",
                           height=5)
     command_list = Command.fetchObjects(
         {"lvl": "port"},
         APIClient.getInstance().getCurrentPentest())
     command_names = ["None"]
     self.command_names_to_iid = {}
     for command_doc in command_list:
         command_names.append(command_doc.name)
         self.command_names_to_iid[command_doc.name] = str(command_doc._id)
     self.tool_panel = self.form.addFormPanel(grid=True)
     self.tool_panel.addFormLabel("Tool to add")
     self.tool_panel.addFormCombo("Tool to add",
                                  command_names,
                                  "None",
                                  column=1)
     self.tool_panel.addFormButton("Add tool", self._addTool, column=2)
     top_panel = self.form.addFormPanel(grid=True)
     top_panel.addFormButton("Add a security defect",
                             self.addDefectCallback)
     self.form.addFormHidden("ip", modelData["ip"])
     self.completeModifyWindow()
Beispiel #13
0
 def loadData(self):
     """
     Fetch data from database
     """
     apiclient = APIClient.getInstance()
     self.auths = apiclient.find("auths")
Beispiel #14
0
 def addToMyCommands(self):
     apiclient = APIClient.getInstance()
     apiclient.addCommandToMyCommands(self.getId())
Beispiel #15
0
    def _load(self):
        """
        Load the treeview with database information
        """
        apiclient = APIClient.getInstance()
        dialog = ChildDialogProgress(
            self.appli, "Loading " + str(apiclient.getCurrentPentest()),
            "Opening " + str(apiclient.getCurrentPentest()) +
            ". Please wait for a few seconds.", 200, "determinate")
        step = 0
        dialog.show(100)
        nbObjects = apiclient.count("waves", )
        nbObjects += apiclient.count("scopes")
        nbObjects += apiclient.count("intervals")
        nbObjects += apiclient.count("scopes")
        nbObjects += apiclient.count("ips")
        nbObjects += apiclient.count("ports")
        nbObjects += apiclient.count("tools")
        nbObjects += apiclient.count("commands")
        onePercentNbObject = nbObjects // 100 if nbObjects > 100 else 1
        nbObjectTreated = 0
        self.delete(*self.get_children())
        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

        self.commands_node = self.insert("",
                                         "end",
                                         "commands",
                                         text="Commands",
                                         image=CommandView.getClassIcon())
        self.group_command_node = self.insert(
            "",
            "end",
            "groupcommands",
            text="Command Groups",
            image=CommandGroupView.getClassIcon())
        self.my_group_command_node = self.insert(
            self.group_command_node,
            "end",
            "mygroupcommands",
            text="My Command Groups",
            image=CommandGroupView.getClassIcon())
        self.worker_group_command_node = self.insert(
            self.group_command_node,
            "end",
            "workergroupcommands",
            text="Worker Command Groups",
            image=CommandGroupView.getClassIcon())
        self.my_commands_node = self.insert(self.commands_node,
                                            "end",
                                            "mycommands",
                                            text="My commands",
                                            image=CommandView.getClassIcon())
        self.worker_commands_node = self.insert(
            self.commands_node,
            "end",
            "workercommands",
            text="Worker commands",
            image=CommandView.getClassIcon())
        self.others_commands_node = self.insert(
            self.commands_node,
            "end",
            "otherscommands",
            text="Others commands",
            image=CommandView.getClassIcon())
        commands = Command.fetchObjects({}, apiclient.getCurrentPentest())
        for command in commands:
            command_vw = CommandView(self, self.appli.viewframe, self.appli,
                                     CommandController(command))
            command_vw.addInTreeview()
        group_commands = CommandGroup.fetchObjects(
            {}, apiclient.getCurrentPentest())
        for command_groupe_vw in group_commands:
            command_groupe_vw = CommandGroupView(
                self, self.appli.viewframe, self.appli,
                CommandGroupController(command_groupe_vw))
            command_groupe_vw.addInTreeview()
        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()
Beispiel #16
0
    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
        """
        apiclient = APIClient.getInstance()
        if not apiclient.getCurrentPentest() != "":
            return
        if db == "pollenisator":
            if collection == "settings":
                self.configureTags()
                return
        if apiclient.getCurrentPentest() != db:
            return
        # Delete
        if action == "delete":
            if collection == "defects":
                view = self.getViewFromId(str(iid))
                if view is not None:
                    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 = apiclient.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)))
            elif collection == "commands":
                view = CommandView(self, self.appli.viewframe, self.appli,
                                   CommandController(Command(res)))
            elif collection == "group_commands":
                view = CommandGroupView(
                    self, self.appli.viewframe, self.appli,
                    CommandGroupController(CommandGroup(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:
                    item = self.item(str(iid))
                    oldTags = item["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 addComputerinDb(self, port_o):
     apiclient = APIClient.getInstance()
     existing = apiclient.findInDb(apiclient.getCurrentPentest(),
                                   ActiveDirectory.collName, {
                                       "type": "computer",
                                       "ip": port_o.ip
                                   }, False)
     existingUsers = []
     newUsers = []
     existingAdmins = []
     newAdmins = []
     isDC = False
     if existing is None:
         newUsers = ActiveDirectory.normalize_users(
             port_o.infos.get("users", []))
         newAdmins = ActiveDirectory.normalize_users(
             port_o.infos.get("admins", []))
         apiclient.insertInDb(
             apiclient.getCurrentPentest(),
             ActiveDirectory.collName, {
                 "type": "computer",
                 "domain": port_o.infos.get("domain", ""),
                 "isDC": isDC,
                 "name": port_o.infos.get("machine_name", ""),
                 "ip": port_o.ip,
                 "OS": port_o.infos.get("OS", ""),
                 "signing": port_o.infos.get("signing", ""),
                 "secrets": port_o.infos.get("secrets", ""),
                 "ntds": port_o.infos.get("ntds", ""),
                 "SMBv1": port_o.infos.get("SMBv1", ""),
                 "users": newUsers,
                 "admins": newAdmins
             },
             notify=True)
     else:
         isDC = existing.get("isDC", False)
         existingUsers = set(
             map(tuple,
                 ActiveDirectory.normalize_users(existing.get("users",
                                                              []))))
         newUsers = list(
             existingUsers.union(
                 map(
                     tuple,
                     ActiveDirectory.normalize_users(
                         port_o.infos.get("users", [])))))
         existingAdmins = set(
             map(
                 tuple,
                 ActiveDirectory.normalize_users(existing.get("admins",
                                                              []))))
         newAdmins = list(
             existingAdmins.union(
                 map(
                     tuple,
                     ActiveDirectory.normalize_users(
                         port_o.infos.get("admins", [])))))
         apiclient.updateInDb(
             apiclient.getCurrentPentest(), ActiveDirectory.collName,
             {"_id": ObjectId(existing["_id"])}, {
                 "$set": {
                     "name": port_o.infos.get("machine_name", ""),
                     "domain": port_o.infos.get("domain", ""),
                     "isDC": isDC,
                     "OS": port_o.infos.get("OS", ""),
                     "signing": port_o.infos.get("signing", ""),
                     "secrets": port_o.infos.get("secrets", ""),
                     "ntds": port_o.infos.get("ntds", ""),
                     "SMBv1": port_o.infos.get("SMBv1", ""),
                     "users": newUsers,
                     "admins": newAdmins
                 }
             })
     self.checkEvents(port_o, existingUsers, newUsers, existingAdmins,
                      newAdmins, isDC)
 def addSelectedToMyCommands(self, event=None):
     apiclient = APIClient.getInstance()
     for selected in self.appliTw.selection():
         apiclient.addCommandToMyCommands(selected)
Beispiel #19
0
    def openModifyWindow(self):
        """
        Creates a tkinter form using Forms classes. This form aims to update or delete an existing Tool
        """
        modelData = self.controller.getData()
        top_panel = self.form.addFormPanel(grid=True)
        top_panel.addFormLabel("Name", modelData["name"])
        dates_panel = self.form.addFormPanel(grid=True)
        dates_panel.addFormLabel("Start date")
        dates_panel.addFormDate("Start date",
                                self.mainApp,
                                modelData["dated"],
                                column=1)
        dates_panel.addFormLabel("End date", row=1)
        dates_panel.addFormDate("End date",
                                self.mainApp,
                                modelData["datef"],
                                row=1,
                                column=1)
        dates_panel.addFormLabel("Scanner", row=2)
        dates_panel.addFormStr("Scanner",
                               r"",
                               modelData["scanner_ip"],
                               row=2,
                               column=1)
        dates_panel.addFormLabel("Command executed", row=3)
        dates_panel.addFormStr("Command executed",
                               "",
                               modelData.get("infos", {}).get("cmdline", ""),
                               row=3,
                               column=1,
                               state="disabled")
        notes = modelData.get("notes", "")
        top_panel = self.form.addFormPanel()
        top_panel.addFormLabel("Notes", side="top")
        top_panel.addFormText("Notes", r"", notes, None, side="top", height=15)
        actions_panel = self.form.addFormPanel()
        apiclient = APIClient.getInstance()
        hasWorkers = len(
            apiclient.getWorkers({"pentest": apiclient.getCurrentPentest()}))
        #Ready is legacy, OOS and/or OOT should be used
        if ("ready" in self.controller.getStatus()
                or "error" in self.controller.getStatus()
                or "timedout" in self.controller.getStatus()) or len(
                    self.controller.getStatus()) == 0:
            if apiclient.getUser() in modelData["name"]:
                actions_panel.addFormButton("Local launch",
                                            self.localLaunchCallback,
                                            side="right")
            elif hasWorkers and "Worker" in modelData["name"]:
                actions_panel.addFormButton("Run on worker",
                                            self.launchCallback,
                                            side="right")
            else:
                actions_panel.addFormLabel("Info",
                                           "Tool is ready",
                                           side="right")
        elif "OOS" in self.controller.getStatus(
        ) or "OOT" in self.controller.getStatus():
            actions_panel.addFormButton("Local launch",
                                        self.localLaunchCallback,
                                        side="right")
            if hasWorkers:
                actions_panel.addFormButton("Run on worker",
                                            self.launchCallback,
                                            side="right")
            else:
                actions_panel.addFormLabel("Info",
                                           "Tool is ready but no worker found",
                                           side="right")
        elif "running" in self.controller.getStatus():
            actions_panel.addFormButton("Stop",
                                        self.stopCallback,
                                        side="right")
        elif "done" in self.controller.getStatus():
            actions_panel.addFormButton("Download result file",
                                        self.downloadResultFile,
                                        side="right")
            try:
                mod = Utils.loadPlugin(
                    self.controller.model.getCommand()["plugin"])
                pluginActions = mod.getActions(self.controller.model)
            except KeyError:  # Happens when parsed an existing file.:
                pluginActions = None
            except Exception:
                pluginActions = None
            if pluginActions is not None:
                for pluginAction in pluginActions:
                    actions_panel.addFormButton(pluginAction,
                                                pluginActions[pluginAction],
                                                side="right")
                actions_panel.addFormButton("Reset",
                                            self.resetCallback,
                                            side="right")
        defect_panel = self.form.addFormPanel(grid=True)
        defect_panel.addFormButton("Create defect", self.createDefectCallback)
        defect_panel.addFormButton("Show associated command",
                                   self.showAssociatedCommand,
                                   column=1)

        self.completeModifyWindow()
def executeCommand(apiclient, toolId, local=True, allowAnyCommand=False):
    """
     remote task
    Execute the tool with the given toolId on the given calendar name.
    Then execute the plugin corresponding.
    Any unhandled exception will result in a task-failed event in the class.

    Args:
        apiclient: the apiclient instance.
        toolId: the mongo Object id corresponding to the tool to execute.
        local: boolean, set the execution in a local context
    Raises:
        Terminated: if the task gets terminated
        OSError: if the output directory cannot be created (not if it already exists)
        Exception: if an exception unhandled occurs during the bash command execution.
        Exception: if a plugin considered a failure.
    """
    # Connect to given calendar
    APIClient.setInstance(apiclient)
    toolModel = Tool.fetchObject({"_id": ObjectId(toolId)})
    command_dict = toolModel.getCommand()
    if command_dict is None and toolModel.text != "":
        command_dict = {"plugin": toolModel.plugin_used, "timeout": 0}
    msg = ""
    success, comm, fileext = apiclient.getCommandLine(toolId)
    if not success:
        print(str(comm))
        toolModel.setStatus(["error"])
        return False, str(comm)

    outputRelDir = toolModel.getOutputDir(apiclient.getCurrentPentest())
    abs_path = os.path.dirname(os.path.abspath(__file__))
    toolFileName = toolModel.name+"_" + \
            str(time.time()) # ext already added in command
    outputDir = os.path.join(abs_path, "./results", outputRelDir)
    # Create the output directory
    try:
        os.makedirs(outputDir)
    except OSError as exc:
        if exc.errno == errno.EEXIST and os.path.isdir(outputDir):
            pass
        else:
            print(str(exc))
            toolModel.setStatus(["error"])
            return False, str(exc)
    outputDir = os.path.join(outputDir, toolFileName)
    comm = comm.replace("|outputDir|", outputDir)
    toolModel.updateInfos({"cmdline": comm})

    # Get tool's wave time limit searching the wave intervals
    if toolModel.wave == "Custom commands" or local:
        timeLimit = None
    else:
        timeLimit = getWaveTimeLimit(toolModel.wave)
    # adjust timeLimit if the command has a lower timeout
    if command_dict is not None and timeLimit is not None:
        timeLimit = min(
            datetime.now() + timedelta(0, int(command_dict.get("timeout", 0))),
            timeLimit)
    ##
    try:
        print(('TASK STARTED:' + toolModel.name))
        print("Will timeout at " + str(timeLimit))
        # Execute the command with a timeout
        returncode, stdout = Utils.execute(comm, timeLimit, True)
        if returncode == -1:
            toolModel.setStatus(["timedout"])
            return False, "timedout"
    except Exception as e:
        print(str(e))
        toolModel.setStatus(["error"])
        return False, str(e)
    # Execute found plugin if there is one
    outputfile = outputDir + fileext
    plugin = "auto-detect" if command_dict["plugin"] == "" else command_dict[
        "plugin"]
    msg = apiclient.importToolResult(toolId, plugin, outputfile)
    if msg != "Success":
        #toolModel.markAsNotDone()
        print(str(msg))
        toolModel.setStatus(["error"])
        return False, str(msg)

    # Delay
    if command_dict is not None:
        if float(command_dict.get("sleep_between", 0)) > 0.0:
            msg += " (will sleep for " + \
                str(float(command_dict.get("sleep_between", 0)))+")"
        print(msg)
        time.sleep(float(command_dict.get("sleep_between", 0)))
    return True, outputfile
Beispiel #21
0
def pollex():
    """Send a command to execute for pollenisator-gui running instance
    """
    verbose = False
    if sys.argv[1] == "-v":
        verbose = True
        execCmd = shlex.join(sys.argv[2:])
    else:
        execCmd = shlex.join(sys.argv[1:])
    bin_name = shlex.split(execCmd)[0]
    if bin_name in [
            "echo", "print", "vim", "vi", "tmux", "nano", "code", "cd", "pwd",
            "cat"
    ]:
        return
    cmdName = os.path.splitext(os.path.basename(execCmd.split(" ")[0]))[0]
    apiclient = APIClient.getInstance()
    apiclient.tryConnection()
    cmdName += "::" + str(time.time()).replace(" ", "-")
    commands = Command.fetchObjects({"bin_path": {'$regex': bin_name}})
    choices = set()
    if commands is not None:
        for command in commands:
            choices.add(command.plugin)
    if len(choices) == 0:
        plugin = "Default"
    elif len(choices) == 1:
        plugin = choices.pop()
    else:
        choice = -1
        while choice == -1:
            print("Choose plugin:")
            for i, choice in enumerate(choices):
                print(f"{i+1}. {choice}")
            try:
                choice_str = input()
                choice = int(choice_str)
            except ValueError as e:
                print("You must type a valid number")
            if choice > len(choices) or choice < 1:
                choice = -1
                print("You must type a number between 1 and " +
                      str(len(choices)))
        plugin = list(choices)[choice - 1]
    print("INFO : Executing plugin " + str(plugin))
    success, comm, fileext = apiclient.getDesiredOutputForPlugin(
        execCmd, plugin)
    if not success:
        print("ERROR : An error as occured : " + str(comm))
        return
    with tempfile.TemporaryDirectory() as tmpdirname:
        outputFilePath = os.path.join(tmpdirname, cmdName)
        comm = comm.replace("|outputDir|", outputFilePath)
        if (verbose):
            print("Executing command : " + str(comm))
        returncode, stdout = Utils.execute(comm, None, True)
        #if stdout.strip() != "":
        #    print(stdout.strip())
        if not os.path.exists(outputFilePath):
            if os.path.exists(outputFilePath + fileext):
                outputFilePath += fileext
            else:
                print(
                    f"ERROR : Expected file was not generated {outputFilePath}"
                )
                return
        print(f"INFO : Uploading results {outputFilePath}")
        msg = apiclient.importExistingResultFile(
            outputFilePath, plugin,
            os.environ.get("POLLENISATOR_DEFAULT_TARGET", ""), comm)
        print(msg)
Beispiel #22
0
 def stop(self):
     """Stop an automatic scan. Will try to stop running tools."""
     apiclient = APIClient.getInstance()
     apiclient.sendStopAutoScan()
Beispiel #23
0
    def initUI(self, parent):
        """Create widgets and initialize them
        Args:
            parent: the parent tkinter widget container."""
        if self.workerTv is not None:
            self.refreshUI()
            return
        apiclient = APIClient.getInstance()
        self.parent = parent
        self.parent.configure(onfiledrop=self.dropFile)
        ### WORKER TREEVIEW : Which worker knows which commands
        lblworker = ttk.Label(self.parent, text="Workers:")
        lblworker.pack(side=tk.TOP, padx=10, pady=5, fill=tk.X)
        self.workerTv = ttk.Treeview(self.parent)
        self.workerTv['columns'] = ('workers')
        self.workerTv.heading("#0", text='Workers', anchor=tk.W)
        self.workerTv.column("#0", anchor=tk.W)
        self.workerTv.pack(side=tk.TOP, padx=10, pady=10, fill=tk.X)
        self.workerTv.bind("<Double-Button-1>", self.OnWorkerDoubleClick)
        self.workerTv.bind("<Delete>", self.OnWorkerDelete)
        btn_pane = ttk.Frame(self.parent)
        self.btn_setInclusion = ttk.Button(
            btn_pane,
            text="Include/exclude selected worker",
            command=self.setWorkerInclusion)
        self.btn_setInclusion.pack(padx=5, side=tk.RIGHT)
        self.docker_image = tk.PhotoImage(file=Utils.getIcon("baleine.png"))
        self.docker_download_image = tk.PhotoImage(
            file=Utils.getIcon("baleine_download.png"))
        self.btn_ServerWorker = ttk.Button(btn_pane,
                                           command=self.runWorkerOnServer,
                                           text="Start remote worker")
        self.btn_ServerWorker.pack(padx=5, side=tk.RIGHT)

        if git_available:
            self.btn_docker_worker = ttk.Button(
                btn_pane,
                command=self.launchDockerWorker,
                image=self.docker_image,
                style="Toolbutton")
            self.btn_docker_worker.pack(padx=5, side=tk.RIGHT)
            self.btn_docker_worker = ttk.Button(
                btn_pane,
                command=self.installDockerWorker,
                image=self.docker_download_image,
                style="Toolbutton")
            self.btn_docker_worker.pack(padx=5, side=tk.RIGHT)
        self.btn_ServerWorker = ttk.Button(btn_pane,
                                           command=self.registerAsWorker,
                                           text="Register as worker")
        self.btn_ServerWorker.pack(padx=5, side=tk.RIGHT)
        btn_pane.pack(side=tk.TOP, padx=10, pady=5)
        workers = apiclient.getWorkers()
        total_registered_commands = 0
        registeredCommands = set()
        for worker in workers:
            workername = worker["name"]
            try:
                if apiclient.getCurrentPentest() == worker.get("pentest", ""):
                    worker_node = self.workerTv.insert('',
                                                       'end',
                                                       workername,
                                                       text=workername,
                                                       image=self.ok_icon)
                else:
                    worker_node = self.workerTv.insert('',
                                                       'end',
                                                       workername,
                                                       text=workername,
                                                       image=self.nok_icon)
            except tk.TclError:
                pass
        #### TREEVIEW SCANS : overview of ongoing auto scan####
        lblscan = ttk.Label(self.parent, text="Scan overview:")
        lblscan.pack(side=tk.TOP, padx=10, pady=5, fill=tk.X)
        self.scanTv = ttk.Treeview(self.parent)
        self.scanTv['columns'] = ('Started at')
        self.scanTv.heading("#0", text='Scans', anchor=tk.W)
        self.scanTv.column("#0", anchor=tk.W)
        self.scanTv.pack(side=tk.TOP, padx=10, pady=10, fill=tk.X)
        self.scanTv.bind("<Double-Button-1>", self.OnDoubleClick)
        running_scans = Tool.fetchObjects({"status": "running"})
        for running_scan in running_scans:
            self.scanTv.insert('',
                               'end',
                               running_scan.getId(),
                               text=running_scan.name,
                               values=(running_scan.dated),
                               image=self.running_icon)
        #### BUTTONS FOR AUTO SCANNING ####
        if apiclient.getAutoScanStatus():
            self.btn_autoscan = ttk.Button(self.parent,
                                           text="Stop Scanning",
                                           command=self.stopAutoscan)
            self.btn_autoscan.pack()
        else:
            self.btn_autoscan = ttk.Button(self.parent,
                                           text="Start Scanning",
                                           command=self.startAutoscan)
            self.btn_autoscan.pack()
        btn_parse_scans = ttk.Button(self.parent,
                                     text="Parse existing files",
                                     command=self.parseFiles)
        btn_parse_scans.pack(side="top", pady=10)
        info = ttk.Label(self.parent,
                         text="You can also drop your files / folder here")
        info.pack()
Beispiel #24
0
 def OnUserDelete(self, event):
     apiclient = APIClient.getInstance()
     username = self.userTv.selection()[0]
     apiclient.deleteUser(username)
     self.userTv.delete(username)
Beispiel #25
0
 def onTreeviewSelect(self, event=None):
     """Called when a line is selected on the treeview
     Open the selected object view on the view frame.
     Args:
         _event: not used but mandatory
     """
     selection = self.selection()
     if len(selection) == 1:
         item = super().onTreeviewSelect(event)
         if isinstance(item, str):
             apiclient = APIClient.getInstance()
             self.saveState(apiclient.getCurrentPentest())
             if str(item) == "waves":
                 objView = WaveView(self, self.appli.viewframe, self.appli,
                                    WaveController(Wave()))
                 objView.openInsertWindow()
             elif str(item) == "mycommands":
                 user = apiclient.getUser()
                 objView = CommandView(
                     self, self.appli.viewframe, self.appli,
                     CommandController(
                         Command({
                             "indb": apiclient.getCurrentPentest(),
                             "owner": user
                         })))
                 objView.openInsertWindow()
             elif str(item) == "workercommands":
                 user = "******"
                 objView = CommandView(
                     self, self.appli.viewframe, self.appli,
                     CommandController(
                         Command({
                             "indb": apiclient.getCurrentPentest(),
                             "owner": user
                         })))
                 objView.openInsertWindow()
             elif str(item) == "mygroupcommands":
                 objView = CommandGroupView(
                     self, self.appli.viewframe, self.appli,
                     CommandGroupController(
                         CommandGroup({
                             "indb": apiclient.getCurrentPentest(),
                             "owner": apiclient.getUser()
                         })))
                 objView.openInsertWindow()
             elif str(item) == "workergroupcommands":
                 objView = CommandGroupView(
                     self, self.appli.viewframe, self.appli,
                     CommandGroupController(
                         CommandGroup({
                             "indb": apiclient.getCurrentPentest(),
                             "owner": "Worker"
                         })))
                 objView.openInsertWindow()
             elif str(item) == "ips":
                 objView = MultipleIpView(self, self.appli.viewframe,
                                          self.appli, IpController(Ip()))
                 objView.openInsertWindow()
             elif "intervals" in str(item):
                 wave = Wave.fetchObject({
                     "_id":
                     ObjectId(IntervalView.treeviewListIdToDb(item))
                 })
                 objView = IntervalView(
                     self, self.appli.viewframe, self.appli,
                     IntervalController(Interval().initialize(wave.wave)))
                 objView.openInsertWindow()
             elif "scopes" in str(item):
                 wave = Wave.fetchObject(
                     {"_id": ObjectId(ScopeView.treeviewListIdToDb(item))})
                 objView = MultipleScopeView(
                     self, self.appli.viewframe, self.appli,
                     ScopeController(Scope().initialize(wave.wave)))
                 objView.openInsertWindow()
         else:
             self.openModifyWindowOf(item)
     elif len(selection) > 1:
         # Multi select:
         multiView = MultiSelectionView(self, self.appli.viewframe,
                                        self.appli)
         for widget in self.appli.viewframe.winfo_children():
             widget.destroy()
         multiView.form.clear()
         multiView.openModifyWindow()
Beispiel #26
0
 def addWorkerCommandsToWave(self):
     apiclient = APIClient.getInstance()
     apiclient.addWorkerCommandsToWave(self.getId())
Beispiel #27
0
 def getDefectTable(cls):
     """Return the table of global defects sorted by their index field
     Returns:
         A list of Defect
     """
     return APIClient.getInstance().getDefectTable()
Beispiel #28
0
 def delete(self):
     """
     Delete the tool represented by this model in database.
     """
     apiclient = APIClient.getInstance()
     apiclient.delete("tools", ObjectId(self._id))
Beispiel #29
0
 def isMyCommand(self):
     user = APIClient.getInstance().getUser()
     return user == self.owner
 def removeSelectedFromMyCommands(self, event=None):
     apiclient = APIClient.getInstance()
     for selected in self.appliTw.selection():
         apiclient.removeCommandFromMyCommands(selected)