def userCommand(self, command_option, user):
     if user is None:
         selection_users = self.tvUsers.selection()
         if len(selection_users) >= 1:
             item = self.tvUsers.item(selection_users[0])
             user = (item["values"][1], item["text"], item["values"][0])
         else:
             user = None
     searching = [r"ask_text:([^:\|]+)", "computers_as_file"]
     for keyword in searching:
         s = re.search(r"\|" + keyword + r"\|", command_option)
         if s is not None:
             if keyword == "computers_as_file":
                 filepath = self.exportAllComputersAsFile()
                 command_option = command_option.replace(
                     s.group(0), filepath)
             elif "|ask_text:" in s.group(0):
                 what = s.group(1)
                 dialog = ChildDialogAskText(self.tkApp, what)
                 self.tkApp.wait_window(dialog.app)
                 fp = tempfile.mkdtemp()
                 filepath = os.path.join(fp, what + ".txt")
                 with open(filepath, "w") as f:
                     f.write(dialog.rvalue)
                 command_option = command_option.replace(
                     s.group(0), filepath)
         command_option = command_option.replace("|domain|", user[0])
         command_option = command_option.replace("|username|", user[1])
         command_option = command_option.replace("|password|", user[2])
     Utils.executeInExternalTerm(command_option)
 def openPathForUser(self):
     selection = self.treevw.selection()
     if selection:
         folder = os.path.join(self.getScriptsDir(), selection[0])
     else:
         folder = self.getScriptsDir()
     Utils.openPathForUser(folder)
Example #3
0
 def downloadResultFile(self, _event=None):
     """Callback for tool click #TODO move to ToolController
     Download the tool result file and asks the user if he or she wants to open it. 
     If OK, tries to open it
     Args:
         _event: not used 
     """
     apiclient = APIClient.getInstance()
     dialog = ChildDialogInfo(self.appliViewFrame, "Download Started",
                              "Downloading...")
     dialog.show()
     abs_path = os.path.dirname(os.path.abspath(__file__))
     outputDir = os.path.join(abs_path, "../../results")
     path = self.controller.getOutputDir(apiclient.getCurrentPentest())
     path = apiclient.getResult(self.controller.getDbId(),
                                os.path.join(outputDir, path))
     dialog.destroy()
     if path is not None:
         if os.path.isfile(path):
             dialog = ChildDialogQuestion(
                 self.appliViewFrame,
                 "Download completed",
                 "The file has been downloaded.\n Would you like to open it?",
                 answers=["Open", "Cancel"])
             self.appliViewFrame.wait_window(dialog.app)
             if dialog.rvalue == "Open":
                 Utils.openPathForUser(path)
                 return
             else:
                 return
         path = None
     if path is None:
         tkinter.messagebox.showerror(
             "Download failed", "the file does not exist on sftp server")
 def shareCommand(self, command_option):
     selected = self.tvShares.selection()[0]
     parent_iid = self.tvShares.parent(selected)
     if not parent_iid:  # file in share
         return
     ip = self.tvShares.item(parent_iid)["text"]
     item_values = self.tvShares.item(selected)["values"]
     domain = item_values[-2] if item_values[-2] != "" else None
     user = item_values[-1]
     share_name = item_values[0]
     apiclient = APIClient.getInstance()
     apiclient.getCurrentPentest()
     user_o = apiclient.findInDb(apiclient.getCurrentPentest(),
                                 ActiveDirectory.collName, {
                                     "type": "user",
                                     "domain": domain,
                                     "username": user
                                 }, False)
     if user_o is None:
         tk.messagebox.showerror(
             "user not found",
             "User " + str(domain) + "\\" + str(user) + " was not found")
         return
     user = "" if user is None else user
     domain = "" if domain is None else domain
     command_option = command_option.replace("|username|", user)
     command_option = command_option.replace("|domain|", domain)
     command_option = command_option.replace("|password|",
                                             user_o["password"])
     command_option = command_option.replace(
         "|share|", share_name.replace("\\\\", "\\"))
     command_option = command_option.replace("|ip|", ip)
     Utils.executeInExternalTerm(command_option)
