def Parse(self, file_opened, **kwargs): """ Parse a opened file to extract information Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ targets = {} notes = file_opened.read() regex_ip = r"Nmap scan report for (\S+)" ip_group = re.search(regex_ip, notes) if ip_group is None: return None, None, None, None # Auto Detect: if "smb-vuln-ms17-010:" not in notes: return None, None, None, None # Parsing ip = ip_group.group(1).strip() Ip().initialize(ip).addInDb() port_re = r"(\d+)\/(\S+)\s+open\s+microsoft-ds" res_search = re.search(port_re, notes) res_insert = None if res_search is None: port = None proto = None else: port = res_search.group(1) proto = res_search.group(2) p_o = Port() p_o.initialize(ip, port, proto, "microsoft-ds") res_insert = p_o.addInDb() targets[str(p_o.getId())] = { "ip": ip, "port": port, "proto": proto } if "VULNERABLE" in notes: d_o = Defect() d_o.initialize(ip, port, proto, "Serveur vulnérable à EternalBlue", "Difficile", "Critique", "Critique", "N/A", ["Socle"], notes=notes, proofs=[]) d_o.addInDb() tags = ["P0wned!"] if res_insert is not None: p_o.addTag("P0wned!") return notes, tags, "port", targets
def addPort(self, values): """ Add a port object to database associated with this Ip. Args: values: A dictionary crafted by PortView containg all form fields values needed. Returns:ret '_id': The mongo ObjectId _idret of the inserted port document or None if insertion failed (unicity broken). """ portToInsert = {"ip": self.ip, "port": str( values["Port"]), "proto": str(values["Protocole"]), "service": values["Service"], "product": values["Product"]} newPort = Port() newPort.initialize( self.ip, portToInsert["port"], portToInsert["proto"], portToInsert["service"], portToInsert["product"]) return newPort.addInDb()
def Parse(self, file_opened, **_kwargs): """ Parse a opened file to extract information Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ tags = ["todo"] data = file_opened.read() notes = "" if data.strip() == "": return None, None, None, None else: hosts = parse_dirsearch_file(data) if not hosts.keys(): return None, None, None, None targets = {} for host in hosts: Ip().initialize(host).addInDb() for port in hosts[host]: port_o = Port() port_o.initialize(host, port, "tcp", hosts[host][port]["service"]) res, iid = port_o.addInDb() if not res: port_o = Port.fetchObject({"_id": iid}) targets[str(port_o.getId())] = { "ip": host, "port": port, "proto": "tcp"} hosts[host][port]["paths"].sort(key=lambda x: int(x[0])) results = "\n".join(hosts[host][port]["paths"]) notes += results newInfos = {} for statuscode in hosts[host][port]: if isinstance(statuscode, int): if hosts[host][port].get(statuscode, []): newInfos["Dirsearch_"+str(statuscode) ] = hosts[host][port][statuscode] newInfos["SSL"] = "True" if hosts[host][port]["service"] == "https" else "False" port_o.updateInfos(newInfos) return notes, tags, "port", targets
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 Parse(self, file_opened, **_kwargs): """ Parse a opened file to extract information Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ notes = file_opened.read() targets = {} tags = [] if "| http-methods:" not in notes: return None, None, None, None host, port, proto, service, risky_methods, supported_methods = parse( notes) if host == "": return None, None, None, None Ip().initialize(host).addInDb() p_o = Port().initialize(host, port, proto, service) res, iid = p_o.addInDb() if not res: p_o = Port.fetchObject({"_id": iid}) p_o.updateInfos({"Methods": ", ".join(supported_methods)}) targets[str(p_o.getId())] = {"ip": host, "port": port, "proto": proto} if "TRACE" in risky_methods: Defect().initialize(host, port, proto, "Méthode TRACE activée", "Difficile", "Important", "Important", "N/A", ["Socle"], notes="TRACE detected", proofs=[]).addInDb() risky_methods.remove("TRACE") if len(risky_methods) > 0: notes = "RISKY HTTP METHODS ALLOWED : " + " ".join(risky_methods) tags = [] tags.append("Interesting") return notes, tags, "port", targets
def Parse(self, file_opened, **_kwargs): """ Parse a opened file to extract information Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ tags = ["todo"] targets = {} notes = file_opened.read() if notes == "": return None, None, None, None if not notes.startswith("- Nikto v"): return None, None, None, None host, port, service, infos = parse_nikto_plain_text(notes) if host: if port: Ip().initialize(host).addInDb() p_o = Port().initialize(host, port, "tcp", service) res, iid = p_o.addInDb() if not res: p_o = Port.fetchObject({"_id": iid}) p_o.updateInfos({ "Nikto": infos, "SSL": "True" if service == "https" else "False" }) targets[str(iid)] = {"ip": host, "port": port, "proto": "tcp"} return notes, tags, "port", targets
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 Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ notes = "" tags = [] content = file_opened.read() targets = {} try: notes_json = json.loads(content) except json.decoder.JSONDecodeError: return None, None, None, None oneScanIsValid = False for scan in notes_json: try: if scan.get('ssh_scan_version', None) is None: continue ips = [scan["hostname"], scan["ip"]] port = str(scan["port"]) for ip in ips: if ip.strip() == "": continue Ip().initialize(ip).addInDb() port_o = Port().initialize(ip, port, "tcp", "ssh") res, iid = port_o.addInDb() if not res: port_o = Port.fetchObject({"_id": iid}) notes = "\n".join(scan["compliance"].get( "recommendations", [])) targets[str(port_o.getId())] = { "ip": ip, "port": port, "proto": "tcp" } oneScanIsValid = True if "nopassword" in scan["auth_methods"]: tags = ["P0wned!"] # Will not exit if port was not ssh is_ok = scan["compliance"]["compliant"] if str(is_ok) == "False": port_o.updateInfos({"compliant": "False"}) port_o.updateInfos( {"auth_methods": scan["auth_methods"]}) Defect().initialize( ip, port, "tcp", "Défauts d’implémentation de la configuration SSH", "Très difficile", "Majeur", "Important", "N/A", ["Socle"], notes=notes, proofs=[]).addInDb() except KeyError: continue if not oneScanIsValid: return None, None, None, None return notes, tags, "port", targets
def Parse(self, file_opened, **_kwargs): """ Parse a opened file to extract information Args: file_opened: the open file _kwargs: not used Returns: a tuple with 4 values (All set to None if Parsing wrong file): 0. notes: notes to be inserted in tool giving direct info to pentester 1. tags: a list of tags to be added to tool 2. lvl: the level of the command executed to assign to given targets 3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects. """ tags = ["todo"] targets = {} notes = file_opened.read() if notes == "": return None, None, None, None try: data = json.loads(notes) except json.decoder.JSONDecodeError: return None, None, None, None regex_host = r"https?://([^\/]+)" oneValidWhatweb = False for website in data: keys = website.keys() expected_keys = [ 'target', 'http_status', 'request_config', 'plugins' ] all_keys = True for expected in expected_keys: if expected not in keys: all_keys = False break if not all_keys: continue host_port_groups = re.search(regex_host, website["target"]) if host_port_groups is None: continue host_port = host_port_groups.group(1) service = "https" if "https://" in website["target"] else "http" if len(host_port.split(":")) == 2: port = host_port.split(":")[1] host = host_port.split(":")[0] else: host = host_port port = "443" if "https://" in website["target"] else "80" Ip().initialize(host).addInDb() p_o = Port().initialize(host, port, "tcp", service) inserted, iid = p_o.addInDb() if not inserted: p_o = Port.fetchObject({"_id": iid}) infosToAdd = {"URL": website["target"]} for plugin in website.get("plugins", {}): item = website["plugins"][plugin].get("string") if isinstance(item, list): if item: infosToAdd[plugin] = item else: item = str(item) if item != "": infosToAdd[plugin] = item p_o.updateInfos(infosToAdd) targets[str(p_o.getId())] = { "ip": host, "port": port, "proto": "tcp" } oneValidWhatweb = True if not oneValidWhatweb: return None, None, None, None return notes, tags, "port", targets