def delete(pentest, interval_iid): mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(pentest) interval_o = ServerInterval(pentest, mongoInstance.find("intervals", {"_id": ObjectId(interval_iid)}, False)) res = mongoInstance.delete("intervals", {"_id": ObjectId(interval_iid)}, False) parent_wave = mongoInstance.find("waves", {"wave": interval_o.wave}, False) if parent_wave is not None: mongoInstance.notify(pentest, "waves", parent_wave["_id"], "update", "") other_intervals = mongoInstance.find("waves", {"wave": interval_o.wave}) no_interval_in_time = True for other_interval in other_intervals: other_interval = ServerInterval(pentest, other_interval) if fitNowTime(other_interval.dated, other_interval.datef): no_interval_in_time = False break if no_interval_in_time: tools = mongoInstance.find("tools", {"wave": interval_o.wave}) for tool in tools: tool = ServerTool(pentest, tool) tool.setOutOfTime(pentest) if res is None: return 0 else: return res.deleted_count
def getNotDoneTools(pentest, waveName): """Returns a set of tool mongo ID that are not done yet. """ notDoneTools = set() tools = ServerTool.fetchObjects(pentest, { "wave": waveName, "ip": "", "dated": "None", "datef": "None" }) for tool in tools: notDoneTools.add(tool.getId()) scopes = ServerScope.fetchObjects(pentest, {"wave": waveName}) for scope in scopes: scopeId = scope.getId() ips = ServerIp.getIpsInScope(pentest, scopeId) for ip in ips: tools = ServerTool.fetchObjects(pentest, { "wave": waveName, "ip": ip.ip, "dated": "None", "datef": "None" }) for tool in tools: notDoneTools.add(tool.getId()) return notDoneTools
def importExistingFile(pentest, upfile, body): from pollenisator.server.ServerModels.Tool import ServerTool plugin = body.get("plugin", "auto-detect") mongoInstance.connectToDb(pentest) md5File = md5(upfile.stream) upfile.stream.seek(0) name = upfile.filename.replace("/", "_") toolName = os.path.splitext(os.path.basename(name))[ 0] + md5File[:6] results = {} if plugin == "auto-detect": # AUTO DETECT foundPlugin = "Ignored" for pluginName in listPlugin(): if foundPlugin != "Ignored": break mod = loadPlugin(pluginName) if mod.autoDetectEnabled(): notes, tags, lvl, targets = mod.Parse(pentest, upfile.stream) upfile.stream.seek(0) if notes is not None and tags is not None: foundPlugin = pluginName results[foundPlugin] = results.get( foundPlugin, 0) + 1 else: # SET PLUGIN mod = loadPlugin(plugin) notes, tags, lvl, targets = mod.Parse(pentest, upfile.stream) results[plugin] = results.get( plugin, 0) + 1 # IF PLUGIN FOUND SOMETHING if notes is not None and tags is not None: # ADD THE RESULTING TOOL TO AFFECTED for target in targets.values(): date = datetime.now().strftime("%d/%m/%Y %H:%M:%S") if target is None: scope = None ip = None port = None proto = None else: scope = target.get("scope", None) ip = target.get("ip", None) port = target.get("port", None) proto = target.get("proto", None) mongoInstance.connectToDb(pentest) mongoInstance.insert("waves", {"wave":"Imported", "wave_commands":[]}) tool_m = ServerTool().initialize(toolName, "Imported", scope=scope, ip=ip, port=port, proto=proto, lvl=lvl, text="", dated=date, datef=date, scanner_ip="Imported", status="done", notes=notes, tags=tags) ret = tool_m.addInDb() upfile.stream.seek(0) msg, status, filepath = _upload(pentest, str(ret["iid"]), "result", upfile) if status == 200: mongoInstance.update("tools", {"_id":ObjectId(ret["iid"])}, {"resultfile": filepath}) return results
def setToolsInTime(self): """Get all OOT (Out of Time) tools in this wave and checks if this Interval makes them in time. If it is the case, set them in time. """ if fitNowTime(self.dated, self.datef): tools = ServerTool.fetchObjects(self.pentest, {"wave": self.wave, "status": "OOT"}) for tool in tools: tool.setInTime()
def update(pentest, port_iid, body): mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(pentest) oldPort = ServerPort( pentest, mongoInstance.find("ports", {"_id": ObjectId(port_iid)}, False)) if oldPort is None: return port_o = ServerPort(pentest, body) oldService = oldPort.service if oldService != port_o.service: mongoInstance.delete("tools", { "lvl": "port", "ip": port_o.ip, "port": port_o.port, "proto": port_o.proto }, many=True) port_commands = mongoInstance.findInDb(pentest, "commands", {"lvl": "port"}) for port_command in port_commands: allowed_services = port_command["ports"].split(",") for i, elem in enumerate(allowed_services): if not (elem.strip().startswith("tcp/") or elem.strip().startswith("udp/")): allowed_services[i] = "tcp/" + str(elem) if port_o.proto + "/" + str(port_o.service) in allowed_services: waves = mongoInstance.find( "waves", { "wave_commands": { "$elemMatch": { "$eq": port_command["name"].strip() } } }) for wave in waves: tool_m = ServerTool(pentest).initialize( port_command["name"], wave["wave"], "", port_o.ip, port_o.port, port_o.proto, "port") tool_m.addInDb() return mongoInstance.update("ports", {"_id": ObjectId(port_iid)}, {"$set": body}, False, True)
def addScopeFitting(self, pentest, scopeId): """Add the given scopeId to the list of scopes this IP fits in. Args: scopeId: a mongo ObjectId of a Scope object. """ if not self.in_scopes: tools = ServerTool.fetchObjects(pentest, {"ip": self.ip}) for tool in tools: tool.setInScope() if str(scopeId) not in self.in_scopes: self.in_scopes.append(str(scopeId)) update(pentest, self._id, IpController(self).getData())
def removeScopeFitting(self, pentest, scopeId): """Remove the given scopeId from the list of scopes this IP fits in. Args: scopeId: a mongo ObjectId of a scope object. """ if str(scopeId) in self.in_scopes: self.in_scopes.remove(str(scopeId)) update(pentest, self._id, IpController(self).getData()) if not self.in_scopes: tools = ServerTool.fetchObjects(pentest, {"ip": self.ip}) for tool in tools: tool.setOutOfScope(pentest)
def unregister(name): worker = mongoInstance.getWorker(name) if worker is not None: running_tools = worker.get("running_tools", []) for running_tool in running_tools: tool_m = ServerTool.fetchObject(running_tool["pentest"], {"_id":ObjectId(running_tool["iid"])}) if "running" in tool_m.getStatus(): tool_m.markAsNotDone() tool_update(running_tool["pentest"], running_tool["iid"], ToolController(tool_m).getData()) mongoInstance.deleteFromDb("pollenisator", "workers", {"name": name}, False, True) return True return "Worker not Found", 404
def insert(pentest, body): mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(pentest) ip_o = ServerIp(pentest, body) base = ip_o.getDbKey() existing = mongoInstance.find("ips", base, False) if existing is not None: return {"res": False, "iid": existing["_id"]} if "_id" in body: del body["_id"] parent = ip_o.getParentId() ins_result = mongoInstance.insert("ips", body, parent) iid = ins_result.inserted_id if ip_o.in_scopes: waves = mongoInstance.find("waves", {}) for wave in waves: waveName = wave["wave"] commands = wave["wave_commands"] for commName in commands: # 2. finding the command only if lvl is port comm = mongoInstance.findInDb(pentest, "commands", { "name": commName, "lvl": "ip" }, False) if comm is not None: # 3. checking if the added port fit into the command's allowed service # 3.1 first, default the selected port as tcp if no protocole is defined. tool_o = ServerTool(pentest) tool_o.initialize(comm["name"], waveName, "", ip_o.ip, "", "", "ip") tool_o.addInDb() return {"res": True, "iid": iid}
def addAllTool(self, command_name, wave_name, scope): """ Kind of recursive operation as it will call the same function in its children ports. Add the appropriate tools (level check and wave's commands check) for this ip. Also add for all registered ports the appropriate tools. Args: command_name: The command that we want to create all the tools for. wave_name: the wave name from where we want to load tools scope: a scope object allowing to launch this command. Opt """ # retrieve the command level mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(self.pentest) command = mongoInstance.findInDb(self.pentest, "commands", {"name": command_name}, False) if command["lvl"] == "ip": # finally add tool newTool = ServerTool(self.pentest) newTool.initialize(command_name, wave_name, "", self.ip, "", "", "ip") newTool.addInDb() return # Do the same thing for all children ports. ports = mongoInstance.find("ports", {"ip": self.ip}) for port in ports: p = ServerPort(self.pentest, port) p.addAllTool(command_name, wave_name, scope)
def removeWorkers(): workers = mongoInstance.getWorkers() count = 0 for worker in workers: running_tools = worker.get("running_tools", []) for running_tool in running_tools: tool_m = ServerTool.fetchObject(running_tool["pentest"], {"_id":ObjectId(running_tool["iid"])}) if "running" in tool_m.getStatus(): tool_m.markAsNotDone() tool_update(running_tool["pentest"], running_tool["iid"], ToolController(tool_m).getData()) deleteWorker(worker["name"]) count += 1 return {"n":int(count)}
def insert(pentest, body): mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(pentest) port_o = ServerPort(pentest, body) base = port_o.getDbKey() existing = mongoInstance.find("ports", base, False) if existing is not None: return {"res": False, "iid": existing["_id"]} if "_id" in body: del body["_id"] parent = port_o.getParentId() ins_result = mongoInstance.insert("ports", body, parent) iid = ins_result.inserted_id # adding the appropriate tools for this port. # 1. fetching the wave's commands waves = mongoInstance.find("waves", {}) for wave in waves: waveName = wave["wave"] commands = wave["wave_commands"] for commName in commands: # 2. finding the command only if lvl is port comm = mongoInstance.findInDb(pentest, "commands", { "name": commName, "lvl": "port" }, False) if comm is not None: # 3. checking if the added port fit into the command's allowed service # 3.1 first, default the selected port as tcp if no protocole is defined. allowed_ports_services = comm["ports"].split(",") for i, elem in enumerate(allowed_ports_services): if not (elem.strip().startswith("tcp/") or elem.strip().startswith("udp/")): allowed_ports_services[i] = "tcp/" + str(elem.strip()) for allowed in allowed_ports_services: protoRange = "udp" if allowed.startswith("udp/") else "tcp" maybeRange = str(allowed)[4:].split("-") startAllowedRange = -1 endAllowedRange = -1 if len(maybeRange) == 2: try: startAllowedRange = int(maybeRange[0]) endAllowedRange = int(maybeRange[1]) except ValueError: pass if (port_o.proto+"/"+port_o.port == allowed) or \ (port_o.proto+"/"+port_o.service == allowed) or \ (port_o.proto == protoRange and int(port_o.port) >= int(startAllowedRange) and int(port_o.port) <= int(endAllowedRange)): # finally add tool newTool = ServerTool(pentest) newTool.initialize(comm["name"], waveName, "", port_o.ip, port_o.port, port_o.proto, "port") newTool.addInDb() return {"res": True, "iid": iid}
def removeAllTool(self, command_name): """ Remove from every member of this wave the old tool corresponding to given command name but only if the tool is not done. We preserve history Args: command_name: The command that we want to remove all the tools. """ mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(self.pentest) tools = ServerTool.fetchObjects(self.pentest, { "name": command_name, "wave": self.wave }) for tool in tools: if "done" not in tool.getStatus(): tool.delete()
def findLaunchableTools(pentest): """ Try to find tools that matches all criteria. Args: workerName: the current working worker Returns: A tuple with two values: * A list of launchable tools as dictionary with values _id, name and priority * A dictionary of waiting tools with tool's names as keys and integer as value. """ toolsLaunchable = [] waiting = {} time_compatible_waves_id = searchForAddressCompatibleWithTime(pentest) for wave_id in time_compatible_waves_id: commandsLaunchableWave = getNotDoneTools(pentest, wave_id) for tool in commandsLaunchableWave: toolModel = ServerTool.fetchObject(pentest, {"_id": tool}) try: waiting[str(toolModel)] += 1 except KeyError: waiting[str(toolModel)] = 1 if "error" in toolModel.status: continue command = toolModel.getCommand() if command is None: prio = 0 else: prio = int(command.get("priority", 0)) toolsLaunchable.append({ "tool": toolModel, "name": str(toolModel), "priority": prio, "timedout": "timedout" in toolModel.status }) return toolsLaunchable, waiting
def addAllTool(self, command_name): """ Kind of recursive operation as it will call the same function in its children ports. Add the appropriate tools (level check and wave's commands check) for this wave. Also add for all registered scopes the appropriate tools. Args: command_name: The command that we want to create all the tools for. """ mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(self.pentest) command = mongoInstance.findInDb(self.pentest, "commands", {"name": command_name}, False) if command["lvl"] == "wave": newTool = ServerTool(self.pentest) newTool.initialize(command_name, self.wave, "", "", "", "", "wave") newTool.addInDb() return scopes = mongoInstance.find("scopes", {"wave": self.wave}) for scope in scopes: h = ServerScope(self.pentest, scope) h.addAllTool(command_name)
def addAllTool(self, command_name): """ Add the appropriate tools (level check and wave's commands check) for this scope. Args: command_name: The command that we want to create all the tools for. """ mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(self.pentest) command = mongoInstance.findInDb(self.pentest, "commands", {"name": command_name}, False) if command["lvl"] == "network": newTool = ServerTool(self.pentest) newTool.initialize(command["name"], self.wave, self.scope, "", "", "", "network") newTool.addInDb() return if command["lvl"] == "domain": if not isNetworkIp(self.scope): newTool = ServerTool(self.pentest) newTool.initialize(command["name"], self.wave, self.scope, "", "", "", "domain") newTool.addInDb() return ips = self.getIpsFitting() for ip in ips: i = ServerIp(self.pentest, ip) i.addAllTool(command_name, self.wave, self.scope)
def addAllTool(self, command_name, wave_name, scope, check=True): """ Add the appropriate tools (level check and wave's commands check) for this port. Args: command_name: The command that we want to create all the tools for. wave_name: name of the was to fetch allowed commands from scope: a scope matching this tool (should only be used by network level tools) check: A boolean to bypass checks. Force adding this command tool to this port if False. Default is True """ mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(self.pentest) if not check: newTool = ServerTool(self.pentest) newTool.initialize(command_name, wave_name, scope, self.ip, self.port, self.proto, "port") newTool.addInDb() return # retrieve wave's command wave = mongoInstance.find("waves", {"wave": wave_name}, False) commands = wave["wave_commands"] try: index = commands.index(command_name) # retrieve the command level command = mongoInstance.findInDb(self.pentest, "commands", {"name": commands[index]}, False) if command["lvl"] == "port": # 3. checking if the added port fit into the command's allowed service # 3.1 first, default the selected port as tcp if no protocole is defined. allowed_ports_services = command["ports"].split(",") for i, elem in enumerate(allowed_ports_services): if not (elem.strip().startswith("tcp/") or elem.strip().startswith("udp/")): allowed_ports_services[i] = "tcp/" + str(elem.strip()) for allowed in allowed_ports_services: protoRange = "udp" if allowed.startswith("udp/") else "tcp" maybeRange = str(allowed)[4:].split("-") startAllowedRange = -1 endAllowedRange = -1 if len(maybeRange) == 2: try: startAllowedRange = int(maybeRange[0]) endAllowedRange = int(maybeRange[1]) except ValueError: pass if (self.proto+"/"+self.port == allowed) or \ (self.proto+"/"+self.service == allowed) or \ (self.proto == protoRange and int(self.port) >= int(startAllowedRange) and int(self.port) <= int(endAllowedRange)): # finally add tool newTool = ServerTool(self.pentest) newTool.initialize(command_name, wave_name, scope, self.ip, self.port, self.proto, "port") newTool.addInDb() except ValueError: pass