Example #5
0
    def openMultiInsertWindow(self, addButtons=True):
        """
        Creates a tkinter form using Forms classes. This form aims to insert many Defects
        Args:
            addButtons: boolean value indicating that insertion buttons should be visible. Default to True
        """
        settings = self.mainApp.settings
        settings.reloadSettings()
        results, msg = APIClient.searchDefect("")
        default_values = {}

        if results is not None:
            for result in results:
                if result is not None:
                    default_values[result["title"]] = result["risk"]
            self.browse_top_treevw = self.form.addFormTreevw(
                "Defects", ("Title", "Risk"),
                default_values,
                side="top",
                fill="both",
                width=400,
                height=8,
                status="readonly",
                binds={
                    "<Double-Button-1>": self.doubleClickDefectView,
                    "<Delete>": self.deleteDefectTemplate
                })
        self.buttonUpImage = ImageTk.PhotoImage(
            Image.open(Utils.getIconDir() + 'up-arrow.png'))
        self.buttonDownImage = ImageTk.PhotoImage(
            Image.open(Utils.getIconDir() + 'down-arrow.png'))
        # use self.buttonPhoto
        buttonPan = self.form.addFormPanel(side="top",
                                           anchor="center",
                                           fill="none")
        btn_down = buttonPan.addFormButton("V",
                                           self.moveDownMultiTreeview,
                                           side="left",
                                           anchor="center",
                                           image=self.buttonDownImage)
        btn_down = buttonPan.addFormButton("Î",
                                           self.moveUpMultiTreeview,
                                           side="right",
                                           anchor="center",
                                           image=self.buttonUpImage)
        default_values = {}
        self.browse_down_treevw = self.form.addFormTreevw("Defects",
                                                          ("Title", "Risk"),
                                                          default_values,
                                                          side="bottom",
                                                          fill="both",
                                                          width=400,
                                                          height=8,
                                                          status="readonly")
        if addButtons:
            self.completeInsertWindow()
        else:
            self.showForm()
    def __init__(self, parent):
        """
            parent: the tkinter parent view to use for this window construction.
        """
        self.parent = parent
        self.app = tk.Toplevel(parent)
        self.app.title("Scripts Manager")
        self.app.resizable(True, True)
        self.rvalue = None
        appFrame = ttk.Frame(self.app)
         #PANED PART
        self.paned = tk.PanedWindow(appFrame, height=300)
        #RIGHT PANE : TAble
        self.viewframe = ttk.Frame(self.paned)
        self.file_tree = CheckboxTreeview(self.viewframe)
        self.file_tree['columns'] = ('name', 'category')
        self.file_tree.heading('#0', text='Name')
        self.file_tree.column("#0", stretch=tk.YES, minwidth=300, width=300)
        self.file_tree.heading('#1', text='Category')
        self.file_tree.column("#1", stretch=tk.YES, minwidth=300, width=300)
        self.file_tree.pack(fill=tk.BOTH, expand=True)
        btn_pane = ttk.Frame(self.viewframe)
        self.execute_icone = tk.PhotoImage(file = Utils.getIcon("execute.png"))
        btn_execute = ttk.Button(btn_pane, text="Execute", image=self.execute_icone, command=self.executedSelectedScripts, tooltip="Execute all selected scripts", style="Toolbutton")        
        btn_execute.pack(side=tk.RIGHT, padx=3, pady=5)
        self.open_folder_icone = tk.PhotoImage(file = Utils.getIcon("folder.png"))
        btn_openPathForUser = ttk.Button(btn_pane, text="Execute", image=self.open_folder_icone, command=self.openPathForUser, tooltip="Open scripts folder", style="Toolbutton")        
        btn_openPathForUser.pack(side=tk.RIGHT, padx=3, pady=5)
        
        btn_pane.pack(fill=tk.X, side=tk.BOTTOM, anchor=tk.E)
        #LEFT PANE : Treeview
        self.frameTw = ttk.Frame(self.paned)
        self.treevw = ttk.Treeview(self.frameTw)
        self.treevw.pack()
        scbVSel = ttk.Scrollbar(self.frameTw,
                                orient=tk.VERTICAL,
                                command=self.treevw.yview)
        self.treevw.configure(yscrollcommand=scbVSel.set)
        self.treevw.grid(row=0, column=0, sticky=tk.NSEW)
        scbVSel.grid(row=0, column=1, sticky=tk.NS)
        self.treevw.grid(row=0, column=0, sticky=tk.NSEW)
        scbVSel.grid(row=0, column=1, sticky=tk.NS)
        self.paned.add(self.frameTw)
        self.paned.add(self.viewframe)
        self.paned.pack(fill=tk.BOTH, expand=1)
        self.frameTw.rowconfigure(0, weight=1) # Weight 1 sur un layout grid, sans ça le composant ne changera pas de taille en cas de resize
        self.frameTw.columnconfigure(0, weight=1) # Weight 1 sur un layout grid, sans ça le composant ne changera pas de taille en cas de resize

        appFrame.pack(fill=tk.BOTH, ipady=10, ipadx=10, expand=True)

        self.treevw.bind("<<TreeviewSelect>>", self.onTreeviewSelect)
        try:
            self.app.wait_visibility()
            self.app.focus_force()
            self.app.lift()
        except tk.TclError:
            pass
        self.refreshUI()
