def notify_summary(self, audit_name): """ This method is called when an audit ends and when a plugin ends. :param audit_name: Name of the audit. :type audit_name: str """ # Get the number of vulnerabilities in the database. vulns_number = Database.count(Data.TYPE_VULNERABILITY) # Count the vulnerabilities by severity. vulns_counter = collections.defaultdict(int) for l_vuln in Database.iterate(Data.TYPE_VULNERABILITY): vulns_counter[l_vuln.level] += 1 # Get the number of IP addresses and hostnames. total_hosts = Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_DOMAIN) total_hosts += Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_IP) # Substract the ones that were passed as targets. discovered_hosts = total_hosts - len(Config.audit_scope.targets) discovered_hosts = discovered_hosts if discovered_hosts > 0 else 0 # Send the summary. packet = ("summary", audit_name, vulns_number, discovered_hosts, total_hosts, vulns_counter['info'], vulns_counter['low'], vulns_counter['medium'], vulns_counter['high'], vulns_counter['critical'],) self.bridge.send(packet)
def common_get_resources(self, data_type=None, data_subtype=None): """ Get a list of datas. :return: List of resources. :rtype: list(Resource) """ # Get each resource m_resource = None m_len_urls = Database.count(data_type, data_type) if m_len_urls < 200: # increase as you see fit... # fast but memory consuming method m_resource = Database.get_many( Database.keys(data_type=data_type, data_subtype=data_subtype)) else: # slow but lean method m_resource = Database.iterate(data_type=data_type, data_subtype=data_subtype) return m_resource
def __iterate(self, data_type = None, data_subtype = None): if Database.count(data_type, data_type) < 100: return Database.get_many( Database.keys(data_type=data_type, data_subtype=data_subtype) ) return Database.iterate(data_type=data_type, data_subtype=data_subtype)
def __write_report(self): # Header print >>self.__fd, "" print >>self.__fd, "--= %s =--" % self.__colorize("Report", "cyan") print >>self.__fd, "" # Summary start_time, stop_time, run_time = parse_audit_times( *get_audit_times() ) host_count = Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_DOMAIN) host_count += Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_IP) vuln_count = Database.count(Data.TYPE_VULNERABILITY) print >>self.__fd, "-# %s #- " % self.__colorize("Summary", "yellow") print >>self.__fd, "" print >>self.__fd, "Audit started: %s" % self.__colorize(start_time, "yellow") print >>self.__fd, "Audit ended: %s" % self.__colorize(stop_time, "yellow") print >>self.__fd, "Execution time: %s" % self.__colorize(run_time, "yellow") print >>self.__fd, "" print >>self.__fd, "Scanned hosts: %s" % self.__colorize(str(host_count), "yellow") print >>self.__fd, "Vulnerabilities: %s" % self.__colorize(str(vuln_count), "red" if vuln_count else "yellow") print >>self.__fd, "" # Audit scope if self.__show_data or not self.__console: table = Texttable() scope_domains = ["*." + r for r in Config.audit_scope.roots] scope_domains.extend(Config.audit_scope.domains) if Config.audit_scope.addresses: table.add_row(("IP addresses", "\n".join(Config.audit_scope.addresses))) if scope_domains: table.add_row(("Domains", "\n".join(scope_domains))) if Config.audit_scope.web_pages: table.add_row(("Web pages", "\n".join(Config.audit_scope.web_pages))) if table._rows: self.__fix_table_width(table) print >>self.__fd, "-# %s #- " % self.__colorize("Audit Scope", "yellow") print >>self.__fd, "" print >>self.__fd, table.draw() print >>self.__fd, "" # Discovered hosts if self.__show_data: need_header = True for domain in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_DOMAIN): table = Texttable() self.__add_related(table, domain, Data.TYPE_RESOURCE, Resource.RESOURCE_IP, "IP Address") self.__add_related(table, domain, Data.TYPE_INFORMATION, Information.INFORMATION_GEOLOCATION, "Location") self.__add_related(table, domain, Data.TYPE_INFORMATION, Information.INFORMATION_WEB_SERVER_FINGERPRINT, "Web Server") self.__add_related(table, domain, Data.TYPE_INFORMATION, Information.INFORMATION_OS_FINGERPRINT, "OS Fingerprint") if table._rows: if need_header: need_header = False print >>self.__fd, "-# %s #- " % self.__colorize("Hosts", "yellow") print >>self.__fd, "" table.header(("Domain Name", domain.hostname)) self.__fix_table_width(table) text = table.draw() if self.__color: text = colorize_substring(text, domain.hostname, "red" if domain.get_links(Data.TYPE_VULNERABILITY) else "green") print >>self.__fd, text print >>self.__fd, "" for ip in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_IP): table = Texttable() self.__add_related(table, ip, Data.TYPE_RESOURCE, Resource.RESOURCE_DOMAIN, "Domain Name") self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_GEOLOCATION, "Location") self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_WEB_SERVER_FINGERPRINT, "Web Server") self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_OS_FINGERPRINT, "OS Fingerprint") self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_PORTSCAN, "Port Scan") self.__add_related(table, ip, Data.TYPE_INFORMATION, Information.INFORMATION_TRACEROUTE, "Network Route") if table._rows: if need_header: need_header = False print >>self.__fd, "-# %s #- " % self.__colorize("Hosts", "yellow") print >>self.__fd, "" table.header(("IP Address", ip.address)) self.__fix_table_width(table) text = table.draw() if self.__color: text = colorize_substring(text, ip.address, "red" if ip.get_links(Data.TYPE_VULNERABILITY) else "green") print >>self.__fd, text print >>self.__fd, "" # Web servers if self.__show_data and Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_BASE_URL): print >>self.__fd, "-# %s #- " % self.__colorize("Web Servers", "yellow") print >>self.__fd, "" crawled = defaultdict(list) vulnerable = [] for url in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_URL): crawled[url.hostname].append(url.url) if self.__color and url.get_links(Data.TYPE_VULNERABILITY): vulnerable.append(url) for url in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_BASE_URL): table = Texttable() table.header(("Base URL", url.url)) self.__add_related(table, url, Data.TYPE_INFORMATION, Information.INFORMATION_WEB_SERVER_FINGERPRINT, "Server") self.__add_related(table, url, Data.TYPE_INFORMATION, Information.INFORMATION_OS_FINGERPRINT, "Platform") urls = crawled[url.hostname] if urls: urls.sort() table.add_row(("Visited URLs", "\n".join(urls))) if table._rows: self.__fix_table_width(table) text = table.draw() if self.__color: p = text.find("\n") p = text.find("\n", p + 1) p = text.find("\n", p + 1) if p > 0: text = colorize_substring(text[:p], url.url, "red" if url.get_links(Data.TYPE_VULNERABILITY) else "green") + text[p:] for u in vulnerable: if u != url.url: text = colorize_substring(text, u, "red") print >>self.__fd, text print >>self.__fd, "" # Emails if self.__show_data: emails = { e.address: "red" if e.get_links(Data.TYPE_VULNERABILITY) else "green" for e in self.__iterate(Data.TYPE_RESOURCE, Resource.RESOURCE_EMAIL) } if emails: print >>self.__fd, "-# %s #- " % self.__colorize("Email Addresses", "yellow") print >>self.__fd, "" for e in sorted(emails): print >>self.__fd, "* " + self.__colorize(e, emails[e]) print >>self.__fd, "" # Vulnerabilities print >>self.__fd, "-# %s #- " % self.__colorize("Vulnerabilities", "yellow") print >>self.__fd, "" count = Database.count(Data.TYPE_VULNERABILITY) if count: if self.__show_data: print >>self.__fd, self.__colorize("%d vulnerabilities found!" % count, "red") print >>self.__fd, "" vuln_types = { v.display_name: v.vulnerability_type for v in self.__iterate(Data.TYPE_VULNERABILITY) } titles = vuln_types.keys() titles.sort() if "Uncategorized Vulnerability" in titles: titles.remove("Uncategorized Vulnerability") titles.append("Uncategorized Vulnerability") for title in titles: data_subtype = vuln_types[title] print >>self.__fd, "-- %s (%s) -- " % (self.__colorize(title, "cyan"), data_subtype) print >>self.__fd, "" for vuln in self.__iterate(Data.TYPE_VULNERABILITY, data_subtype): table = Texttable() table.header(("Occurrence ID", vuln.identity)) w = len(table.draw()) table.add_row(("Title", vuln.title)) targets = [str(x) for x in vuln.associated_resources] for info in vuln.associated_informations: targets.extend(str(x) for x in info.associated_resources) table.add_row(("Found By", get_plugin_name(vuln.plugin_id))) p = len(table.draw()) table.add_row(("Level", vuln.level)) table.add_row(("Impact", vuln.impact)) table.add_row(("Severity", vuln.severity)) table.add_row(("Risk", vuln.risk)) q = len(table.draw()) if vuln.cvss_base: table.add_row(("CVSS Base", vuln.cvss_base)) if vuln.cvss_base_vector: table.add_row(("CVSS Base Vector", vuln.cvss_base_vector)) if len(targets) > 1: targets.sort() table.add_row(("Locations", "\n".join(targets))) else: table.add_row(("Location", targets[0])) table.add_row(("Description", vuln.description)) table.add_row(("Solution", vuln.solution)) taxonomy = [] if vuln.bid: taxonomy.extend(vuln.bid) if vuln.cve: taxonomy.extend(vuln.cve) if vuln.cwe: taxonomy.extend(vuln.cwe) if vuln.osvdb: taxonomy.extend(vuln.osvdb) if vuln.sa: taxonomy.extend(vuln.sa) if vuln.sectrack: taxonomy.extend(vuln.sectrack) if vuln.xf: taxonomy.extend(vuln.xf) if taxonomy: table.add_row(("Taxonomy", "\n".join(taxonomy))) if vuln.references: table.add_row(("References", "\n".join(sorted(vuln.references)))) details = vuln.display_properties["Details"] if details: props = details.keys() props.sort() table.add_row(("Additional details", "\n".join(("%s: %s" % (x, details[x])) for x in props))) self.__fix_table_width(table) text = table.draw() if self.__color: text_1 = text[:w] text_3 = text[p:q] text_1 = colorize_substring(text_1, vuln.identity, vuln.level.lower()) for lvl in Vulnerability.VULN_LEVELS: if lvl in text_3: text_3 = colorize_substring(text_3, lvl, lvl.lower()) text = text_1 + text[w:p] + text_3 + text[q:] print >>self.__fd, text print >>self.__fd, "" else: print >>self.__fd, self.__colorize("No vulnerabilities found.", "green") print >>self.__fd, ""
def do_audit_summary(self, audit_name): """ Implementation of: /audit/summary :param audit_name: Name of the audit to query. :type audit_name: str :returns: Summary in the following format:: { 'vulns_number' : int, 'discovered_hosts' : int, 'total_hosts' : int, 'vulns_by_level' : { 'info' : int, 'low' : int, 'medium' : int, 'high' : int, 'critical' : int, }, } Returns None on error. :rtype: dict(str -> \\*) | None """ # Checks for errors if audit_name in self.audit_error: return "error" try: if self.is_audit_running(audit_name): with SwitchToAudit(audit_name): # Get the number of vulnerabilities in the database. vulns_number = Database.count(Data.TYPE_VULNERABILITY) # Count the vulnerabilities by severity. vulns_counter = collections.Counter() for l_vuln in Database.iterate(Data.TYPE_VULNERABILITY): vulns_counter[l_vuln.level] += 1 # Get the number of IP addresses and hostnames. total_hosts = Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_DOMAIN) total_hosts += Database.count(Data.TYPE_RESOURCE, Resource.RESOURCE_IP) # Substract the ones that were passed as targets. discovered_hosts = total_hosts - len(Config.audit_scope.targets) # Return the data in the expected format. return { 'vulns_number' : vulns_number, 'discovered_hosts' : discovered_hosts, 'total_hosts' : total_hosts, 'vulns_by_level' : { 'info' : vulns_counter['info'], 'low' : vulns_counter['low'], 'medium' : vulns_counter['medium'], 'high' : vulns_counter['high'], 'critical' : vulns_counter['critical'], } } else: # XXX TODO open the database manually here raise NotImplementedError( "Querying finished audits is not implemented yet!") except Exception: Logger.log_error(traceback.format_exc())
def __write_report(self): # Header print >>self.__fd, "" print >>self.__fd, "--= %s =--" % self.__colorize("Report", "cyan") print >>self.__fd, "" # Summary start_time, stop_time, run_time = parse_audit_times( *get_audit_times() ) host_count = Database.count(Data.TYPE_RESOURCE, Domain.data_subtype) host_count += Database.count(Data.TYPE_RESOURCE, IP.data_subtype) vuln_count = Database.count(Data.TYPE_VULNERABILITY) print >>self.__fd, "-# %s #- " % self.__colorize("Summary", "yellow") print >>self.__fd, "" print >>self.__fd, "Audit started: %s" % self.__colorize(start_time, "yellow") print >>self.__fd, "Audit ended: %s" % self.__colorize(stop_time, "yellow") print >>self.__fd, "Execution time: %s" % self.__colorize(run_time, "yellow") print >>self.__fd, "" print >>self.__fd, "Scanned hosts: %s" % self.__colorize(str(host_count), "yellow") print >>self.__fd, "Vulnerabilities: %s" % self.__colorize(str(vuln_count), "red" if vuln_count else "yellow") print >>self.__fd, "" # Audit scope if self.__show_data or not self.__console: table = Texttable() scope_domains = ["*." + r for r in Config.audit_scope.roots] scope_domains.extend(Config.audit_scope.domains) if Config.audit_scope.addresses: table.add_row(("IP addresses", "\n".join(Config.audit_scope.addresses))) if scope_domains: table.add_row(("Domains", "\n".join(scope_domains))) if Config.audit_scope.web_pages: table.add_row(("Web pages", "\n".join(Config.audit_scope.web_pages))) if table._rows: self.__fix_table_width(table) print >>self.__fd, "-# %s #- " % self.__colorize("Audit Scope", "yellow") print >>self.__fd, "" print >>self.__fd, table.draw() print >>self.__fd, "" # Discovered hosts if self.__show_data: need_header = True for domain in self.__iterate(Data.TYPE_RESOURCE, Domain.data_subtype): table = Texttable() self.__add_related(table, domain, Data.TYPE_RESOURCE, IP.data_subtype, "IP Address") self.__add_related(table, domain, Data.TYPE_INFORMATION, Geolocation.data_subtype, "Location") self.__add_related(table, domain, Data.TYPE_INFORMATION, WebServerFingerprint.data_subtype, "Web Server") self.__add_related(table, domain, Data.TYPE_INFORMATION, OSFingerprint.data_subtype, "OS Fingerprint") if table._rows: if need_header: need_header = False print >>self.__fd, "-# %s #- " % self.__colorize("Hosts", "yellow") print >>self.__fd, "" table.header(("Domain Name", domain.hostname)) self.__fix_table_width(table) text = table.draw() if self.__color: text = colorize_substring(text, domain.hostname, "red" if domain.get_links(Data.TYPE_VULNERABILITY) else "green") print >>self.__fd, text print >>self.__fd, "" for ip in self.__iterate(Data.TYPE_RESOURCE, IP.data_subtype): table = Texttable() self.__add_related(table, ip, Data.TYPE_RESOURCE, Domain.data_subtype, "Domain Name") self.__add_related(table, ip, Data.TYPE_RESOURCE, MAC.data_subtype, "MAC Address") self.__add_related(table, ip, Data.TYPE_RESOURCE, BSSID.data_subtype, "WiFi 802.11 BSSID") self.__add_related(table, ip, Data.TYPE_INFORMATION, Geolocation.data_subtype, "Location") self.__add_related(table, ip, Data.TYPE_INFORMATION, WebServerFingerprint.data_subtype, "Web Server") self.__add_related(table, ip, Data.TYPE_INFORMATION, OSFingerprint.data_subtype, "OS Fingerprint") self.__add_related(table, ip, Data.TYPE_INFORMATION, ServiceFingerprint.data_subtype, "Service") self.__add_related(table, ip, Data.TYPE_INFORMATION, Portscan.data_subtype, "Port Scan") self.__add_related(table, ip, Data.TYPE_INFORMATION, Traceroute.data_subtype, "Network Route") if table._rows: if need_header: need_header = False print >>self.__fd, "-# %s #- " % self.__colorize("Hosts", "yellow") print >>self.__fd, "" table.header(("IP Address", ip.address)) self.__fix_table_width(table) text = table.draw() if self.__color: text = colorize_substring(text, ip.address, "red" if ip.get_links(Data.TYPE_VULNERABILITY) else "green") print >>self.__fd, text print >>self.__fd, "" # Web servers if self.__show_data and Database.count(Data.TYPE_RESOURCE, BaseURL.data_subtype): print >>self.__fd, "-# %s #- " % self.__colorize("Web Servers", "yellow") print >>self.__fd, "" crawled = defaultdict(list) vulnerable = [] for url in self.__iterate(Data.TYPE_RESOURCE, URL.data_subtype): crawled[url.hostname].append(url.url) if self.__color and url.get_links(Data.TYPE_VULNERABILITY): vulnerable.append(url) for url in self.__iterate(Data.TYPE_RESOURCE, BaseURL.data_subtype): table = Texttable() table.header(("Base URL", url.url)) self.__add_related(table, url, Data.TYPE_INFORMATION, WebServerFingerprint.data_subtype, "Server") self.__add_related(table, url, Data.TYPE_INFORMATION, OSFingerprint.data_subtype, "Platform") urls = crawled[url.hostname] if urls: urls.sort() table.add_row(("Visited URLs", "\n".join(urls))) if table._rows: self.__fix_table_width(table) text = table.draw() if self.__color: p = text.find("\n") p = text.find("\n", p + 1) p = text.find("\n", p + 1) if p > 0: text = colorize_substring(text[:p], url.url, "red" if url.get_links(Data.TYPE_VULNERABILITY) else "green") + text[p:] for u in vulnerable: if u != url.url: text = colorize_substring(text, u, "red") print >>self.__fd, text print >>self.__fd, "" # Emails if self.__show_data: emails = { e.address: "red" if e.get_links(Data.TYPE_VULNERABILITY) else "green" for e in self.__iterate(Data.TYPE_RESOURCE, Email.data_subtype) } if emails: print >>self.__fd, "-# %s #- " % self.__colorize("Email Addresses", "yellow") print >>self.__fd, "" for e in sorted(emails): print >>self.__fd, "* " + self.__colorize(e, emails[e]) print >>self.__fd, "" # Vulnerabilities print >>self.__fd, "-# %s #- " % self.__colorize("Vulnerabilities", "yellow") print >>self.__fd, "" count = Database.count(Data.TYPE_VULNERABILITY) if count: if self.__show_data: print >>self.__fd, self.__colorize("%d vulnerabilities found!" % count, "red") print >>self.__fd, "" vuln_types = { v.display_name: v.vulnerability_type for v in self.__iterate(Data.TYPE_VULNERABILITY) } titles = vuln_types.keys() titles.sort() if "Uncategorized Vulnerability" in titles: titles.remove("Uncategorized Vulnerability") titles.append("Uncategorized Vulnerability") for title in titles: data_subtype = vuln_types[title] print >>self.__fd, "-- %s (%s) -- " % (self.__colorize(title, "cyan"), data_subtype) print >>self.__fd, "" for vuln in self.__iterate(Data.TYPE_VULNERABILITY, data_subtype): table = Texttable() table.header(("Occurrence ID", vuln.identity)) w = len(table.draw()) table.add_row(("Title", vuln.title)) ##targets = self.__gather_vulnerable_resources(vuln) targets = [vuln.target] table.add_row(("Found By", get_plugin_name(vuln.plugin_id))) p = len(table.draw()) table.add_row(("Level", vuln.level)) #table.add_row(("Impact", vuln.impact)) #table.add_row(("Severity", vuln.severity)) #table.add_row(("Risk", vuln.risk)) q = len(table.draw()) if vuln.cvss_base: table.add_row(("CVSS Base", vuln.cvss_base)) if vuln.cvss_score: table.add_row(("CVSS Score", vuln.cvss_score)) if vuln.cvss_vector: table.add_row(("CVSS Vector", vuln.cvss_vector)) if len(targets) > 1: targets.sort() table.add_row(("Locations", "\n".join(targets))) elif targets: table.add_row(("Location", targets[0])) table.add_row(("Description", vuln.description)) table.add_row(("Solution", vuln.solution)) taxonomy = [] if vuln.bid: taxonomy.extend(vuln.bid) if vuln.cve: taxonomy.extend(vuln.cve) if vuln.cwe: taxonomy.extend(vuln.cwe) if vuln.osvdb: taxonomy.extend(vuln.osvdb) if vuln.sa: taxonomy.extend(vuln.sa) if vuln.sectrack: taxonomy.extend(vuln.sectrack) if vuln.xf: taxonomy.extend(vuln.xf) if taxonomy: table.add_row(("Taxonomy", "\n".join(taxonomy))) if vuln.references: table.add_row(("References", "\n".join(sorted(vuln.references)))) details = vuln.display_properties.get("Details") if details: props = details.keys() props.sort() table.add_row(("Additional details", "\n".join(("%s: %s" % (x, details[x])) for x in props))) self.__fix_table_width(table) text = table.draw() if self.__color: text_1 = text[:w] text_3 = text[p:q] text_1 = colorize_substring(text_1, vuln.identity, vuln.level.lower()) for lvl in Vulnerability.VULN_LEVELS: if lvl in text_3: text_3 = colorize_substring(text_3, lvl, lvl.lower()) text = text_1 + text[w:p] + text_3 + text[q:] print >>self.__fd, text print >>self.__fd, "" else: print >>self.__fd, self.__colorize("No vulnerabilities found.", "green") print >>self.__fd, ""
def __iterate(self, data_type = None, data_subtype = None): if Database.count(data_type=data_type, data_subtype=data_subtype) <100: return Database.get_many( Database.keys(data_type=data_type, data_subtype=data_subtype) ) return Database.iterate(data_type=data_type, data_subtype=data_subtype)