def Parse(self, file_opened, **_kwargs): """ Parse a opened file to extract information Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ notes = "" tags = [] targets = {} result_socket = file_opened.read() domain, ip = parse_reverse_python(result_socket) if domain is None: return None, None, None, None Ip().initialize(domain).addInDb() ip_m = Ip().initialize(ip) res, iid = ip_m.addInDb() if not res: ip_m = Ip.fetchObject({"_id": iid}) hostnames = list(set(ip_m.infos.get("hostname", []) + [domain])) ip_m.updateInfos({"hostname": hostnames}) targets["ip"] = {"ip": ip} notes += "Domain found :" + domain + "\n" if notes == "": notes = "No domain found\n" return notes, tags, "ip", targets
def Parse(self, file_opened, **kwargs): """ Parse a opened file to extract information Example file: 10.0.0.1 - UNKNOWN - no connection - timeout 10.0.0.2 - VULNERABLE - ?? - ???? Args: file_opened: the open file kwargs: port("") and proto("") are valid Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ # 5. Parse the file has you want. # Here add a note to the tool's notes of each warnings issued by this testssl run. notes = "" tags = ["Neutral"] targets = {} for line in file_opened: # Auto Detect infos = line.split(" - ") if len(infos) < 3: return None, None, None, None if not Ip.isIp(infos[0]): return None, None, None, None if infos[1] not in ["UNKNOWN", "SAFE", "VULNERABLE"]: return None, None, None, None # Parse ip = line.split(" ")[0].strip() Ip().initialize(ip).addInDb() p_o = Port.fetchObject({"ip": ip, "port": kwargs.get( "port", None), "proto": kwargs.get("proto", None)}) if p_o is not None: targets[str(p_o.getId())] = {"ip": ip, "port": kwargs.get( "port", None), "proto": kwargs.get("proto", None)} if "VULNERABLE" in line: Defect().initialize(ip, kwargs.get("port", None), kwargs.get("proto", None), "Serveur vulnérable à BlueKeep", "Difficile", "Critique", "Critique", "N/A", ["Socle"], notes=notes, proofs=[]).addInDb() tags=["P0wned!"] if p_o is not None: p_o.addTag("P0wned!") ip_o = Ip.fetchObject({"ip": ip}) if ip_o is not None: ip_o.addTag("P0wned!") elif "UNKNOWN" in line: tags = ["todo"] notes += line return notes, tags, "port", targets
def Parse(self, file_opened, **_kwargs): """ Parse a opened file to extract information foe.test.fr. 801 IN A 18.19.20.21 blog.test.fr. 10800 IN CNAME 22.33.44.55 Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ notes = "" tags = [] countInserted = 0 for line in file_opened: domain, _record_type, ip = parse_crtsh_line(line) if domain is not None: # a domain has been found infosToAdd = {"hostname": ip} ip_m = Ip().initialize(domain, infos=infosToAdd) res, iid = ip_m.addInDb() # failed, domain is out of scope if not res: notes += domain + " exists but already added.\n" ip_m = Ip.fetchObject({"_id": iid}) infosToAdd = { "hostname": list(set([ip] + ip_m.infos.get("hostname", []))) } ip_m.updateInfos(infosToAdd) else: countInserted += 1 notes += domain + " inserted.\n" if notes.strip() == "": return None, None, None, None elif countInserted != 0: tags.append("todo") return notes, tags, "wave", {"wave": None}
def Parse(self, file_opened, **_kwargs): """ Parse a opened file to extract information Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ notes = "" tags = ["todo"] marker = "- scanning for subdomain..." markerFound = False countFound = 0 for line in file_opened: if marker == line.strip(): markerFound = True if not markerFound: continue ip, domain, alias = parse_knockpy_line(line) if ip is not None and domain is not None: # a domain has been found res, iid = Ip().initialize(domain).addInDb() if res: Ip().initialize(ip).addInDb() notes += line + "\n" countFound += 1 # failed, domain is out of scope else: notes += domain + " exists but already added.\n" ip_m = Ip.fetchObject({"_id": iid}) if alias: ip_m.updateInfos({"alias": ip}) if notes.strip() == "": return None, None, None, None return notes, tags, "wave", {"wave": None}
def editScopeIPs(hostsInfos): """ Add all the ips and theirs ports found after parsing the file to the scope object in database. Args: hostsInfos: the dictionnary with ips as keys and a list of dictionnary containing ports informations as value. """ # Check if any ip has been found. if hostsInfos is not None: for infos in hostsInfos: tags = [] if infos.get("powned", False): tags.append("P0wned!") infosToAdd = {} OS = infos.get("OS", "") if OS != "": infosToAdd["OS"] = OS creds = infos.get("creds", "") if creds != "": infosToAdd["creds"] = creds powned = infos.get("powned", False) if powned: infosToAdd["powned"] = "True" ip_m = Ip().initialize(str(infos["ip"])) res, iid = ip_m.addInDb() if not res: ip_m = Ip.fetchObject({"_id": iid}) infosToAdd["hostname"] = list( set(ip_m.infos.get("hostname", []) + [infos["hostname"]])) ip_m.notes = "hostname:" + \ infos["hostname"] + "\n"+infos.get("OS", "") ip_m.tags = tags ip_m.update() port_m = Port().initialize(str(infos["ip"]), str(infos["port"]), "tcp", "netbios-ssn") res, iid = port_m.addInDb() if not res: port_m = Port.fetchObject({"_id": iid}) port_m.updateInfos(infosToAdd) port_m.tags = tags port_m.update()
def addInTreeview(self, parentNode=None, addChildren=True): """Add this view in treeview. Also stores infos in application treeview. Args: parentNode: if None, will calculate the parent. If setted, forces the node to be inserted inside given parentNode. _addChildren: not used here """ if parentNode is None: parentNode = self.getParent() ip_node = None try: if isinstance(parentNode, ObjectId): ip_parent_o = Ip.fetchObject({"_id": parentNode}) if ip_parent_o is not None: parent_view = IpView(self.appliTw, self.appliViewFrame, self.mainApp, IpController(ip_parent_o)) parent_view.addInTreeview(None, False) ip_node = self.appliTw.insert(parentNode, "end", str(self.controller.getDbId()), text=str( self.controller.getModelRepr()), tags=self.controller.getTags(), image=self.getClassIcon()) except TclError: pass self.appliTw.views[str(self.controller.getDbId())] = {"view": self} if addChildren and ip_node is not None: self._insertChildrenDefects() self._insertChildrenTools() self._insertChildrenPorts(ip_node) # self.appliTw.sort(parentNode) if "hidden" in self.controller.getTags(): self.hide() modelData = self.controller.getData() if not modelData["in_scopes"]: self.controller.addTag("OOS")
def loadSummary(self): """Reload information about IP and Port and reload the view. """ mongoInstance = MongoCalendar.getInstance() nonEmptyIps = list( mongoInstance.aggregate("ports", [{ "$group": { "_id": "$ip" } }, { "$count": "total" }])) if not nonEmptyIps: return nonEmptyIps = nonEmptyIps[0] step = 0 dialog = ChildDialogProgress( self.parent, "Loading summary ", "Refreshing summary. Please wait for a few seconds.", 200, "determinate") dialog.show(nonEmptyIps["total"]) nonEmptyIps = mongoInstance.aggregate("ports", [{ "$group": { "_id": "$ip" } }]) for ipCIDR in nonEmptyIps: step += 1 ip = Ip.fetchObject({"ip": ipCIDR["_id"]}) if ip.in_scopes: dialog.update(step) self.insertIp(ip.ip) self.frameTw.update_idletasks() self.parent.update_idletasks() smart_grid(self.frameTw, self.root, *list(self.treeviews.values())) dialog.destroy()
def getIpPortsNmap(nmapFile): """ Read the given nmap .nmap file results and return a dictionnary with ips and a list of their open ports. Args: nmapFile: the path to the .nmap file generated by an nmap scan Returns: notes about inseted ip and ports """ notes = "" countOpen = 0 all_text = nmapFile.read().strip() lines = all_text.split("\n") if len(lines) <= 3: # print("Not enough lines to be nmap") return None if not lines[0].startswith("# Nmap"): # print("Not starting with # Nmap") return None if "scan initiated" not in lines[0]: # print("Not scan initiated on first line") return None if "# Nmap done at" not in lines[-1]: # print("Not # Nmap done at at the end : "+str(lines[-1])) return None ipCIDR_m = None ipDom_m = None for line in lines: # Search ip in file # match an ip ip = re.search( r"^Nmap scan report for (\S+)(?: \(((?:[0-9]{1,3}\.){3}[0-9]{1,3})\))?$", line) if ip is not None: # regex match lastIp = [ ip.group(1), ip.group(2) if ip.group(2) is not None else "" ] notes_ip = "ip:" + \ str(lastIp[1]) if lastIp[1] != "" and lastIp[1] is not None else "" ipCIDR_m = Ip().initialize(str(lastIp[0]), notes=notes_ip) if lastIp[1].strip() != "" and lastIp[1] is not None: ipDom_m = Ip().initialize(str(lastIp[1]), notes="domain:" + str(lastIp[0])) else: ipDom_m = None if " open " in line: if ipCIDR_m is None: # Probably a gnmap return None notes += line + "\n" # regex to find open ports in gnmap file port_search = re.search( r"^(\d+)\/(\S+)\s+open\s+(\S+)(?: +(.+))?$", line) if port_search is not None: port_number = str(port_search.group(1)) proto = str(port_search.group(2)) service = "unknown" if str( port_search.group(3)) == "" else str(port_search.group(3)) product = str(port_search.group(4)) # a port unique key is its protocole/number. countOpen += 1 validIps = [] if ipCIDR_m is not None: ipCIDR_m.addInDb() validIps.append(ipCIDR_m.ip) if ipDom_m is not None: res, iid = ipDom_m.addInDb() if not res: ipDom_m = Ip.fetchObject({"_id": iid}) ipDom_m.updateInfos({ "hostname": list( set( list(ipDom_m.infos.get("hostname", [])) + [str(ipCIDR_m.ip)])) }) validIps.append(ipDom_m.ip) for ipFound in validIps: if ip == "": continue port_o = Port().initialize(ipFound, port_number, proto, service, product) res_insert, iid = port_o.addInDb() if not res_insert: port_o = Port.fetchObject({"_id": iid}) port_o.service = service port_o.update() notes = str(countOpen) + " open ports found\n" + notes return notes
def Parse(self, file_opened, **_kwargs): """ Parse a opened file to extract information Example: [ { "arguments": "./dnsrecon.py -r 10.0.0.0/24 -j /home/barre/test.json", "date": "2020-01-06 11:43:37.701513", "type": "ScanInfo" }, { "address": "10.0.0.1", "name": "_gateway", "type": "PTR" }, { "address": "10.0.0.77", "name": "barre-ThinkPad-E480", "type": "PTR" }, { "address": "10.0.0.77", "name": "barre-ThinkPad-E480.local", "type": "PTR" } ] Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ notes = "" tags = [] countInserted = 0 try: dnsrecon_content = json.loads(file_opened.read()) except json.decoder.JSONDecodeError: return None, None, None, None if len(dnsrecon_content) == 0: return None, None, None, None if not isinstance(dnsrecon_content[0], dict): return None, None, None, None if dnsrecon_content[0].get("type", "") != "ScanInfo": return None, None, None, None if dnsrecon_content[0].get("date", "") == "": return None, None, None, None for record in dnsrecon_content[1:]: ip = record["address"] name = record["name"] infosToAdd = {"hostname": name} ip_m = Ip().initialize(ip, infos=infosToAdd) res, iid = ip_m.addInDb() infosToAdd = {"ip": ip} ip_m = Ip().initialize(name, infos=infosToAdd) res, iid = ip_m.addInDb() # failed, domain is out of scope if not res: notes += name + " exists but already added.\n" ip_m = Ip.fetchObject({"_id": iid}) infosToAdd = {"ip": list(set([ip] + ip_m.infos.get("ip", [])))} ip_m.updateInfos(infosToAdd) else: countInserted += 1 notes += name + " inserted.\n" return notes, tags, "wave", {"wave": None}