Example #7
0
 def openTerminal(cls, default_target=""):
     if cls.settings.isTrapCommand():
         comm = "bash --rcfile " + os.path.join(
             Utils.getMainDir(), "setupTerminalForPentest.sh")
     else:
         comm = "bash"
     env = {
         "POLLENISATOR_DEFAULT_TARGET": default_target,
     }
     res = Utils.executeInExternalTerm(comm, with_bash=False, env=env)
    def doInsert(self, values):
        """
        Insert the Scope represented by this model in the database with the given values.

        Args:
            values: A dictionary crafted by MultipleScopeView or ScopeView containg all form fields values needed.

        Returns:
            {
                '_id': The mongo ObjectId _id of the inserted command document.
                'nbErrors': The number of objects that has not been inserted in database due to errors.
            }
        """
        # Only multi insert exists at the moment for Scope
        # Get form values
        wave = values["wave"]
        ret = []
        total = 0
        accepted = 0
        insert_setting = values["Settings"]
        split_range_setting = values.get("Split", False)
        for line in values["Scopes"].split("\n"):
            if line.strip() != "":
                # Insert in database
                scopeToAdd = line.strip()
                if Utils.isIp(scopeToAdd):
                    scopeToAdd += "/32"
                if Utils.isNetworkIp(scopeToAdd):
                    if split_range_setting:
                        network_ips = Utils.splitRange(scopeToAdd)
                        if len(network_ips) == 0:
                            model = Scope().initialize(wave, scopeToAdd, "")
                            inserted_res, iid = model.addInDb()
                        else:
                            for network_ip in network_ips:
                                model = Scope().initialize(
                                    wave, str(network_ip), "")
                                inserted_res, iid = model.addInDb()
                                if inserted_res:
                                    accepted += 1
                                    ret.append(iid)
                                total += 1
                    else:
                        model = Scope().initialize(wave, scopeToAdd, "")
                        inserted_res, iid = model.addInDb()
                else:
                    model = Scope().initialize(wave, scopeToAdd, "")
                    inserted_res, iid = model.addDomainInDb(insert_setting)
                if inserted_res == 1:
                    accepted += 1
                    ret.append(iid)
                total += 1
        return ret, total - accepted  # nb errors = total - accepted
Example #9
0
 def add_path_listbox(self, event):
     data = Utils.drop_file_event_parser(event)
     for d in data:
         if os.path.isfile(d) and "file" in self.modes:
             self.listbox.insert("end", d)
         elif os.path.isdir(d) and "directory" in self.modes:
             self.listbox.insert("end", d)
Example #10
0
 def __init__(self, parent, settings):
     self.proc = None
     self.s = None
     self.__class__.settings = settings
     self.img = ImageTk.PhotoImage(Image.open(Utils.getIcon("help.png")))
     manager = Manager()
     self.exiting = manager.Value('i', 0)
Example #11
0
 def openModifyWindow(self, addButtons=True):
     """
     Creates a tkinter form using Forms classes.
     This form aims to update or delete an existing Defect
     Args:
         addButtons: boolean value indicating that insertion buttons should be visible. Default to True
     """
     modelData = self.controller.getData()
     topPanel = self.form.addFormPanel(grid=True)
     topPanel.addFormSearchBar("Search Remark",
                               APIClient.searchRemark,
                               topPanel,
                               row=0,
                               column=1,
                               autofocus=False)
     self.imgTypeForm = topPanel.addFormImage(
         Utils.getIconDir() + RemarkView.getIconName(modelData["type"]),
         row=1)
     self.comboTypeForm = topPanel.addFormCombo(
         "Type", ["Positive", "Neutral", "Negative"],
         column=1,
         row=1,
         default=modelData["type"],
         binds={"<<ComboboxSelected>>": self.updateImage})
     topPanel.addFormStr("Title",
                         r".+",
                         modelData["title"],
                         width=50,
                         row=1,
                         column=2)
     if addButtons:
         self.completeModifyWindow()
     else:
         self.showForm()
Example #12
0
    def __init__(self, parent, settings):
        """
        Constructor
        """
        self.dashboardFrame = None
        self.parent = None
        self.treevw = None
        self.style = None
        self.ips = None
        self.ports = None
        self.tools = None

        iconPath = Utils.getIconDir()
        self.icons = {}
        self.icons["tool"] = ImageTk.PhotoImage(
            Image.open(iconPath + "tool.png"))
        self.icons["cross"] = ImageTk.PhotoImage(
            Image.open(iconPath + "cross.png"))
        self.icons["running"] = ImageTk.PhotoImage(
            Image.open(iconPath + "running.png"))
        self.icons["done"] = ImageTk.PhotoImage(
            Image.open(iconPath + "done_tool.png"))
        self.icons["error"] = ImageTk.PhotoImage(
            Image.open(iconPath + "error_tool.png"))
        self.icons["ready"] = ImageTk.PhotoImage(
            Image.open(iconPath + "waiting.png"))
        self.icons["Not ready"] = ImageTk.PhotoImage(
            Image.open(iconPath + "cross.png"))
Example #13
0
 def updateImage(self, _event=None):
     """Callback when ease or impact is modified.
     Calculate new resulting risk value
     Args
         _event: mandatory but not used
     """
     typeof = self.comboTypeForm.getValue()
     self.imgTypeForm.setImage(Utils.getIconDir() +
                               RemarkView.getIconName(typeof))
    def __init__(self, default_path=""):
        """
        Open a child dialog of a tkinter application to ask details about
        existing files parsing.

        Args:
            default_path: a default path to be added
        """
        self.app = tkinterDnD.Tk()
        Utils.setStyle(self.app)
        self.app.title("Upload result file")
        self.rvalue = None
        self.default = default_path
        appFrame = ttk.Frame(self.app)
        apiclient = APIClient.getInstance()
        self.form = FormPanel()
        self.form.addFormLabel("Import one file or choose a directory",
                               "",
                               side=tk.TOP)
        self.form.addFormFile("File",
                              ".+",
                              self.default,
                              width=50,
                              side=tk.TOP,
                              mode="file|directory")
        self.form.addFormLabel("Plugins", side=tk.TOP)
        self.form.addFormCombo("Plugin",
                               ["auto-detect"] + apiclient.getPlugins(),
                               "auto-detect",
                               side=tk.TOP)
        self.form.addFormButton("Parse", self.onOk, side=tk.RIGHT)

        self.form.constructView(appFrame)
        appFrame.pack(ipadx=10, ipady=10)

        try:
            self.app.wait_visibility()
            self.app.focus_force()
            self.app.grab_set()
            self.app.lift()
        except tk.TclError:
            pass
        self.app.mainloop()
        self.app.destroy()
Example #15
0
 def isLaunchableNow(self):
     """Returns True if the tool matches criteria to be launched 
     (current time matches one of interval object assigned to this wave)
     Returns:
         bool
     """
     intervals = Interval.fetchObjects({"wave": self.wave})
     for intervalModel in intervals:
         if Utils.fitNowTime(intervalModel.dated, intervalModel.datef):
             return True
     return False
Example #16
0
    def checkDomainFit(cls, waveName, domain):
        """
        Check if a found domain belongs to one of the scope of the given wave.

        Args:
            waveName: The wave id (name) you want to search for a validating scope
            domain: The found domain.

        Returns:
            boolean
        """
        # Checking settings for domain check.
        settings = Settings()
        # get the domain ip so we can search for it in ipv4 range scopes.
        domainIp = Utils.performLookUp(domain)
        apiclient = APIClient.getInstance()
        scopesOfWave = apiclient.find("scopes", {"wave": waveName})
        for scopeOfWave in scopesOfWave:
            scopeIsANetworkIp = Utils.isNetworkIp(scopeOfWave["scope"])
            if scopeIsANetworkIp:
                if settings.db_settings.get("include_domains_with_ip_in_scope", False):
                    if Ip.checkIpScope(scopeOfWave["scope"], domainIp):
                        return True
            else:  # If scope is domain
                # check if we include subdomains
                if settings.db_settings.get("include_all_domains", False):
                    return True
                else:
                    splitted_domain = domain.split(".")
                    # Assuring to check only if there is a domain before the tld (.com, .fr ... )
                    topDomainExists = len(splitted_domain) > 2
                    if topDomainExists:
                        if settings.db_settings.get("include_domains_with_topdomain_in_scope", False):
                            if splitted_domain[1:] == scopeOfWave["scope"].split("."):
                                return True
                    if settings.db_settings.get("include_domains_with_ip_in_scope", False):
                        inRangeDomainIp = Utils.performLookUp(
                            scopeOfWave["scope"])
                        if str(inRangeDomainIp) == str(domainIp):
                            return True
        return False
    def __init__(self, parent, info="Choose a file", default_path=""):
        """
        Open a child dialog of a tkinter application to ask details about
        existing files parsing.

        Args:
            default_path: a default path to be added
        """
        self.app = tkinterDnD.Tk()
        Utils.setStyle(self.app)
        self.app.title(info)
        self.rvalue = None
        self.default = default_path
        appFrame = ttk.Frame(self.app)
        self.form = FormPanel()
        self.form.addFormLabel("Choose one file", info, side=tk.TOP)
        self.fileForm = self.form.addFormFile("File",
                                              ".+",
                                              '',
                                              width=50,
                                              side=tk.TOP,
                                              mode="file")
        self.button = self.form.addFormButton("Cancel",
                                              self.onError,
                                              side=tk.RIGHT)
        self.form.addFormButton("OK", self.onOk, side=tk.RIGHT)

        self.form.constructView(appFrame)
        appFrame.pack(ipadx=10, ipady=10)

        try:
            self.app.wait_visibility()
            self.app.focus_force()
            self.app.grab_set()
            self.app.lift()
        except tk.TclError:
            pass
        self.app.mainloop()
        self.app.destroy()
Example #18
0
    def getIcon(cls, typeOfRemark):
        """
        Load the object icon in cache if it is not yet done, and returns it

        Return:
            Returns the icon representing this object.
        """
        cache = cls.cached_icons.get(typeOfRemark, None)

        if cache is None:
            from PIL import Image, ImageTk
            path = Utils.getIconDir() + cls.getIconName(typeOfRemark)
            cls.cached_icons[typeOfRemark] = ImageTk.PhotoImage(
                Image.open(path))
            return cls.cached_icons[typeOfRemark]
        return cache
def getWaveTimeLimit(waveName):
    """
    Return the latest time limit in which this tool fits. The tool should timeout after that limit

    Returns:
        Return the latest time limit in which this tool fits.
    """
    intervals = Interval.fetchObjects({"wave": waveName})
    furthestTimeLimit = datetime.now()
    for intervalModel in intervals:
        if Utils.fitNowTime(intervalModel.dated, intervalModel.datef):
            endingDate = intervalModel.getEndingDate()
            if endingDate is not None:
                if endingDate > furthestTimeLimit:
                    furthestTimeLimit = endingDate
    return furthestTimeLimit
Example #20
0
 def refreshUI(self):
     for widget in self.treevw.winfo_children():
         widget.destroy()
     script_dir = self.getScriptsDir()
     if self.__class__.folder_icon is None:
         self.__class__.folder_icon = ImageTk.PhotoImage(Image.open(Utils.getIcon("folder.png")))
     parent = self.treevw.insert("", "end", " ", text="Scripts", image=self.__class__.folder_icon, open=True)
     self.treevw.focus(parent)
     self.treevw.selection_set(parent)
     for root, subFolders, files in os.walk(script_dir):
         root_name = root.replace(script_dir, "")
         for folder in subFolders:
             if folder.startswith("__") or folder.endswith("__"):
                 continue
             folder_iid = os.path.join(root_name, folder)
             parent_node = parent if root_name == "" else root_name
             self.treevw.insert(parent_node, "end", folder_iid, text=folder, image=self.__class__.folder_icon)
     self.openScriptFolderView()
Example #21
0
 def viewProof(self, _event, obj):
     """Callback when view proof is clicked.
     Download and display the file 
     Args
         _event: mandatory but not used
         obj: the clicked index proof
     """
     proof_local_path = self.controller.getProof(obj)
     if proof_local_path is not None:
         if os.path.isfile(proof_local_path):
             res = Utils.openPathForUser(proof_local_path)
             if not res:
                 tk.messagebox.showerror("Could not open",
                                         "Failed to open this file.")
                 proof_local_path = None
                 return
     if proof_local_path is None:
         tk.messagebox.showerror("Download failed",
                                 "the file does not exist on sftp server")
Example #22
0
 def dropFile(self, event):
     # This function is called, when stuff is dropped into a widget
     data = Utils.drop_file_event_parser(event)
     self.parseFiles(data)
Example #23
0
def start_docker(dialog, force_reinstall):
    worker_subdir = os.path.join(Utils.getMainDir(), "PollenisatorWorker")
    if os.path.isdir(worker_subdir) and force_reinstall:
        shutil.rmtree(worker_subdir)
    if not os.path.isdir(worker_subdir):
        git.Git(Utils.getMainDir()).clone(
            "https://github.com/fbarre96/PollenisatorWorker.git")
    shutil.copyfile(
        os.path.join(Utils.getConfigFolder(), "client.cfg"),
        os.path.join(Utils.getMainDir(),
                     "PollenisatorWorker/config/client.cfg"))
    dialog.update(
        1,
        msg=
        "Building worker docker could take a while (1~10 minutes depending on internet connection speed)..."
    )
    try:
        client = docker.from_env()
        clientAPI = docker.APIClient()
    except Exception as e:
        dialog.destroy()
        tk.messagebox.showerror("Unable to launch docker", e)
        return
    image = client.images.list("pollenisatorworker")
    if len(image) > 0 and force_reinstall:
        force_reinstall = tk.messagebox.askyesno(
            "Force reinstall",
            "A pollenisator worker image has been found. Are you sure you want to rebuild it ?"
        )
    if len(image) == 0 or force_reinstall:
        try:
            log_generator = clientAPI.build(path=os.path.join(
                Utils.getMainDir(), "PollenisatorWorker/"),
                                            rm=True,
                                            tag="pollenisatorworker",
                                            nocache=force_reinstall)
            change_max = None
            for byte_log in log_generator:
                updated_dialog = False
                log_line = byte_log.decode("utf-8").strip()
                if log_line.startswith("{\"stream\":\""):
                    log_line = log_line[len("{\"stream\":\""):-4]
                    matches = re.search(r"Step (\d+)/(\d+)", log_line)
                    if matches is not None:
                        if change_max is None:
                            change_max = int(matches.group(2))
                            dialog.progressbar["maximum"] = change_max
                        dialog.update(int(matches.group(1)),
                                      log=log_line + "\n")
                        updated_dialog = True
        except docker.errors.BuildError as e:
            dialog.destroy()
            tk.messagebox.showerror("Build docker error",
                                    "Building error:\n" + str(e))
            return
        image = client.images.list("pollenisatorworker")
    if len(image) == 0:
        tk.messagebox.showerror(
            "Building docker failed",
            "The docker build command failed, try to install manually...")
        return
    dialog.update(2, msg="Starting worker docker ...")
    clientCfg = Utils.loadClientConfig()
    if clientCfg["host"] == "localhost" or clientCfg["host"] == "127.0.0.1":
        network_mode = "host"
    else:
        network_mode = None
    container = client.containers.run(
        image=image[0],
        network_mode=network_mode,
        volumes={
            os.path.join(Utils.getMainDir(), "PollenisatorWorker"): {
                'bind': '/home/Pollenisator',
                'mode': 'rw'
            }
        },
        detach=True)
    dialog.update(3, msg="Checking if worker is running")
    print(container.id)
    if container.logs() != b"":
        print(container.logs())
    dialog.destroy()
Example #24
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()
Example #25
0
    def initUI(self, parent):
        """
        Initialize window and widgets.
        """
        if self.parent is not None:  # Already initialized
            self.reset()
            self.fillWithFixes()
            return
        self.parent = parent
        ###Fixes TABLE ###
        self.rowHeight = 20
        self.style = ttk.Style()
        self.style.configure('Report.Treeview', rowheight=self.rowHeight)

        # FIXES TREEVW
        fixesLabelFrame = ttk.LabelFrame(parent, text="Fixes table")
        self.paned = tk.PanedWindow(fixesLabelFrame,
                                    orient=tk.VERTICAL,
                                    height=400)
        self.frameTw = ttk.Frame(self.paned)
        self.treevw = ttk.Treeview(self.frameTw,
                                   style='Report.Treeview',
                                   height=0)
        self.treevw['columns'] = ('execution', 'gain')
        self.treevw.heading("#0", text='Title', anchor=tk.W)
        self.treevw.column("#0", anchor=tk.W, width=150)
        self.treevw.heading('execution', text='Execution')
        self.treevw.column('execution', anchor='center', width=40)
        self.treevw.heading('gain', text='Gain')
        self.treevw.column('gain', anchor='center', width=40)

        self.treevw.bind("<Double-Button-1>", self.OnDoubleClick)
        self.treevw.bind("<Delete>", self.deleteSelectedItem)
        self.treevw.bind("<Alt-Down>", self.bDown)
        self.treevw.bind("<Alt-Up>", self.bUp)
        self.treevw.bind("<ButtonPress-1>", self.dragStart)
        self.treevw.bind("<ButtonRelease-1>", self.dragRelease, add='+')
        self.treevw.bind("<B1-Motion>", self.dragMove, add='+')
        self.treevw.grid(row=0, column=0, sticky=tk.NSEW)
        scbVSel = ttk.Scrollbar(self.frameTw,
                                orient=tk.VERTICAL,
                                command=self.treevw.yview)
        self.treevw.configure(yscrollcommand=scbVSel.set)
        scbVSel.grid(row=0, column=1, sticky=tk.NS)
        self.frameTw.pack(side=tk.TOP, fill=tk.BOTH, padx=5, pady=10)
        self.frameTw.columnconfigure(0, weight=1)
        self.frameTw.rowconfigure(0, weight=1)
        ### OFFICE EXPORT FRAME ###
        belowFrame = ttk.Frame(self.paned)
        frameBtn = ttk.Frame(belowFrame)
        self.buttonUpImage = ImageTk.PhotoImage(
            Image.open(Utils.getIconDir() + 'up-arrow.png'))
        self.buttonDownImage = ImageTk.PhotoImage(
            Image.open(Utils.getIconDir() + 'down-arrow.png'))
        # use self.buttonPhoto
        btn_down = ttk.Button(frameBtn,
                              image=self.buttonDownImage,
                              command=self.bDown)
        btn_down.pack(side="left", anchor="center")
        btn_up = ttk.Button(frameBtn,
                            image=self.buttonUpImage,
                            command=self.bUp)
        btn_up.pack(side="left", anchor="center")
        btn_delFix = ttk.Button(frameBtn,
                                text="Remove selection",
                                command=self.deleteSelectedItem)
        btn_delFix.pack(side=tk.RIGHT, padx=5)
        btn_addFix = ttk.Button(frameBtn,
                                text="Add a fix",
                                command=self.addFixCallback)
        btn_addFix.pack(side=tk.RIGHT, padx=5)
        frameBtn.pack(side=tk.TOP, pady=5)
        belowFrame.pack(side=tk.TOP, fill=tk.BOTH)
        self.paned.add(self.frameTw)
        self.paned.add(belowFrame)
        self.paned.pack(fill=tk.BOTH, expand=1)
        fixesLabelFrame.pack(side=tk.TOP, fill=tk.BOTH, pady=10)
        self.fillWithFixes()
Example #26
0
 def getScriptsDir(self):
     return os.path.join(Utils.getMainDir(), "scripts/")
Example #27
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)
 def computerCommand(self, command_option, ips=None, user=None):
     if ips is None:
         ips = []
         selection = self.tvComputers.selection()
         for selected in selection:
             item = self.tvComputers.item(selected)
             ip = item["text"]
             ips.append(ip)
     if user is None:
         selection_users = self.tvUsers.selection()
         if len(selection_users) >= 1:
             item = self.tvUsers.item(selection_users[0])
             user = (item["values"][1], item["text"], item["values"][0])
         else:
             user = None
     for ip in ips:
         searching = [
             "wordlist", r"ask_text:([^:\|]+)", "users_as_file", "ip"
         ]
         for keyword in searching:
             s = re.search(r"\|" + keyword + r"\|", command_option)
             if s is not None:
                 if keyword == "wordlist":
                     dialog = ChildDialogAskFile(self.tkApp,
                                                 f"Choose a wordlist file")
                     command_option = command_option.replace(
                         s.group(0), dialog.rvalue)
                 elif keyword == "ip":
                     command_option = command_option.replace(s.group(0), ip)
                 elif keyword == "users_as_file":
                     filepath = self.exportAllUsersAsFile()
                     command_option = command_option.replace(
                         s.group(0), filepath)
                 elif "|ask_text:" in s.group(0):
                     what = s.group(1)
                     dialog = ChildDialogAskText(self.tkApp, what)
                     self.tkApp.wait_window(dialog.app)
                     fp = tempfile.mkdtemp()
                     filepath = os.path.join(fp, what + ".txt")
                     with open(filepath, "w") as f:
                         f.write(dialog.rvalue)
                     command_option = command_option.replace(
                         s.group(0), filepath)
         user_searching = {
             "domain": None,
             "username": None,
             "password": None
         }
         if any(
                 map(
                     lambda user_keyword: f"|{user_keyword}|" in
                     command_option, user_searching)):
             if user is not None and len(user) == 3:
                 command_option = command_option.replace(
                     "|domain|", user[0])
                 command_option = command_option.replace(
                     "|username|", user[1])
                 command_option = command_option.replace(
                     "|password|", user[2])
             else:
                 for user_keyword in user_searching:
                     if f"|{user_keyword}|" in command_option:
                         dialog = ChildDialogAskText(self.parent,
                                                     "Enter " +
                                                     str(user_keyword),
                                                     multiline=False)
                         self.parent.wait_window(dialog.app)
                         if dialog.rvalue is None:
                             return
                         command_option = command_option.replace(
                             f"|{user_keyword}|", dialog.rvalue)
         Utils.executeInExternalTerm(command_option)
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
Example #30
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()