def service_vulns_list(): # XXX: this doesn't work yet. . . query = (db.t_service_vulns.id > 0) & (db.t_service_vulns.f_services_id == db.t_services.id) & ( db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) query = create_hostfilter_query(session.hostfilter, query, 't_services') columns = [ db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, db.t_vulndata.f_vulnid, db.t_service_vulns.f_status, db.t_service_vulns.f_proof, #db.t_service_vulns.id ] rows = SQLFORM.grid(query, columns, deletable=True, selectable=True, details=False, field_id=db.t_service_vulns.id) response.title = "Services with Vulnerabilities" return dict(rows=rows)
def vuln_hosts_by_vulnid(): """ Returns a grid of hosts based on f_vulndata_id """ vuln_id = request.args(0) or None query = (db.t_hosts.id > 0) query = create_hostfilter_query(session.hostfilter, query, 't_services') query &= (db.t_services.f_hosts_id == db.t_hosts.id) query &= (db.t_service_vulns.f_services_id == db.t_services.id) query &= (db.t_service_vulns.f_vulndata_id == vuln_id) hosts = SQLFORM.grid( query, args=[vuln_id], fields=[ db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, db.t_service_vulns.f_proof, ], maxtextlength=255, searchable=True, deletable=True, details=False, selectable=True, create=False, csv=True, formstyle='bootstrap', formname='vuln_hosts_grid', client_side_delete=True, paginate=None, ) return hosts
def vuln_hosts_by_vulnid(): """ Returns a grid of hosts based on f_vulndata_id """ vuln_id = request.args(0) or None query = (db.t_hosts.id > 0) query = create_hostfilter_query(session.hostfilter, query, 't_services') query &= (db.t_services.f_hosts_id == db.t_hosts.id) query &= (db.t_service_vulns.f_services_id == db.t_services.id) query &= (db.t_service_vulns.f_vulndata_id == vuln_id) hosts = SQLFORM.grid( query, args=[vuln_id], fields = [ db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, db.t_service_vulns.f_proof, ], maxtextlength=255, searchable=True, deletable=True, details=False, selectable=True, create=False, csv=True, formstyle='bootstrap', formname='vuln_hosts_grid', client_side_delete=True, paginate=None, ) return hosts
def services(): """ Service statistics """ t_hosts = db.t_hosts t_svcs = db.t_services q = (t_hosts.id > 0) q = create_hostfilter_query(session.hostfilter, q, t_svcs) rows = db(q).select(t_svcs.f_proto, t_svcs.f_number, t_svcs.f_name, cache=(cache.ram, 60)) port_counts = {} name_counts = {} for r in rows: port = "%s/%s" % (r.f_proto, r.f_number) sname = r.f_name count = port_counts.setdefault(port, 0) count += 1 port_counts[port] = count count = name_counts.setdefault(sname, 0) count += 1 name_counts[sname] = count response.title = "%s :: Service Statistics" % (settings.title) return dict( port_counts=port_counts, name_counts=name_counts, )
def accounts_grid(): response.title = "%s :: Accounts" % (settings.title) if session.hostfilter is None: session.hostfilter = [(None, None), False] query = (db.t_accounts.id > 0) & (db.t_accounts.f_services_id == db.t_services.id) query = create_hostfilter_query(session.hostfilter, query, "t_services") columns = [ db.t_hosts.f_ipv4, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, db.t_accounts.f_fullname, db.t_accounts.f_domain, db.t_accounts.f_password, db.t_accounts.f_hash1_type, db.t_accounts.f_hash1, db.t_accounts.f_hash2_type, db.t_accounts.f_hash2, db.t_accounts.f_uid, db.t_accounts.f_gid, db.t_accounts.f_level, db.t_accounts.f_active, db.t_accounts.f_lockout, db.t_accounts.f_duration, db.t_accounts.f_source, db.t_accounts.f_message, db.t_accounts.f_description, db.t_accounts.id, ] rows = SQLFORM.grid(query, columns, deletable=True, selectable=True, details=False, field_id=db.t_accounts.id) return dict(rows=rows)
def os(): """ Operating system statistics """ q = create_hostfilter_query(session.hostfilter) rows = db(q).select(db.t_hosts.id, db.t_host_os_refs.f_certainty, db.t_os.f_title, db.t_os.f_vendor, db.t_host_os_refs.f_family, db.t_host_os_refs.f_class, left=(db.t_host_os_refs.on(db.t_hosts.id==db.t_host_os_refs.f_hosts_id), db.t_os.on(db.t_os.id==db.t_host_os_refs.f_os_id)), orderby=db.t_hosts.id|~db.t_host_os_refs.f_certainty, cache=(cache.ram, 60)) seen = set() os_counts = {} vendor_counts = {} family_counts = {} class_counts = {} for r in rows: if r.t_hosts.id not in seen and not seen.add(r.t_hosts.id): # kludge way to select only rows per host with the best OS-guess os_title = r.t_os.f_title or 'Unknown' os_vendor = r.t_os.f_vendor or 'Unknown' os_family = r.t_host_os_refs.f_family or 'Unknown' os_class = r.t_host_os_refs.f_class or 'Unknown' # only capitalize if the first char of the string isn't already capitalized # this covers not destroying things like HP, IOS, etc #if os_vendor[0].islower(): os_vendor = os_vendor.capitalize() if os_family[0].islower(): os_family = os_family.capitalize() if os_class[0].islower(): os_class = os_class.capitalize() count = os_counts.setdefault(os_title, 0) count += 1 os_counts[os_title] = count count = vendor_counts.setdefault(os_vendor, 0) count += 1 vendor_counts[os_vendor] = count count = family_counts.setdefault(os_family, 0) count += 1 family_counts[os_family] = count count = class_counts.setdefault(os_class, 0) count += 1 class_counts[os_class] = count response.title = "%s :: Operating System Statistics" % (settings.title) return dict( vendor_counts=vendor_counts, os_counts=os_counts, family_counts=family_counts, class_counts=class_counts, )
def service_vulns_list(): # XXX: this doesn't work yet. . . query = (db.t_service_vulns.id > 0) & (db.t_service_vulns.f_services_id == db.t_services.id) & (db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) query = create_hostfilter_query(session.hostfilter, query, 't_services') columns = [ db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, db.t_vulndata.f_vulnid, db.t_service_vulns.f_status, db.t_service_vulns.f_proof, #db.t_service_vulns.id ] rows = SQLFORM.grid(query, columns, deletable=True, selectable=True, details=False, field_id=db.t_service_vulns.id) response.title = "Services with Vulnerabilities" return dict(rows=rows)
def vulnlist(qstr="%", hostfilter=None): """ Returns a vulnerability dictionary with counts: :param qstr: Vulnerability identity for .like() :param hostfilter: A valid hostfilter or None :returns dict: { 'vulnerability id': [ status, count, severity, cvss ] } """ db = current.globalenv['db'] session = current.globalenv['session'] status = db.t_service_vulns.f_status svcv_id = db.t_service_vulns.id vulnid = db.t_vulndata.id f_vulnid = db.t_vulndata.f_vulnid f_title = db.t_vulndata.f_title sev = db.t_vulndata.f_severity cvss = db.t_vulndata.f_cvss_score hostfilter = hostfilter or session.hostfilter query = db.t_vulndata.f_vulnid.like(qstr) query &= (db.t_service_vulns.f_services_id == db.t_services.id) & ( db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) query = create_hostfilter_query(hostfilter, query, 't_services') #query = (db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) vulnlist = {} for rec in db(query).select(status, vulnid, f_vulnid, f_title, svcv_id, sev, cvss): q2 = (query & ((db.t_service_vulns.f_vulndata_id == rec.t_vulndata.id) & (db.t_service_vulns.f_status == rec.t_service_vulns.f_status))) vcount = db(q2).count() vstats = vulnlist.setdefault(rec.t_vulndata.f_vulnid, list()) if rec.t_service_vulns.f_status not in [a[0] for a in vstats]: ecount = db(db.t_exploit_references.f_vulndata_id == rec.t_vulndata.id).count() vstats.append([ rec.t_service_vulns.f_status, vcount, rec.t_vulndata.f_severity, rec.t_vulndata.f_cvss_score, rec.t_vulndata.f_title, ecount, ]) vulnlist[rec.t_vulndata.f_vulnid] = vstats return vulnlist
def accounts_grid(): response.title = "%s :: Accounts" % (settings.title) query = (db.t_accounts.id > 0) & (db.t_accounts.f_services_id== db.t_services.id) query = create_hostfilter_query(session.hostfilter, query, 't_services') columns = [ db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, db.t_accounts.f_fullname, db.t_accounts.f_domain, db.t_accounts.f_password, db.t_accounts.f_hash1_type, db.t_accounts.f_hash1, db.t_accounts.f_hash2_type, db.t_accounts.f_hash2, db.t_accounts.f_uid, db.t_accounts.f_gid, db.t_accounts.f_level, db.t_accounts.f_active, db.t_accounts.f_lockout, db.t_accounts.f_duration, db.t_accounts.f_source, db.t_accounts.f_message, db.t_accounts.f_description, db.t_accounts.id, ] rows = SQLFORM.grid(query, columns, deletable=True, selectable=True, details=False, field_id=db.t_accounts.id) return dict(rows=rows)
def vulnlist(query="%", hostfilter=None): """ Returns a vulnerability dictionary with counts: { 'vulnerability id': [ status, count, severity, cvss ] } """ db = current.globalenv['db'] session = current.globalenv['session'] status = db.t_service_vulns.f_status svcv_id = db.t_service_vulns.id vulnid = db.t_vulndata.id f_vulnid = db.t_vulndata.f_vulnid sev = db.t_vulndata.f_severity cvss = db.t_vulndata.f_cvss_score hostfilter = hostfilter or session.hostfilter if hostfilter is None: # if no filter is set then we blank it out if session.hostfilter is None: session.hostfilter = [(None, None), False] query = (db.t_vulndata.f_vulnid.contains(query)) query &= (db.t_service_vulns.f_services_id == db.t_services.id) & ( db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) query = create_hostfilter_query(hostfilter, query, 't_services') #query = (db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) vulnlist = {} for rec in db(query).select(status, vulnid, f_vulnid, svcv_id, sev, cvss): q2 = (query & ((db.t_service_vulns.f_vulndata_id == rec.t_vulndata.id) & (db.t_service_vulns.f_status == rec.t_service_vulns.f_status))) count = db(q2).count() vstats = vulnlist.setdefault(rec.t_vulndata.f_vulnid, list()) if rec.t_service_vulns.f_status not in map(lambda a: a[0], vstats): vstats.append([ rec.t_service_vulns.f_status, count, rec.t_vulndata.f_severity, rec.t_vulndata.f_cvss_score ]) vulnlist[rec.t_vulndata.f_vulnid] = vstats return vulnlist
def vulnlist(qstr="%", hostfilter=None): """ Returns a vulnerability dictionary with counts: :param qstr: Vulnerability identity for .like() :param hostfilter: A valid hostfilter or None :returns dict: { 'vulnerability id': [ status, count, severity, cvss ] } """ db = current.globalenv['db'] session = current.globalenv['session'] status = db.t_service_vulns.f_status svcv_id = db.t_service_vulns.id vulnid = db.t_vulndata.id f_vulnid = db.t_vulndata.f_vulnid f_title = db.t_vulndata.f_title sev = db.t_vulndata.f_severity cvss = db.t_vulndata.f_cvss_score hostfilter = hostfilter or session.hostfilter query = db.t_vulndata.f_vulnid.like(qstr) query &= (db.t_service_vulns.f_services_id == db.t_services.id) & (db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) query = create_hostfilter_query(hostfilter, query, 't_services') #query = (db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) vulnlist = {} for rec in db(query).select(status, vulnid, f_vulnid, f_title, svcv_id, sev, cvss): q2 = (query & ((db.t_service_vulns.f_vulndata_id == rec.t_vulndata.id) & (db.t_service_vulns.f_status == rec.t_service_vulns.f_status))) vcount = db(q2).count() vstats = vulnlist.setdefault(rec.t_vulndata.f_vulnid, list()) if rec.t_service_vulns.f_status not in map(lambda a:a[0], vstats): ecount = db(db.t_exploit_references.f_vulndata_id==rec.t_vulndata.id).count() vstats.append([rec.t_service_vulns.f_status, vcount, rec.t_vulndata.f_severity, rec.t_vulndata.f_cvss_score, rec.t_vulndata.f_title, ecount, ] ) vulnlist[rec.t_vulndata.f_vulnid] = vstats return vulnlist
def vulnlist(query="%", hostfilter=None): """ Returns a vulnerability dictionary with counts: { 'vulnerability id': [ status, count, severity, cvss ] } """ db = current.globalenv['db'] session = current.globalenv['session'] status = db.t_service_vulns.f_status svcv_id = db.t_service_vulns.id vulnid = db.t_vulndata.id f_vulnid = db.t_vulndata.f_vulnid sev = db.t_vulndata.f_severity cvss = db.t_vulndata.f_cvss_score hostfilter = hostfilter or session.hostfilter if hostfilter is None: # if no filter is set then we blank it out if session.hostfilter is None: session.hostfilter = [(None, None), False] query = (db.t_vulndata.f_vulnid.contains(query)) query &= (db.t_service_vulns.f_services_id == db.t_services.id) & (db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) query = create_hostfilter_query(hostfilter, query, 't_services') #query = (db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) vulnlist = {} for rec in db(query).select(status, vulnid, f_vulnid, svcv_id, sev, cvss): q2 = (query & ((db.t_service_vulns.f_vulndata_id == rec.t_vulndata.id) & (db.t_service_vulns.f_status == rec.t_service_vulns.f_status))) count = db(q2).count() vstats = vulnlist.setdefault(rec.t_vulndata.f_vulnid, list()) if rec.t_service_vulns.f_status not in map(lambda a:a[0], vstats): vstats.append([rec.t_service_vulns.f_status, count, rec.t_vulndata.f_severity, rec.t_vulndata.f_cvss_score ] ) vulnlist[rec.t_vulndata.f_vulnid] = vstats return vulnlist
def new_service_vulns(): # server-side processing of service vulns.. faster..better? # TODO: This...? response.title = "%s :: Services and Vulnerabilities" % (settings.title) if request.extension == 'json': if session.hostfilter is None: session.hostfilter = [(None, None), False] query = (db.t_service_vulns.id > 0) & (db.t_service_vulns.f_services_id == db.t_services.id) & (db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) query = create_hostfilter_query(session.hostfilter, query, 't_services') if request.vars.has_key('iDisplayStart'): start = int(request.vars.iDisplayStart) else: start = 0 if request.vars.has_key('iDisplayLength'): if request.vars.iDisplayLength == '-1': limit = db(query).count() else: limit = start + int(request.vars.iDisplayLength) else: limit = int(auth.user.f_show_size) if request.vars.has_key('sSearch'): # sSearch global search box query &= db.t_vulndata.f_vulnid.like("%%%s%%" % request.vars.sSearch) | db.t_vulndata.f_title.like("%%%s%%" % request.vars.sSearch) if request.vars.iSortingCols == '1': # sorting by a column - this is a little trippy because tuples start at 0 # and datatables starts at 1 so we have to subtract 1 from iSortCol_0 cols = ( None, db.t_vulndata.id, db.t_vulndata.f_vulnid, db.t_vulndata.f_title, db.t_vulndata.f_severity, None, db.t_vulndata.f_cvss_score )
def new_service_vulns(): # server-side processing of service vulns.. faster..better? # TODO: This...? response.title = "%s :: Services and Vulnerabilities" % (settings.title) if request.extension == 'json': if session.hostfilter is None: session.hostfilter = [(None, None), False] query = (db.t_service_vulns.id > 0) & ( db.t_service_vulns.f_services_id == db.t_services.id) & ( db.t_service_vulns.f_vulndata_id == db.t_vulndata.id) query = create_hostfilter_query(session.hostfilter, query, 't_services') if request.vars.has_key('iDisplayStart'): start = int(request.vars.iDisplayStart) else: start = 0 if request.vars.has_key('iDisplayLength'): if request.vars.iDisplayLength == '-1': limit = db(query).count() else: limit = start + int(request.vars.iDisplayLength) else: limit = int(auth.user.f_show_size) if request.vars.has_key('sSearch'): # sSearch global search box query &= db.t_vulndata.f_vulnid.like( "%%%s%%" % request.vars.sSearch) | db.t_vulndata.f_title.like( "%%%s%%" % request.vars.sSearch) if request.vars.iSortingCols == '1': # sorting by a column - this is a little trippy because tuples start at 0 # and datatables starts at 1 so we have to subtract 1 from iSortCol_0 cols = (None, db.t_vulndata.id, db.t_vulndata.f_vulnid, db.t_vulndata.f_title, db.t_vulndata.f_severity, None, db.t_vulndata.f_cvss_score)
def customer_xml(): """ Generates an XML file suitable for Customer usage """ from lxml import etree location_attribute = '{%s}noNameSpaceSchemaLocation' % "http://www.w3.org/2001/XMLSchema-instance" kvasir_results_xml = etree.Element('KvasirResults', attrib={ location_attribute: 'kvasir.xsd', }) summary_xml = etree.SubElement(kvasir_results_xml, 'summary') customer = etree.SubElement(summary_xml, 'customer') customer.text = settings.customer or 'CUSTOMER NAME' assessment = etree.SubElement(summary_xml, 'assessment') assessment.set('type', settings.assessment_type) start_date = etree.SubElement(assessment, 'start-date') start_date.text = settings.start_date or 'START DATE' end_date = etree.SubElement(assessment, 'end-date') end_date.text = settings.end_date or 'END DATE' hosts_xml = etree.SubElement(kvasir_results_xml, 'hosts') os_xml = etree.SubElement(kvasir_results_xml, 'os_records') vulns_xml = etree.SubElement(kvasir_results_xml, 'vulns') # this is a little hack to ensure a record is either blank or None # use it as "if variable not in notin:" notin = [None, ''] unknown_cpeid_counter = 0 # go through each host, adding the os, services and vulns accordingly query = create_hostfilter_query(session.hostfilter) for host_rec in db(query).select(): host_xml = etree.SubElement(hosts_xml, 'host') host_xml.set('ipaddr', host_rec.f_ipaddr) host_xml.set('assetgroup', host_rec.f_asset_group) if host_rec.f_macaddr: host_xml.set('macaddr', host_rec.f_macaddr) if host_rec.f_hostname: host_xml.set('hostname', host_rec.f_hostname.decode('utf-8')) if host_rec.f_netbios_name: host_xml.set('netbios', host_rec.f_netbios_name.decode('utf-8')) # build the os information using the highest certainty record highest = (0, None) for os_rec in db(db.t_host_os_refs.f_hosts_id == host_rec.id).select(): if os_rec.f_certainty > highest[0]: highest = (os_rec.f_certainty, os_rec) if highest[0] > 0: # add os element to the host record = highest[1] os = etree.SubElement(host_xml, 'os') os.set('certainty', str(highest[0])) if record.f_class not in notin: os.set('class', record.f_class) if record.f_family not in notin: os.set('family', record.f_family) # since some os records may not have a cpe id we'll mask them with # using their title, replacing spaces with underscores t_os_rec = db.t_os[record.f_os_id] if t_os_rec.f_cpename in notin: cpeid = t_os_rec.f_title.replace(' ', '_') else: cpeid = t_os_rec.f_cpename os.set('id', cpeid) # if the id isn't in os_records, add it if len(os_xml.findall('.//os[@id="%s"]' % (os.get('id', None)))) < 1: os_info_xml = etree.SubElement(os_xml, 'os') os_rec = db.t_os[highest[1].f_os_id] os_info_xml.set('id', cpeid) os_info_xml.set('title', os_rec.f_title) if os_rec.f_vendor not in notin: vendor = etree.SubElement(os_info_xml, 'vendor') vendor.text = os_rec.f_vendor if os_rec.f_product not in notin: product = etree.SubElement(os_info_xml, 'product') product.text = os_rec.f_product if os_rec.f_version not in notin: version = etree.SubElement(os_info_xml, 'version') version.text = os_rec.f_version if os_rec.f_update not in notin: update = etree.SubElement(os_info_xml, 'update') update.text = os_rec.f_update if os_rec.f_edition not in notin: edition = etree.SubElement(os_info_xml, 'edition') edition.text = os_rec.f_edition if os_rec.f_language not in notin: language = etree.SubElement(os_info_xml, 'language') language.text = os_rec.f_language # snmp strings snmp_recs = db(db.t_snmp.f_hosts_id == host_rec.id).select() if len(snmp_recs) > 0: snmp_top_xml = etree.SubElement(hosts_xml, 'snmps') for record in snmp_recs: snmp_xml = etree.SubElement(snmp_top_xml, 'snmp') if record.f_community not in notin: snmp_xml.set('community', record.f_community.decode('utf-8')) snmp_xml.set('version', record.f_version) snmp_xml.set('access', record.f_access) # netbios information netb_record = db( db.t_netbios.f_hosts_id == host_rec.id).select().first() or None if netb_record: netbios_xml = etree.SubElement(hosts_xml, 'netbios') if netb_record.f_type not in notin: netbios_xml.set('type', netb_record.f_type) if netb_record.f_domain not in notin: netbios_xml.set('domain', netb_record.f_domain.decode('utf-8')) if netb_record.f_lockout_limit not in notin: netbios_xml.set('lockout_limit', str(netb_record.f_lockout_limit)) if netb_record.f_lockout_duration not in notin: netbios_xml.set('lockout_duration', str(netb_record.f_lockout_duration)) if netb_record.f_advertised_names is not None: adv_names_xml = etree.SubElement(netbios_xml, 'advertised_names') for name in netb_record.f_advertised_names: name_xml = etree.SubElement(adv_names_xml, 'name') name.text = name.decode('utf-8') # build the services and vulnerabilities services_xml = etree.SubElement(host_xml, 'services') for svc_rec in db(db.t_services.f_hosts_id == host_rec.id).select(): service_xml = etree.SubElement(services_xml, 'service') service_xml.set('proto', svc_rec.f_proto) service_xml.set('number', svc_rec.f_number) if svc_rec.f_name not in notin: name = etree.SubElement(service_xml, 'name') name.text = svc_rec.f_name.decode('utf-8') if svc_rec.f_banner not in notin: banner = etree.SubElement(service_xml, 'banner') banner.text = svc_rec.f_banner.decode('utf-8') # service configuration records svc_info_recs = db( db.t_service_info.f_services_id == svc_rec.id).select() if len(svc_info_recs) > 0: config_xml = etree.SubElement(service_xml, 'configuration') for info_rec in svc_info_recs: rec_xml = etree.SubElement(config_xml, 'config') if info_rec.f_name not in notin: rec_xml.set('name', info_rec.f_name) if info_rec.f_text not in notin: rec_xml.text = info_rec.f_text.decode('utf-8') # vulnerabilities svc_vuln_recs = db( db.t_service_vulns.f_services_id == svc_rec.id).select() if len(svc_vuln_recs) > 0: svc_vulns_xml = etree.SubElement(service_xml, 'vulns') for vuln_rec in svc_vuln_recs: vuln_xml = etree.SubElement(svc_vulns_xml, 'vuln') vuln_xml.set('status', vuln_rec.f_status) vuln_xml.set( 'id', db.t_vulndata[vuln_rec.f_vulndata_id].f_vulnid) proof = etree.SubElement(vuln_xml, 'proof') proof.text = etree.CDATA( unicode(MARKMIN(vuln_rec.f_proof).xml(), 'utf-8')) # search for the nexpose id in vulns_xml if len( vuln_xml.findall('.//vuln[@id="%s"]' % vuln_xml.get('id', None))) < 1: new_vuln_xml = etree.SubElement(vulns_xml, 'vuln') vulndata = db.t_vulndata[vuln_rec.f_vulndata_id] new_vuln_xml.set('id', vulndata.f_vulnid) new_vuln_xml.set('title', vulndata.f_title) new_vuln_xml.set('severity', str(vulndata.f_severity)) new_vuln_xml.set('pci_sev', str(vulndata.f_pci_sev)) new_vuln_xml.set('cvss_score', str(vulndata.f_cvss_score)) new_vuln_xml.set('cvss_metric', cvss_metrics(vulndata)) description = etree.SubElement(new_vuln_xml, 'description') description.text = etree.CDATA( unicode( MARKMIN(vulndata.f_description).xml(), 'utf-8')) solution = etree.SubElement(new_vuln_xml, 'solution') solution.text = etree.CDATA( unicode( MARKMIN(vulndata.f_solution).xml(), 'utf-8')) # find vulnerability references and add them vuln_refs = db(db.t_vuln_references.f_vulndata_id == vulndata.id).select() if len(vuln_refs) > 0: refs_xml = etree.SubElement( new_vuln_xml, 'references') for ref_rec in vuln_refs: record = db.t_vuln_refs[ref_rec.f_vuln_ref_id] ref_xml = etree.SubElement( refs_xml, 'reference') ref_xml.set('source', record.f_source) ref_xml.text = record.f_text.decode('utf-8') # accounts accounts = db(db.t_accounts.f_services_id == svc_rec.id).select() if len(accounts) > 0: accounts_xml = etree.SubElement(service_xml, 'accounts') for acct_rec in accounts: acct_xml = etree.SubElement(accounts_xml, 'account') if acct_rec.f_username not in notin: elem = etree.SubElement(acct_xml, 'username') elem.text = acct_rec.f_username.decode('utf-8') if acct_rec.f_fullname not in notin: elem = etree.SubElement(acct_xml, 'fullname') elem.text = acct_rec.f_fullname.decode('utf-8') if acct_rec.f_password not in notin: elem = etree.SubElement(acct_xml, 'password') elem.text = acct_rec.f_password.decode('utf-8') if acct_rec.f_hash1 not in notin: elem = etree.SubElement(acct_xml, 'hash1') elem.text = acct_rec.f_hash1 if acct_rec.f_hash1_type not in notin: elem = etree.SubElement(acct_xml, 'hash1_type') elem.text = acct_rec.f_hash1_type if acct_rec.f_hash2 not in notin: elem = etree.SubElement(acct_xml, 'hash2') elem.text = acct_rec.f_hash2 if acct_rec.f_hash2_type not in notin: elem = etree.SubElement(acct_xml, 'hash2_type') elem.text = acct_rec.f_hash2_type if acct_rec.f_uid not in notin: elem = etree.SubElement(acct_xml, 'uid') elem.text = acct_rec.f_uid if acct_rec.f_gid not in notin: elem = etree.SubElement(acct_xml, 'gid') elem.text = acct_rec.f_gid if acct_rec.f_level not in notin: elem = etree.SubElement(acct_xml, 'level') elem.text = acct_rec.f_level if acct_rec.f_domain not in notin: elem = etree.SubElement(acct_xml, 'domain') elem.text = acct_rec.f_domain.decode('utf-8') if acct_rec.f_description not in notin: elem = etree.SubElement(acct_xml, 'description') elem.text = acct_rec.f_description.decode('utf-8') result = etree.tostring(kvasir_results_xml, pretty_print=True, encoding=unicode) return result
def hosts_with_port(): """ Creates a CSV file of ipv4,ipv6 for hosts with a user-specified tcp/udp port """ # XXX: This is broken and needs some TLC # buld the dropdown user list #users = db(db.auth_user).select() #userlist = [] #for user in users: # userlist.append( [ user.id, user.username ] ) form = SQLFORM.factory( Field('f_proto', 'string', label=T('Protocol'), default="tcp", requires=IS_IN_SET(("tcp", "udp", "info"))), Field('f_number', type='string', label=T('Port')), Field('f_name', type='string', label=T('Name (exact)')), Field('f_banner', type='string', label=T('Banner (contains)')), Field('ignore_filter', type='boolean', default=False, label=T('Ignore Hostfilter')), #Field('f_ipaddr', type='boolean', default=True, label=T('Show IP Address')), #Field('f_hostname', type='boolean', default=False, label=T('Show Hostname')), #Field('f_engineer', type='integer', label=T('Engineer'), default=auth.user.id, requires=IS_IN_SET(userlist)), #Field('f_asset_group', type='string', label=T('Asset Group'), requires=IS_NOT_EMPTY()), _action=URL(request.application,'services','hosts_with_port.csv'), ) db_svcs = db.t_services db_hosts = db.t_hosts if form.accepts(request.vars, session): q = (db_svcs.id > 0) q1 = None if form.vars.f_number: q1 = (db_svcs.f_number == form.vars.f_number) if form.vars.f_proto: q2 = (db_svcs.f_proto == form.vars.f_proto) if q1: q1 = q1 & q2 if form.vars.f_name: q2 = (db_svcs.f_name == form.vars.f_name) if q1: q1 = q1 & q2 if form.vars.f_banner: q2 = (db_svcs.f_banner.contains(form.vars.f_banner)) if q1: q1 = q1 & q2 if q1: q = q & q1 if not form.vars.ignore_filter: q = create_hostfilter_query(session.hostfilter, q, 't_services') else: q &= (db_svcs.f_hosts_id == db_hosts.id) ip_list = db(q).select(db_hosts.f_ipaddr, db_svcs.f_number, db_hosts.f_hostname, cache=(cache.ram, 60)) return dict( ip_list=ip_list, ) elif form.errors: response.flash = 'Error in form' redirect(URL('hosts_with_port', extension='')) return dict(form=form)
def list(): from skaldship.general import severity_mapping response.title = "%s :: Services" % (settings.title) if request.extension == 'json': q = (db.t_services.id > 0) proto = request.vars.f_proto pnum = request.vars.f_number if pnum: q &= (db.t_services.f_number == pnum) if proto: q &= (db.t_services.f_protocol == proto) q = create_hostfilter_query(session.hostfilter, q, 't_services') # Datatables Server-side: http://datatables.net/usage/server-side if request.vars.has_key('iDisplayStart'): start = int(request.vars.iDisplayStart) else: start = 0 if request.vars.has_key('iDisplayLength'): if request.vars.iDisplayLength == '-1': limit = db(q).count() else: limit = start + int(request.vars.iDisplayLength) else: limit = int(auth.user.f_show_size) srch_data = request.vars.get('sSearch') if srch_data: # sSearch global search box # parse the search into fields (port:num proto:tcp etc) srch_vals = [ ["port", db.t_services.f_number], ["proto", db.t_services.f_proto], ["status", db.t_services.f_status], ["name", db.t_services.f_name], ["banner", db.t_services.f_banner], ["ip", db.t_hosts.f_ipaddr], ["hostname", db.t_hosts.f_hostname], ] parsed = False for val in srch_vals: srch_str = "%s:(?P<f>\w+)" % val[0] srch_res = re.findall(srch_str, srch_data) for res in srch_res: parsed = True if val[0] == 'banner': q &= (val[1].contains(res)) else: q &= (val[1].upper() == res.upper()) if not parsed: q &= db.t_services.f_proto.like("%%%s%%" % request.vars.sSearch) | \ db.t_services.f_number.like("%%%s%%" % request.vars.sSearch) | \ db.t_services.f_name.like("%%%s%%" % request.vars.sSearch) | \ db.t_services.f_banner.like("%%%s%%" % request.vars.sSearch) | \ db.t_services.f_status.like("%%%s%%" % request.vars.sSearch) if request.vars.iSortingCols == '1': cols = ( None, None, None, db.t_services.f_hosts_id, db.t_services.f_proto, db.t_services.f_number, db.t_services.f_status, None, None, None, None, db.t_services.f_name, db.t_services.f_banner, ) orderby = cols[int(request.vars.iSortCol_0)] if request.vars.sSortDir_0 == 'asc': rows=db(q).select(orderby=orderby, limitby=(start, limit)) else: rows=db(q).select(orderby=~orderby, limitby=(start, limit)) else: rows=db(q).select(limitby=(start, limit)) nolimit = db(q).count() aaData = [] # datatable formatting is specific # gather all the vulndata and exploits into a big row # later we'll do a find(lambda: row: row.<db>.<field> == <value>) # to slice it into the bits we need. Maybe it'll be faster? #vulndata = db().select(db.t_vulndata.f_vulnid, db.t_vulndata.id, db.t_exploit_references.f_exploit_id, # left=db.t_exploit_references.on(db.t_vulndata.id==db.t_exploit_references.f_vulndata_id)) for r in rows: atxt = {} vulncount = 0 vulns = db(db.t_service_vulns.f_services_id==r.t_services.id).select(db.t_service_vulns.f_vulndata_id, cache=(cache.ram, 60)) vulnlist = [] explist=[] for vuln in vulns: vuln_rec = db.t_vulndata[vuln.f_vulndata_id] if vuln_rec.f_vulnid not in vulnlist: if settings.use_cvss: vulnlist.append((vuln_rec.f_vulnid, vuln_rec.f_cvss_score)) else: vulnlist.append((vuln_rec.f_vulnid, vuln_rec.f_severity)) exploits = db(db.t_exploit_references.f_vulndata_id == vuln.f_vulndata_id).select(cache=(cache.ram, 60)) if len(exploits) > 0: for expinfo in exploits: exp = db.t_exploits[expinfo.f_exploit_id] exp_link = A(exp.f_name, _href=URL('exploits', 'edit', extension='html', args=exp.id), _target='blank') explist.append(TR(TD(exp_link), TD(exp.f_title), TD(exp.f_source), TD(exp.f_rank) ) ) q = r.t_services.t_service_info.select(cache=(cache.ram, 60)) if (len(q) > 0) or (len(explist) > 0) or (len(vulnlist) > 0): atxt['0'] = IMG(_src=URL(request.application,'static','images/details_open.png')).xml() else: atxt['0'] = "" atxt['1'] = A("edit", _target="services_edit_%s" % (r.t_services.id), _href=URL('edit', args=[r.t_services.id], extension='html')).xml() if len(q) > 0: addl = [] for svcinfo in q: addl.append(TR(TD(svcinfo.f_name), TD(svcinfo.f_text))) atxt['2'] = TABLE(THEAD(TR(TH(T('Name')), TH(T('Text')))), TBODY(addl), _class="table table-condensed table-striped", _style="width:100%").xml() else: atxt['2'] = '' host_rec = db.t_hosts[r.t_services.f_hosts_id] atxt['3'] = host_a_maker(host_rec).xml(), atxt['4'] = r.t_services.f_proto # Append A tags around services with HTTP Ports if r.t_services.f_number in HTTP_PORTS and r.t_services.f_proto == "tcp" or r.t_services.f_name == "HTTP": atxt['5'] = A(r.t_services.f_number, _href=URL('default', 'redirect', extension='html', vars={'url': "http://%s:%s/" % (host_rec.f_ipaddr, r.t_services.f_number)}), _target="%s-tcp-%s" % (host_rec.f_ipaddr, r.t_services.f_number)).xml() elif r.t_services.f_number in HTTPS_PORTS and r.t_services.f_proto == "tcp" or r.t_services.f_name == "HTTPS": atxt['5'] = A(r.t_services.f_number, _href=URL('default', 'redirect', extension='html', vars={'url': "https://%s:%s/" % (host_rec.f_ipaddr, r.t_services.f_number)}), _target="%s-tcp-%s" % (host_rec.f_ipaddr, r.t_services.f_number)).xml() else: atxt['5'] = r.t_services.f_number atxt['6'] = r.t_services.f_status atxt['7'] = len(vulnlist) vulntxt = [] for vuln in vulnlist: color = severity_mapping(vuln[1])[2] vulntxt.append(A(vuln[0], _id="vuln", _target="vulninfo_by_vulnid_%s" % (vuln[0]), _href=URL('vulns', 'vulninfo_by_vulnid', args=[vuln[0]], extension='html'), _style="color:"+color).xml()) atxt['8'] = " :: ".join(vulntxt) if len(explist) > 0: atxt['9'] = "Yes (%d)" % (len(explist)) else: atxt['9'] = '' if len(explist) > 0: atxt['10'] = TABLE(THEAD(TR(TH(T('Name')), TH(T('Title')), TH(T('Source')), TH(T('Rank')))), TBODY(explist), _class="table table-condensed", _style="width:100%").xml() else: atxt['10'] = '' atxt['11'] = r.t_services.f_name atxt['12'] = r.t_services.f_banner atxt['DT_RowId'] = r.t_services.id aaData.append(atxt) result = { 'sEcho': request.vars.sEcho, 'iTotalRecords': db(db.t_services).count(), 'iTotalDisplayRecords': nolimit, 'aaData': aaData, } return result else: add = AddModal( db.t_services, 'Add', 'Add', 'Add Service', #fields=[ # 'f_proto', 'f_number', 'f_status', 'f_name', 'f_banner' #], cmd='servicetable.fnReloadAjax();' ) db.t_services.id.comment = add.create() return dict(add=add)
def list(): response.title = "%s :: Accounts" % (settings.title) if request.extension == 'json': query = (db.t_accounts.id > 0) & (db.t_accounts.f_services_id== db.t_services.id) query = create_hostfilter_query(session.hostfilter, query, 't_services') if request.vars.hash_type is not None: query &= ((db.t_accounts.f_hash1_type == request.vars.hash_type) | (db.t_accounts.f_hash2_type == request.vars.hash_type)) if request.vars.has_key('iDisplayStart'): start = int(request.vars.iDisplayStart) else: start = 0 if request.vars.has_key('iDisplayLength'): if request.vars.iDisplayLength == '-1': limit = db(query).count() else: limit = start + int(request.vars.iDisplayLength) else: limit = int(auth.user.f_show_size) srch_data = request.vars.get('sSearch') if srch_data: # sSearch global search box # parse the search into fields (port:num proto:tcp etc) srch_vals = [ ["port", db.t_services.f_number], ["proto", db.t_services.f_proto], ["user", db.t_accounts.f_username], ["name", db.t_accounts.f_fullname], ["domain", db.t_accounts.f_domain], ["hash", db.t_accounts.f_hash1], ["hash1", db.t_accounts.f_hash1], ["hash2", db.t_accounts.f_hash2], ["htype", db.t_accounts.f_hash1_type], ["uid", db.t_accounts.f_uid], ["gid", db.t_accounts.f_gid], ["level", db.t_accounts.f_level], ["source", db.t_accounts.f_source], ["desc", db.t_accounts.f_description], ["msg", db.t_accounts.f_message], ["ip", db.t_hosts.f_ipaddr], ["hostname", db.t_hosts.f_hostname], ] parsed = False for val in srch_vals: srch_str = "%s:(?P<f>\w+)" % val[0] srch_res = re.findall(srch_str, srch_data) for res in srch_res: parsed = True if val[0] in ['source', 'desc', 'hostname']: query &= (val[1].upper().contains(res.upper())) else: query &= (val[1].upper() == res.upper()) if not parsed: query &= db.t_accounts.f_username.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_password.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_fullname.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_domain.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_hash1.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_hash2.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_source.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_message.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_description.like("%%%s%%" % request.vars.sSearch) | \ db.t_hosts.f_ipaddr.like("%%%s%%" % request.vars.sSearch) | \ db.t_hosts.f_hostname.like("%%%s%%" % request.vars.sSearch) #total_count = db.t_vulndata.id.count() if request.vars.iSortingCols == '1': # sorting by a column - this is a little trippy because tuples start at 0 # and datatables starts at 1 so we have to subtract 1 from iSortCol_0 cols = ( db.t_accounts.f_compromised, db.t_hosts.f_ipaddr, db.t_services.f_number, db.t_accounts.f_username, db.t_accounts.f_fullname, db.t_accounts.f_domain, db.t_accounts.f_password, db.t_accounts.f_hash1_type, db.t_accounts.f_hash1, db.t_accounts.f_hash2_type, db.t_accounts.f_hash2, db.t_accounts.f_uid, db.t_accounts.f_gid, db.t_accounts.f_level, db.t_accounts.f_active, db.t_accounts.f_lockout, db.t_accounts.f_source, db.t_accounts.f_message, db.t_accounts.f_description ) orderby = cols[int(request.vars.iSortCol_0) ] if request.vars.sSortDir_0 == 'asc': rows=db(query).select( db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, orderby=orderby, limitby=(start, limit), cache=(cache.with_prefix(cache.ram, "accounts_list"), 180)) else: rows=db(query).select( db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, orderby=~orderby, limitby=(start, limit), cache=(cache.with_prefix(cache.ram, "accounts_list"), 180)) else: rows=db(query).select( db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, limitby=(start,limit), cache=(cache.with_prefix(cache.ram, "accounts_list"), 180)) #rows=db(q).select( # db.t_accounts.ALL, # db.t_hosts.id, # db.t_hosts.f_ipaddr, # db.t_hosts.f_hostname, # db.t_services.f_proto, # db.t_services.f_number, # #cache=(cache.ram,60) #) aaData = [] # datatable formatting is specific for r in rows: atxt = {} if r.t_accounts.f_compromised == True: atxt['0'] = '<div class="acct_compromised" name="row_id" id="%s"><span class="icon-check"></span></div>' % r.t_accounts.id else: atxt['0'] = '<div class="acct_uncompromised" name="row_id" id="%s"/>' % r.t_accounts.id #svc = db.t_services[r.f_services_id] atxt['1'] = host_a_maker(r.t_hosts).xml() atxt['2'] = "%s/%s" % (r.t_services.f_proto, r.t_services.f_number) atxt['3'] = DIV(A(I(_class="icon-pencil", _style="display: inline-block;"), _target="accounts_update_%s" % (r.t_accounts.id), \ _href=URL('edit.html', args=r.t_accounts.id), \ ), A("%s" % (r.t_accounts.f_username), \ _target="_blank", _id="username", \ _href=URL("by_username", vars={'username':r.t_accounts.f_username}, extension="html"), \ ) ).xml() atxt['4'] = r.t_accounts.f_fullname atxt['5'] = r.t_accounts.f_domain atxt['6'] = r.t_accounts.f_password atxt['7'] = r.t_accounts.f_hash1_type atxt['8'] = r.t_accounts.f_hash1 atxt['9'] = r.t_accounts.f_hash2_type atxt['10'] = r.t_accounts.f_hash2 atxt['11'] = r.t_accounts.f_uid atxt['12'] = r.t_accounts.f_gid atxt['13'] = r.t_accounts.f_level atxt['14'] = r.t_accounts.f_active atxt['15'] = r.t_accounts.f_source atxt['16'] = r.t_accounts.f_message atxt['17'] = r.t_accounts.f_description atxt['DT_RowId'] = str(r.t_accounts.id) aaData.append(atxt) result = { 'sEcho': request.vars.sEcho, 'iTotalDisplayRecords': db(query).count(), 'iTotalRecords': db(db.t_accounts).count(), 'aaData': aaData, 'query': db._lastsql, } return result rows=db(db.t_accounts).select(db.t_accounts.f_hash1_type, groupby=db.t_accounts.f_hash1_type, cache=(cache.ram, 60)) hash_types=[] for r in rows: #if r.f_hash2_type is not None: # hash_types.append("%s/%s" % (r.f_hash1_type, r.f_hash2_type)) #else: hash_types.append(r.f_hash1_type) form = TABLE(THEAD(TR(TH(T('C'), _width="1%"), TH(T('Host')), TH(T('Port')), TH(T('Username')), TH(T('Fullname')), TH(T('Domain')), TH(T('Password')), TH(T('Hash 1 Type')), TH(T('Hash 1')), TH(T('Hash 2 Type')), TH(T('Hash 2')), TH(T('UID')), TH(T('GID')), TH(T('Level')), TH(T('Active')), TH(T('Source')), TH(T('Message')), TH(T('Description')), ) ), _class="datatable", _id="accounttable", _style="width:100%") add = AddModal( db.t_accounts, 'Add', 'Add', 'Add Account', #fields=[], cmd='accounttable.fnReloadAjax();' ) services = db(db.t_services.f_hosts_id > 0).select(cache=(cache.ram,30)) svc_set = [] for svc in services: svc_set.append([svc.id, "%s :: %s/%s" % (host_title_maker(db.t_hosts[svc.f_hosts_id]), svc.f_proto, svc.f_number)]) db.t_accounts.f_services_id.requires = IS_IN_SET(svc_set) db.t_accounts.id.comment = add.create() return dict(form=form, hash_types=hash_types, add=add)
def list(): response.title = "%s :: Accounts" % (settings.title) # if no filter is set then we blank it out if session.hostfilter is None: session.hostfilter = [(None, None), False] if request.extension == "json": query = (db.t_accounts.id > 0) & (db.t_accounts.f_services_id == db.t_services.id) query = create_hostfilter_query(session.hostfilter, query, "t_services") if request.vars.hash_type is not None: query &= (db.t_accounts.f_hash1_type == request.vars.hash_type) | ( db.t_accounts.f_hash2_type == request.vars.hash_type ) if request.vars.has_key("iDisplayStart"): start = int(request.vars.iDisplayStart) else: start = 0 if request.vars.has_key("iDisplayLength"): if request.vars.iDisplayLength == "-1": limit = db(query).count() else: limit = start + int(request.vars.iDisplayLength) else: limit = int(auth.user.f_show_size) srch_data = request.vars.get("sSearch") if srch_data: # sSearch global search box # parse the search into fields (port:num proto:tcp etc) srch_vals = [ ["port", db.t_services.f_number], ["proto", db.t_services.f_proto], ["user", db.t_accounts.f_username], ["name", db.t_accounts.f_fullname], ["domain", db.t_accounts.f_domain], ["hash", db.t_accounts.f_hash1], ["hash1", db.t_accounts.f_hash1], ["hash2", db.t_accounts.f_hash2], ["htype", db.t_accounts.f_hash1_type], ["uid", db.t_accounts.f_uid], ["gid", db.t_accounts.f_gid], ["level", db.t_accounts.f_level], ["source", db.t_accounts.f_source], ["desc", db.t_accounts.f_description], ["msg", db.t_accounts.f_message], ["ip", db.t_hosts.f_ipv4], ["ipv4", db.t_hosts.f_ipv4], ["ipv6", db.t_hosts.f_ipv6], ["hostname", db.t_hosts.f_hostname], ] parsed = False for val in srch_vals: srch_str = "%s:(?P<f>\w+)" % val[0] srch_res = re.findall(srch_str, srch_data) for res in srch_res: parsed = True if val[0] in ["source", "desc", "hostname"]: query &= val[1].upper().contains(res.upper()) else: query &= val[1].upper() == res.upper() if not parsed: query &= ( db.t_accounts.f_username.like("%%%s%%" % request.vars.sSearch) | db.t_accounts.f_password.like("%%%s%%" % request.vars.sSearch) | db.t_accounts.f_fullname.like("%%%s%%" % request.vars.sSearch) | db.t_accounts.f_domain.like("%%%s%%" % request.vars.sSearch) | db.t_accounts.f_hash1.like("%%%s%%" % request.vars.sSearch) | db.t_accounts.f_hash2.like("%%%s%%" % request.vars.sSearch) | db.t_accounts.f_source.like("%%%s%%" % request.vars.sSearch) | db.t_accounts.f_message.like("%%%s%%" % request.vars.sSearch) | db.t_accounts.f_description.like("%%%s%%" % request.vars.sSearch) | db.t_hosts.f_ipv4.like("%%%s%%" % request.vars.sSearch) | db.t_hosts.f_ipv6.like("%%%s%%" % request.vars.sSearch) | db.t_hosts.f_hostname.like("%%%s%%" % request.vars.sSearch) ) # total_count = db.t_vulndata.id.count() if request.vars.iSortingCols == "1": # sorting by a column - this is a little trippy because tuples start at 0 # and datatables starts at 1 so we have to subtract 1 from iSortCol_0 cols = ( db.t_accounts.f_compromised, db.t_hosts.f_ipv4, db.t_services.f_number, db.t_accounts.f_username, db.t_accounts.f_fullname, db.t_accounts.f_domain, db.t_accounts.f_password, db.t_accounts.f_hash1_type, db.t_accounts.f_hash1, db.t_accounts.f_hash2_type, db.t_accounts.f_hash2, db.t_accounts.f_uid, db.t_accounts.f_gid, db.t_accounts.f_level, db.t_accounts.f_active, db.t_accounts.f_lockout, db.t_accounts.f_source, db.t_accounts.f_message, db.t_accounts.f_description, ) orderby = cols[int(request.vars.iSortCol_0)] if request.vars.sSortDir_0 == "asc": rows = db(query).select( db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipv4, db.t_hosts.f_ipv6, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, orderby=orderby, limitby=(start, limit), cache=(cache.with_prefix(cache.ram, "accounts_list"), 180), ) else: rows = db(query).select( db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipv4, db.t_hosts.f_ipv6, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, orderby=~orderby, limitby=(start, limit), cache=(cache.with_prefix(cache.ram, "accounts_list"), 180), ) else: rows = db(query).select( db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipv4, db.t_hosts.f_ipv6, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, limitby=(start, limit), cache=(cache.with_prefix(cache.ram, "accounts_list"), 180), ) # rows=db(q).select( # db.t_accounts.ALL, # db.t_hosts.id, # db.t_hosts.f_ipv4, # db.t_hosts.f_ipv6, # db.t_hosts.f_hostname, # db.t_services.f_proto, # db.t_services.f_number, # #cache=(cache.ram,60) # ) aaData = [] # datatable formatting is specific for r in rows: atxt = {} if r.t_accounts.f_compromised == True: atxt["0"] = ( '<div class="acct_compromised" name="row_id" id="%s"><span class="icon-check"></span></div>' % r.t_accounts.id ) else: atxt["0"] = '<div class="acct_uncompromised" name="row_id" id="%s"/>' % r.t_accounts.id # svc = db.t_services[r.f_services_id] atxt["1"] = host_a_maker(r.t_hosts).xml() atxt["2"] = "%s/%s" % (r.t_services.f_proto, r.t_services.f_number) atxt["3"] = DIV( A( I(_class="icon-pencil", _style="display: inline-block;"), _target="accounts_update_%s" % (r.t_accounts.id), _href=URL("edit.html", args=r.t_accounts.id), ), A( "%s" % (r.t_accounts.f_username), _target="_blank", _id="username", _href=URL("by_username", vars={"username": r.t_accounts.f_username}, extension="html"), ), ).xml() atxt["4"] = r.t_accounts.f_fullname atxt["5"] = r.t_accounts.f_domain atxt["6"] = r.t_accounts.f_password atxt["7"] = r.t_accounts.f_hash1_type atxt["8"] = r.t_accounts.f_hash1 atxt["9"] = r.t_accounts.f_hash2_type atxt["10"] = r.t_accounts.f_hash2 atxt["11"] = r.t_accounts.f_uid atxt["12"] = r.t_accounts.f_gid atxt["13"] = r.t_accounts.f_level atxt["14"] = r.t_accounts.f_active atxt["15"] = r.t_accounts.f_source atxt["16"] = r.t_accounts.f_message atxt["17"] = r.t_accounts.f_description atxt["DT_RowId"] = str(r.t_accounts.id) aaData.append(atxt) result = { "sEcho": request.vars.sEcho, "iTotalDisplayRecords": db(query).count(), "iTotalRecords": db(db.t_accounts).count(), "aaData": aaData, "query": db._lastsql, } return result rows = db(db.t_accounts).select( db.t_accounts.f_hash1_type, groupby=db.t_accounts.f_hash1_type, cache=(cache.ram, 60) ) hash_types = [] for r in rows: # if r.f_hash2_type is not None: # hash_types.append("%s/%s" % (r.f_hash1_type, r.f_hash2_type)) # else: hash_types.append(r.f_hash1_type) form = TABLE( THEAD( TR( TH(T("C"), _width="1%"), TH(T("Host")), TH(T("Port")), TH(T("Username")), TH(T("Fullname")), TH(T("Domain")), TH(T("Password")), TH(T("Hash 1 Type")), TH(T("Hash 1")), TH(T("Hash 2 Type")), TH(T("Hash 2")), TH(T("UID")), TH(T("GID")), TH(T("Level")), TH(T("Active")), TH(T("Source")), TH(T("Message")), TH(T("Description")), ) ), _class="datatable", _id="accounttable", _style="width:100%", ) add = AddModal( db.t_accounts, "Add", "Add", "Add Account", # fields=[], cmd="accounttable.fnReloadAjax();", ) services = db(db.t_services.f_hosts_id > 0).select(cache=(cache.ram, 30)) svc_set = [] for svc in services: svc_set.append( [svc.id, "%s :: %s/%s" % (host_title_maker(db.t_hosts[svc.f_hosts_id]), svc.f_proto, svc.f_number)] ) db.t_accounts.f_services_id.requires = IS_IN_SET(svc_set) db.t_accounts.id.comment = add.create() return dict(form=form, hash_types=hash_types, add=add)
def hosts_with_port(): """ Creates a CSV file of ipv4,ipv6 for hosts with a user-specified tcp/udp port """ # XXX: This is broken and needs some TLC # buld the dropdown user list #users = db(db.auth_user).select() #userlist = [] #for user in users: # userlist.append( [ user.id, user.username ] ) form = SQLFORM.factory( Field('f_proto', 'string', label=T('Protocol'), default="tcp", requires=IS_IN_SET(("tcp", "udp", "info"))), Field('f_number', type='string', label=T('Port')), Field('f_name', type='string', label=T('Name (exact)')), Field('f_banner', type='string', label=T('Banner (contains)')), Field('ignore_filter', type='boolean', default=False, label=T('Ignore Hostfilter')), #Field('f_ipaddr', type='boolean', default=True, label=T('Show IP Address')), #Field('f_hostname', type='boolean', default=False, label=T('Show Hostname')), #Field('f_engineer', type='integer', label=T('Engineer'), default=auth.user.id, requires=IS_IN_SET(userlist)), #Field('f_asset_group', type='string', label=T('Asset Group'), requires=IS_NOT_EMPTY()), _action=URL(request.application, 'services', 'hosts_with_port.csv'), ) db_svcs = db.t_services db_hosts = db.t_hosts if form.accepts(request.vars, session): q = (db_svcs.id > 0) q1 = None if form.vars.f_number: q1 = (db_svcs.f_number == form.vars.f_number) if form.vars.f_proto: q2 = (db_svcs.f_proto == form.vars.f_proto) if q1: q1 = q1 & q2 if form.vars.f_name: q2 = (db_svcs.f_name == form.vars.f_name) if q1: q1 = q1 & q2 if form.vars.f_banner: q2 = (db_svcs.f_banner.contains(form.vars.f_banner)) if q1: q1 = q1 & q2 if q1: q = q & q1 if not form.vars.ignore_filter: q = create_hostfilter_query(session.hostfilter, q, 't_services') else: q &= (db_svcs.f_hosts_id == db_hosts.id) ip_list = db(q).select(db_hosts.f_ipaddr, db_svcs.f_number, db_hosts.f_hostname, cache=(cache.ram, 60)) return dict(ip_list=ip_list, ) elif form.errors: response.flash = 'Error in form' redirect(URL('hosts_with_port', extension='')) return dict(form=form)
def list(): from skaldship.general import severity_mapping response.title = "%s :: Services" % (settings.title) if request.extension == 'json': q = (db.t_services.id > 0) proto = request.vars.f_proto pnum = request.vars.f_number if pnum: q &= (db.t_services.f_number == pnum) if proto: q &= (db.t_services.f_protocol == proto) q = create_hostfilter_query(session.hostfilter, q, 't_services') # Datatables Server-side: http://datatables.net/usage/server-side if 'iDisplayStart' in request.vars: start = int(request.vars.iDisplayStart) else: start = 0 if 'iDisplayLength' in request.vars: if request.vars.iDisplayLength == '-1': limit = db(q).count() else: limit = start + int(request.vars.iDisplayLength) else: limit = int(auth.user.f_show_size) srch_data = request.vars.get('sSearch') if srch_data: # sSearch global search box # parse the search into fields (port:num proto:tcp etc) srch_vals = [ ["port", db.t_services.f_number], ["proto", db.t_services.f_proto], ["status", db.t_services.f_status], ["name", db.t_services.f_name], ["banner", db.t_services.f_banner], ["ip", db.t_hosts.f_ipaddr], ["hostname", db.t_hosts.f_hostname], ] parsed = False for val in srch_vals: srch_str = "%s:(?P<f>\w+)" % val[0] srch_res = re.findall(srch_str, srch_data) for res in srch_res: parsed = True if val[0] == 'banner': q &= (val[1].contains(res)) else: q &= (val[1].upper() == res.upper()) if not parsed: q &= db.t_services.f_proto.like("%%%s%%" % request.vars.sSearch) | \ db.t_services.f_number.like("%%%s%%" % request.vars.sSearch) | \ db.t_services.f_name.like("%%%s%%" % request.vars.sSearch) | \ db.t_services.f_banner.like("%%%s%%" % request.vars.sSearch) | \ db.t_services.f_status.like("%%%s%%" % request.vars.sSearch) if request.vars.iSortingCols == '1': cols = ( None, None, None, db.t_services.f_hosts_id, db.t_services.f_proto, db.t_services.f_number, db.t_services.f_status, None, None, None, None, db.t_services.f_name, db.t_services.f_banner, ) orderby = cols[int(request.vars.iSortCol_0)] if request.vars.sSortDir_0 == 'asc': rows = db(q).select(orderby=orderby, limitby=(start, limit)) else: rows = db(q).select(orderby=~orderby, limitby=(start, limit)) else: rows = db(q).select(limitby=(start, limit)) nolimit = db(q).count() aaData = [] # datatable formatting is specific # gather all the vulndata and exploits into a big row # later we'll do a find(lambda: row: row.<db>.<field> == <value>) # to slice it into the bits we need. Maybe it'll be faster? #vulndata = db().select(db.t_vulndata.f_vulnid, db.t_vulndata.id, db.t_exploit_references.f_exploit_id, # left=db.t_exploit_references.on(db.t_vulndata.id==db.t_exploit_references.f_vulndata_id)) for r in rows: atxt = {} vulncount = 0 vulns = db( db.t_service_vulns.f_services_id == r.t_services.id).select( db.t_service_vulns.f_vulndata_id, cache=(cache.ram, 60)) vulnlist = [] explist = [] for vuln in vulns: vuln_rec = db.t_vulndata[vuln.f_vulndata_id] if vuln_rec.f_vulnid not in vulnlist: if settings.use_cvss: vulnlist.append( (vuln_rec.f_vulnid, vuln_rec.f_cvss_score)) else: vulnlist.append( (vuln_rec.f_vulnid, vuln_rec.f_severity)) exploits = db(db.t_exploit_references.f_vulndata_id == vuln.f_vulndata_id).select(cache=(cache.ram, 60)) if len(exploits) > 0: for expinfo in exploits: exp = db.t_exploits[expinfo.f_exploit_id] exp_link = A(exp.f_name, _href=URL('exploits', 'edit', extension='html', args=exp.id), _target='blank') explist.append( TR(TD(exp_link), TD(exp.f_title), TD(exp.f_source), TD(exp.f_rank))) q = r.t_services.t_service_info.select(cache=(cache.ram, 60)) if (len(q) > 0) or (len(explist) > 0) or (len(vulnlist) > 0): atxt['0'] = IMG(_src=URL(request.application, 'static', 'images/details_open.png')).xml() else: atxt['0'] = "" atxt['1'] = A("edit", _target="services_edit_%s" % (r.t_services.id), _href=URL('edit', args=[r.t_services.id], extension='html')).xml() if len(q) > 0: addl = [] for svcinfo in q: addl.append(TR(TD(svcinfo.f_name), TD(svcinfo.f_text))) atxt['2'] = TABLE(THEAD(TR(TH(T('Name')), TH(T('Text')))), TBODY(addl), _class="table table-condensed table-striped", _style="width:100%").xml() else: atxt['2'] = '' host_rec = db.t_hosts[r.t_services.f_hosts_id] atxt['3'] = host_a_maker(host_rec).xml(), atxt['4'] = r.t_services.f_proto # Append A tags around services with HTTP Ports if r.t_services.f_number in HTTP_PORTS and r.t_services.f_proto == "tcp" or r.t_services.f_name == "HTTP": atxt['5'] = A( r.t_services.f_number, _href=URL('default', 'redirect', extension='html', vars={ 'url': "http://%s:%s/" % (host_rec.f_ipaddr, r.t_services.f_number) }), _target="%s-tcp-%s" % (host_rec.f_ipaddr, r.t_services.f_number)).xml() elif r.t_services.f_number in HTTPS_PORTS and r.t_services.f_proto == "tcp" or r.t_services.f_name == "HTTPS": atxt['5'] = A( r.t_services.f_number, _href=URL('default', 'redirect', extension='html', vars={ 'url': "https://%s:%s/" % (host_rec.f_ipaddr, r.t_services.f_number) }), _target="%s-tcp-%s" % (host_rec.f_ipaddr, r.t_services.f_number)).xml() else: atxt['5'] = r.t_services.f_number atxt['6'] = r.t_services.f_status atxt['7'] = len(vulnlist) vulntxt = [] for vuln in vulnlist: color = severity_mapping(vuln[1])[2] vulntxt.append( A(vuln[0], _id="vuln", _target="vulninfo_by_vulnid_%s" % (vuln[0]), _href=URL('vulns', 'vulninfo_by_vulnid', args=[vuln[0]], extension='html'), _style="color:" + color).xml()) atxt['8'] = " :: ".join(vulntxt) if len(explist) > 0: atxt['9'] = "Yes (%d)" % (len(explist)) else: atxt['9'] = '' if len(explist) > 0: atxt['10'] = TABLE(THEAD( TR(TH(T('Name')), TH(T('Title')), TH(T('Source')), TH(T('Rank')))), TBODY(explist), _class="table table-condensed", _style="width:100%").xml() else: atxt['10'] = '' atxt['11'] = r.t_services.f_name atxt['12'] = r.t_services.f_banner atxt['DT_RowId'] = r.t_services.id aaData.append(atxt) result = { 'sEcho': request.vars.sEcho, 'iTotalRecords': db(db.t_services).count(), 'iTotalDisplayRecords': nolimit, 'aaData': aaData, } return result else: add = AddModal( db.t_services, 'Add', 'Add', 'Add Service', #fields=[ # 'f_proto', 'f_number', 'f_status', 'f_name', 'f_banner' #], cmd='servicetable.fnReloadAjax();') db.t_services.id.comment = add.create() return dict(add=add)
def report(): """ Genereate a HTML-report with fields from statistics, hosts, vulns, and summaries from the wiki """ statistics = db_statistics() adv_stats = adv_db_statistics() graphs = graphs_index() customer = settings.customer assessment = settings.assessment_typed start_date = settings.start_date or 'START DATE' end_date = settings.end_date or 'END DATE' # grab the filter type and value if provided or from the session if session.hostfilter is None: f_type = request.vars.f_type or None f_value = request.vars.f_value or None else: f_type = session.hostfilter[0] f_value = session.hostfilter[1] # this is a little hack to ensure a record is either blank or None # use it as "if variable not in notin:" notin = [ None, '' ] unknown_cpeid_counter = 0 hosts = [] vulnerabilities = {} # go through each host, adding the os, services and vulns accordingly query = create_hostfilter_query([(f_type, f_value), False]) for host_rec in db(query).select(): host = {} host['ipv4'] = host_rec.f_ipv4 host['asset_group'] = host_rec.f_asset_group if host_rec.f_ipv6: host['ipv6'] = host_rec.f_ipv6 if host_rec.f_macaddr: host['macaddr'] = host_rec.f_macaddr if host_rec.f_hostname: host['hostname'] = host_rec.f_hostname.decode('utf-8') if host_rec.f_netbios_name: host['netbios_name'] = host_rec.f_netbios_name.decode('utf-8') # build the os information using the highest certainty record highest = (0, None) for os_rec in db(db.t_host_os_refs.f_hosts_id == host_rec.id).select(): if os_rec.f_certainty > highest[0]: highest = (os_rec.f_certainty, os_rec) if highest[0] > 0: # add os element to the host record = highest[1] host['os']=record host['os']['certainty'] = str(highest[0]) if record.f_class not in notin: host['os']['class'] = record.f_class if record.f_family not in notin: host['os']['family'] = record.f_family # since some os records may not have a cpe id we'll mask them with # using their title, replacing spaces with underscores t_os_rec = db.t_os[record.f_os_id] if t_os_rec.f_cpename in notin: cpeid = t_os_rec.f_title.replace(' ', '_') else: cpeid = t_os_rec.f_cpename host['os']['id'] = cpeid # if the id isn't in os_records, add it # if 1: # os_rec = db.t_os[highest[1].f_os_id] # host['os']['id'] = cpeid # host['os']['title'] = os_rec.f_title # # if os_rec.f_vendor not in notin: # host['os']['vendor'] = os_rec.f_vendor # # if os_rec.f_product not in notin: # host['os']['product'] = os_rec.f_product # # if os_rec.f_version not in notin: # host['os']['version'] = os_rec.f_version # # if os_rec.f_update not in notin: # host['os']['update'] = os_rec.f_update # # if os_rec.f_edition not in notin: # host['os']['edition'] = os_rec.f_edition # # if os_rec.f_language not in notin: # host['os']['language'] = os_rec.f_language # snmp strings snmp_recs = db(db.t_snmp.f_hosts_id == host_rec.id).select() if len(snmp_recs) > 0: host['snmps'] = [] for record in snmp_recs: snmp = {} if record.f_community not in notin: snmp['community'] = record.f_community.decode('utf-8') snmp['version'] = record.f_version snmp['access'] = record.f_access host['snmps'].append(snmp) # netbios information netb_record = db(db.t_netbios.f_hosts_id == host_rec.id).select().first() or None if netb_record: host['netbios'] = {} if netb_record.f_type not in notin: host['netbios']['type'] = netb_record.f_type if netb_record.f_domain not in notin: host['netbios']['domain'] = netb_record.f_domain.decode('utf-8') if netb_record.f_lockout_limit not in notin: host['netbios']['lockout_limit'] = str(netb_record.f_lockout_limit) if netb_record.f_lockout_duration not in notin: host['netbios']['lockout_duration'] = str(netb_record.f_lockout_duration) if netb_record.f_advertised_names is not None: for name in netb_record.f_advertised_names: host['netbios']['advertised_name'] = name.decode('utf-8') # build the services and vulnerabilities host['services'] = [] for svc_rec in db(db.t_services.f_hosts_id == host_rec.id).select(): service = {} service['proto'] = svc_rec.f_proto service['number'] = int(svc_rec.f_number) if svc_rec.f_name not in notin: service['name'] = svc_rec.f_name.decode('utf-8') else: service['name'] = T('unknown') if svc_rec.f_banner not in notin: service['banner'] = svc_rec.f_banner.decode('utf-8') # service configuration records svc_info_recs = db(db.t_service_info.f_services_id == svc_rec.id).select() if len(svc_info_recs) > 0: service['configs'] = [] for info_rec in svc_info_recs: config = {} if info_rec.f_name not in notin: config['name'] = info_rec.f_name if info_rec.f_text not in notin: config['text'] = info_rec.f_text.decode('utf-8') service['configs'].append(config) # vulnerabilities svc_vuln_recs = db(db.t_service_vulns.f_services_id == svc_rec.id).select() if len(svc_vuln_recs) > 0: service['vulns'] = [] for vuln_rec in svc_vuln_recs: vuln = {} vuln['status'] = vuln_rec.f_status vuln['proof'] = vuln_rec.f_proof vulndata = db.t_vulndata[vuln_rec.f_vulndata_id] vuln['vulninfo'] = vulndata vuln['id'] = vulndata.f_vulnid vuln['title'] = vulndata.f_title vuln['severity'] = str(vulndata.f_severity) vuln['pci_sev'] = str(vulndata.f_pci_sev) vuln['cvss_score'] = str(vulndata.f_cvss_score) vuln['cvssmetrics'] = cvss_metrics(vulndata) vuln['description'] = vulndata.f_description vuln['solution'] = vulndata.f_solution # find vulnerability references and add them vuln_refs = db(db.t_vuln_references.f_vulndata_id == vulndata.id).select() if len(vuln_refs) > 0: vuln['refs'] = [] for ref_rec in vuln_refs: ref = {} record = db.t_vuln_refs[ref_rec.f_vuln_ref_id] ref['source'] = record.f_source ref['text'] = record.f_text.decode('utf-8') vuln['refs'].append(ref) # find vulnerability exploits and add them vuln_exploits = '' #db(db.t_vuln_references.f_vulndata_id == vulndata.id).select() if len(vuln_exploits) > 0: vuln['exploits'] = [] for ref_rec in vuln_refs: ref = {} record = db.t_vuln_refs[ref_rec.f_vuln_ref_id] ref['source'] = record.f_source ref['text'] = record.f_text.decode('utf-8') vuln['refs'].append(ref) if (int(vuln['severity'])>0): service['vulns'].append(vuln) vuln['hosts'] = [] vulnhost = {} vulnhost['ipv4'] = host['ipv4'] if 'hostname' in host: vulnhost['hostname'] = host['hostname'] else: vulnhost['hostname'] = host['ipv4'] vulnhost['svcproto'] = service['proto'] vulnhost['svcnumber'] = service['number'] vulnhost['status'] = vuln_rec.f_status vulnhost['proof'] = vuln_rec.f_proof vulnhost['url'] = '' if svc_rec.f_name not in notin: vulnhost['svcname'] = svc_rec.f_name.decode('utf-8') else: vulnhost['svcname'] = T('unknown') if svc_rec.f_banner not in notin: vulnhost['svcbanner'] = svc_rec.f_banner.decode('utf-8') id = str(vuln_rec.f_vulndata_id) if id not in vulnerabilities: vulnerabilities[id] = vuln vulnerabilities[id]['hosts'].append(vulnhost) if len(service['vulns']) is 0: del service['vulns'] host['services'].append(service) # accounts #accounts = db(db.t_accounts.f_services_id == svc_rec.id).select() # if len(accounts) > 0: # host['accounts'] = [] # # for acct_rec in accounts: # account = {} # # if acct_rec.f_username not in notin: # account['username'] = acct_rec.f_username.decode('utf-8') # # if acct_rec.f_fullname not in notin: # account['fullname'] = acct_rec.f_fullname.decode('utf-8') # # if acct_rec.f_password not in notin: # account['password'] = acct_rec.f_password.decode('utf-8') # # if acct_rec.f_hash1 not in notin: # account['hash1'] = acct_rec.f_hash1 # # if acct_rec.f_hash1_type not in notin: # account['hash1_type'] = acct_rec.f_hash1_type # # if acct_rec.f_hash2 not in notin: # account['hash2'] = acct_rec.f_hash2 # # if acct_rec.f_hash2_type not in notin: # account['hash2_type'] = acct_rec.f_hash2_type # # if acct_rec.f_uid not in notin: # account['uid'] = acct_rec.f_uid # # if acct_rec.f_gid not in notin: # account['gid'] = acct_rec.f_gid # # if acct_rec.f_level not in notin: # account['level'] = acct_rec.f_level # # if acct_rec.f_domain not in notin: # account['domain'] = acct_rec.f_domain.decode('utf-8') # # if acct_rec.f_description not in notin: # account['description'] = acct_rec.f_description.decode('utf-8') # host['accounts'].append(account) hosts.append(host) #response.files.append(URL(request.application,'static','js/jquery.sparkline.js')) #get JSON from host.list and use mockjax ext = request.extension request.extension = 'json' hostlist = list() #Not an empty list request.extension = ext #remove the engineer field from the customers report hostlist['aaData'][-1]['10']=None import re hostlist = re.sub("href=\"[^>]*>([^<]*)","href=\"#\\1\">\\1", str(hostlist)) listjson=hostlist.replace('\"','\\\"').replace('\'','\"').replace('L, ',', ').replace('None','null') vulnlst=sorted(vulnerabilities, key=lambda x: int(vulnerabilities[x]['severity']), reverse=True) return dict( vulnlst=vulnlst, vulnerabilities=vulnerabilities, statistics=statistics, adv_stats=adv_stats, graphs=graphs, hosts=hosts, hostfilter=session.hostfilter, listjson=listjson)
def vulninfo_by_vulnid(): """ Returns the vulnerablilty details """ if request.args(0) is None: redirect(URL('default', 'error', vars={'msg': T('No Vulnerability ID sent')})) record = db(db.t_vulndata.f_vulnid==request.args(0)).select().first() if record is not None: # grab vuln references and format the table response.title = "%s :: Vulnerability Popup :: %s" % (settings.title, record.f_vulnid) #cvss_metrics = "AV:%s/AC:%s/Au:%s/C:%s/I:%s/A:%s" % (record.f_cvss_av, # record.f_cvss_ac, # record.f_cvss_au, # record.f_cvss_c, # record.f_cvss_i, # record.f_cvss_a) vulninfo = record cvssmetrics = cvss_metrics(record) refs = LOAD(request.controller, 'vuln_refs_by_vulnid', args=[record.id], ajax=True) exploits = LOAD(request.controller, 'vuln_exploits_by_vulnid', args=[record.id], ajax=True) # TODO: Add hosts with vulnerability -- include service info (proto/port) and # ability to delete vuln from service query = db.t_service_vulns.f_vulndata_id == record.id svc_vulns = db(query).select(db.t_service_vulns.f_services_id, db.t_service_vulns.f_proof, db.t_service_vulns.f_status, db.t_service_vulns.id, distinct=True) hosts_tr = [] query = (db.t_hosts.id > 0) query = create_hostfilter_query(session.hostfilter, query, 't_services') hosts_dict = db(query).select(db.t_hosts.id, cache=(cache.ram, 30)).as_dict() hostlist = map(lambda x: x['id'], hosts_dict.itervalues()) for svc_vuln in svc_vulns: svc = db.t_services[svc_vuln.f_services_id] if svc is None: logger.error("t_servics_vuln #%s does not link to a t_services.id!" % (svc_vuln.id)) continue if svc.f_hosts_id not in hostlist: continue host_rec = db.t_hosts[svc.f_hosts_id] hosts_tr.append(TR(TD(SPAN(I(_class="icon-trash"), _name="host_del", _id=svc_vuln.id)), TD(A(IMG(_src=URL(request.application, 'static/images', 'terminal.png'), _width="20", _height="20", _style="float:left"), " ", _href="#", _onclick="launchterm('%s')" % (host_rec.id)), host_a_maker(host_rec)), TD("%s/%s" % (svc.f_proto, svc.f_number)), TD(MARKMIN(svc_vuln.f_proof)), TD(svc_vuln.f_status), _id=svc_vuln.id ) ) if len(hosts_tr) > 0: hosts = TABLE(THEAD(TR(TH(T('Del'), _width="5%"), TH(T('Host Information')), TH(T('Port')), TH(T('Proof')), TH(T('Status')), ) ), TBODY(hosts_tr), _id="vulntable", _class="datatable", _width="100%") else: hosts = None else: response.title = "%s :: Invalid Vulnerability ID" return dict(vulninfo={}, refs={}, exploits={}, hosts={}) # vuln form data vuln=crud.read(db.t_vulndata, record) #returns read-only for for t_vulndata vuln.attributes['_id'] = "vuln_record" return dict(vuln=vuln, vulninfo=vulninfo, cvssmetrics=cvssmetrics, refs=refs, exploits=exploits, hosts=hosts)
def customer_xml(): """ Generates an XML file suitable for Customer usage """ from lxml import etree # grab the filter type and value if provided or from the session if session.hostfilter is None: f_type = request.vars.f_type or None f_value = request.vars.f_value or None else: f_type = session.hostfilter[0] f_value = session.hostfilter[1] location_attribute = '{%s}noNameSpaceSchemaLocation' % "http://www.w3.org/2001/XMLSchema-instance" kvasir_results_xml = etree.Element('KvasirResults', attrib={ location_attribute: 'kvasir.xsd', }) summary_xml = etree.SubElement(kvasir_results_xml, 'summary') customer = etree.SubElement(summary_xml, 'customer') customer.text = settings.customer or 'CUSTOMER NAME' assessment = etree.SubElement(summary_xml, 'assessment') assessment.set('type', settings.assessment_type) start_date = etree.SubElement(assessment, 'start-date') start_date.text = settings.start_date or 'START DATE' end_date = etree.SubElement(assessment, 'end-date') end_date.text = settings.end_date or 'END DATE' hosts_xml = etree.SubElement(kvasir_results_xml, 'hosts') os_xml = etree.SubElement(kvasir_results_xml, 'os_records') vulns_xml = etree.SubElement(kvasir_results_xml, 'vulns') # this is a little hack to ensure a record is either blank or None # use it as "if variable not in notin:" notin = [ None, '' ] unknown_cpeid_counter = 0 # go through each host, adding the os, services and vulns accordingly query = create_hostfilter_query([(f_type, f_value), False]) for host_rec in db(query).select(): host_xml = etree.SubElement(hosts_xml, 'host') host_xml.set('ipv4', host_rec.f_ipv4) host_xml.set('assetgroup', host_rec.f_asset_group) if host_rec.f_ipv6: host_xml.set('ipv6', host_rec.f_ipv6) if host_rec.f_macaddr: host_xml.set('macaddr', host_rec.f_macaddr) if host_rec.f_hostname: host_xml.set('hostname', host_rec.f_hostname.decode('utf-8')) if host_rec.f_netbios_name: host_xml.set('netbios', host_rec.f_netbios_name.decode('utf-8')) # build the os information using the highest certainty record highest = (0, None) for os_rec in db(db.t_host_os_refs.f_hosts_id == host_rec.id).select(): if os_rec.f_certainty > highest[0]: highest = (os_rec.f_certainty, os_rec) if highest[0] > 0: # add os element to the host record = highest[1] os = etree.SubElement(host_xml, 'os') os.set('certainty', str(highest[0])) if record.f_class not in notin: os.set('class', record.f_class) if record.f_family not in notin: os.set('family', record.f_family) # since some os records may not have a cpe id we'll mask them with # using their title, replacing spaces with underscores t_os_rec = db.t_os[record.f_os_id] if t_os_rec.f_cpename in notin: cpeid = t_os_rec.f_title.replace(' ', '_') else: cpeid = t_os_rec.f_cpename os.set('id', cpeid) # if the id isn't in os_records, add it if len(os_xml.findall('.//os[@id="%s"]' % (os.get('id', None)))) < 1: os_info_xml = etree.SubElement(os_xml, 'os') os_rec = db.t_os[highest[1].f_os_id] os_info_xml.set('id', cpeid) os_info_xml.set('title', os_rec.f_title) if os_rec.f_vendor not in notin: vendor = etree.SubElement(os_info_xml, 'vendor') vendor.text = os_rec.f_vendor if os_rec.f_product not in notin: product = etree.SubElement(os_info_xml, 'product') product.text = os_rec.f_product if os_rec.f_version not in notin: version = etree.SubElement(os_info_xml, 'version') version.text = os_rec.f_version if os_rec.f_update not in notin: update = etree.SubElement(os_info_xml, 'update') update.text = os_rec.f_update if os_rec.f_edition not in notin: edition = etree.SubElement(os_info_xml, 'edition') edition.text = os_rec.f_edition if os_rec.f_language not in notin: language = etree.SubElement(os_info_xml, 'language') language.text = os_rec.f_language # snmp strings snmp_recs = db(db.t_snmp.f_hosts_id == host_rec.id).select() if len(snmp_recs) > 0: snmp_top_xml = etree.SubElement(hosts_xml, 'snmps') for record in snmp_recs: snmp_xml = etree.SubElement(snmp_top_xml, 'snmp') if record.f_community not in notin: snmp_xml.set('community', record.f_community.decode('utf-8')) snmp_xml.set('version', record.f_version) snmp_xml.set('access', record.f_access) # netbios information netb_record = db(db.t_netbios.f_hosts_id == host_rec.id).select().first() or None if netb_record: netbios_xml = etree.SubElement(hosts_xml, 'netbios') if netb_record.f_type not in notin: netbios_xml.set('type', netb_record.f_type) if netb_record.f_domain not in notin: netbios_xml.set('domain', netb_record.f_domain.decode('utf-8')) if netb_record.f_lockout_limit not in notin: netbios_xml.set('lockout_limit', str(netb_record.f_lockout_limit)) if netb_record.f_lockout_duration not in notin: netbios_xml.set('lockout_duration', str(netb_record.f_lockout_duration)) if netb_record.f_advertised_names is not None: adv_names_xml = etree.SubElement(netbios_xml, 'advertised_names') for name in netb_record.f_advertised_names: name_xml = etree.SubElement(adv_names_xml, 'name') name.text = name.decode('utf-8') # build the services and vulnerabilities services_xml = etree.SubElement(host_xml, 'services') for svc_rec in db(db.t_services.f_hosts_id == host_rec.id).select(): service_xml = etree.SubElement(services_xml, 'service') service_xml.set('proto', svc_rec.f_proto) service_xml.set('number', svc_rec.f_number) if svc_rec.f_name not in notin: name = etree.SubElement(service_xml, 'name') name.text = svc_rec.f_name.decode('utf-8') if svc_rec.f_banner not in notin: banner = etree.SubElement(service_xml, 'banner') banner.text = svc_rec.f_banner.decode('utf-8') # service configuration records svc_info_recs = db(db.t_service_info.f_services_id == svc_rec.id).select() if len(svc_info_recs) > 0: config_xml = etree.SubElement(service_xml, 'configuration') for info_rec in svc_info_recs: rec_xml = etree.SubElement(config_xml, 'config') if info_rec.f_name not in notin: rec_xml.set('name', info_rec.f_name) if info_rec.f_text not in notin: rec_xml.text = info_rec.f_text.decode('utf-8') # vulnerabilities svc_vuln_recs = db(db.t_service_vulns.f_services_id == svc_rec.id).select() if len(svc_vuln_recs) > 0: svc_vulns_xml = etree.SubElement(service_xml, 'vulns') for vuln_rec in svc_vuln_recs: vuln_xml = etree.SubElement(svc_vulns_xml, 'vuln') vuln_xml.set('status', vuln_rec.f_status) vuln_xml.set('id', db.t_vulndata[vuln_rec.f_vulndata_id].f_vulnid) proof = etree.SubElement(vuln_xml, 'proof') proof.text = etree.CDATA(unicode(MARKMIN(vuln_rec.f_proof).xml(), 'utf-8')) # search for the nexpose id in vulns_xml if len(vuln_xml.findall('.//vuln[@id="%s"]' % vuln_xml.get('id', None))) < 1: new_vuln_xml = etree.SubElement(vulns_xml, 'vuln') vulndata = db.t_vulndata[vuln_rec.f_vulndata_id] new_vuln_xml.set('id', vulndata.f_vulnid) new_vuln_xml.set('title', vulndata.f_title) new_vuln_xml.set('severity', str(vulndata.f_severity)) new_vuln_xml.set('pci_sev', str(vulndata.f_pci_sev)) new_vuln_xml.set('cvss_score', str(vulndata.f_cvss_score)) new_vuln_xml.set('cvss_metric', cvss_metrics(vulndata)) description = etree.SubElement(new_vuln_xml, 'description') description.text = etree.CDATA(unicode(MARKMIN(vulndata.f_description).xml(), 'utf-8')) solution = etree.SubElement(new_vuln_xml, 'solution') solution.text = etree.CDATA(unicode(MARKMIN(vulndata.f_solution).xml(), 'utf-8')) # find vulnerability references and add them vuln_refs = db(db.t_vuln_references.f_vulndata_id == vulndata.id).select() if len(vuln_refs) > 0: refs_xml = etree.SubElement(new_vuln_xml, 'references') for ref_rec in vuln_refs: record = db.t_vuln_refs[ref_rec.f_vuln_ref_id] ref_xml = etree.SubElement(refs_xml, 'reference') ref_xml.set('source', record.f_source) ref_xml.text = record.f_text.decode('utf-8') # accounts accounts = db(db.t_accounts.f_services_id == svc_rec.id).select() if len(accounts) > 0: accounts_xml = etree.SubElement(service_xml, 'accounts') for acct_rec in accounts: acct_xml = etree.SubElement(accounts_xml, 'account') if acct_rec.f_username not in notin: elem = etree.SubElement(acct_xml, 'username') elem.text = acct_rec.f_username.decode('utf-8') if acct_rec.f_fullname not in notin: elem = etree.SubElement(acct_xml, 'fullname') elem.text = acct_rec.f_fullname.decode('utf-8') if acct_rec.f_password not in notin: elem = etree.SubElement(acct_xml, 'password') elem.text = acct_rec.f_password.decode('utf-8') if acct_rec.f_hash1 not in notin: elem = etree.SubElement(acct_xml, 'hash1') elem.text = acct_rec.f_hash1 if acct_rec.f_hash1_type not in notin: elem = etree.SubElement(acct_xml, 'hash1_type') elem.text = acct_rec.f_hash1_type if acct_rec.f_hash2 not in notin: elem = etree.SubElement(acct_xml, 'hash2') elem.text = acct_rec.f_hash2 if acct_rec.f_hash2_type not in notin: elem = etree.SubElement(acct_xml, 'hash2_type') elem.text = acct_rec.f_hash2_type if acct_rec.f_uid not in notin: elem = etree.SubElement(acct_xml, 'uid') elem.text = acct_rec.f_uid if acct_rec.f_gid not in notin: elem = etree.SubElement(acct_xml, 'gid') elem.text = acct_rec.f_gid if acct_rec.f_level not in notin: elem = etree.SubElement(acct_xml, 'level') elem.text = acct_rec.f_level if acct_rec.f_domain not in notin: elem = etree.SubElement(acct_xml, 'domain') elem.text = acct_rec.f_domain.decode('utf-8') if acct_rec.f_description not in notin: elem = etree.SubElement(acct_xml, 'description') elem.text = acct_rec.f_description.decode('utf-8') result = etree.tostring(kvasir_results_xml, pretty_print=True, encoding=unicode) return result
def list(): response.title = "%s :: Host Listing" % (settings.title) # hostfilter is a session variable that can be # None -- no host filtering # (userid, <x>) - limit on user id # (assetgroup, <x>) - limit on asset group # (range, <x>) - limit on subnet (eg: 192.168) hostfilter = session.hostfilter if hostfilter is None: # if no filter is set then we blank it out if session.hostfilter is None: session.hostfilter = [(None, None), False] if request.extension == 'json': # from datetime import datetime, timedelta # host_start = datetime.now() tot_vuln = 0 tot_hosts = 0 """ # load all the vulndata from service_vulns into a dictionary # so we only have to query the memory variables instead of # the database each time. We need to collect: # svc_vulndata[f_service_id] = (f_vulnid, f_severity, f_cvss_score) svc_vulndata = {} rows = s_service_vuln_data.select( db.t_vulndata.id, db.t_vulndata.f_vulnid, db.t_vulndata.f_severity, db.t_vulndata.f_cvss_score, cache=(cache.ram, 60)) for r in rows: #exploitcount = db(db.t_exploit_references.f_vulndata_id == r.id).count() svc_vulndata[r.id] = ( r.f_vulnid, r.f_severity, r.f_cvss_score, r.t_exploit_references.count()) """ # build the query variable.. first all hosts then check # if a hostfilter is applied q = (db.t_hosts.id > 0) q = create_hostfilter_query(session.hostfilter, q) aaData = [] rows = db(q).select(db.t_hosts.ALL, db.t_host_os_refs.f_certainty, db.t_os.f_title, db.auth_user.username, left=(db.t_host_os_refs.on(db.t_hosts.id==db.t_host_os_refs.f_hosts_id), db.t_os.on(db.t_os.id==db.t_host_os_refs.f_os_id), db.auth_user.on(db.t_hosts.f_engineer==db.auth_user.id)), orderby=db.t_hosts.id|~db.t_host_os_refs.f_certainty) # datatable formatting is specific, crud results are not seen = set() for r in rows: if r.t_hosts.id not in seen and not seen.add(r.t_hosts.id): # kludge way to select only rows per host with the best OS-guess spanflags = [] if r.t_hosts.f_confirmed: confirmed = 'hosts_select_confirmed' spanflags.append('<span class="badge"><i class="icon-check"></i></span>') else: confirmed = 'hosts_select_unconfirmed' if r.t_hosts.f_accessed: spanflags.append('<span class="badge badge-success"><i class="icon-heart"></i></span>') if r.t_hosts.f_followup: spanflags.append('<span class="badge badge-important"><i class="icon-flag"></i></span>') confirmed = '<div class="%s">%s</div>' % (confirmed, " ".join(spanflags)) if r.t_hosts.f_ipv4: ipv4 = A(r.t_hosts.f_ipv4, _id='ipv4', _href=URL('detail', extension='html', args=[r.t_hosts.id]), _target="host_detail_%s" % (r.t_hosts.id)).xml() else: ipv4 = "" if r.t_hosts.f_ipv6: ipv6 = A(r.t_hosts.f_ipv6, _id='ipv6', _href=URL('detail', extension='html', args=[r.t_hosts.id]), _target="host_detail_%s" % (r.t_hosts.id)).xml() else: ipv6 = "" if r.t_os.f_title is None: os = "Unknown" else: os = r.t_os.f_title atxt = { '0': confirmed, '1': ipv4, '2': ipv6, '3': r.t_hosts.f_service_count, '4': r.t_hosts.f_vuln_count, '5': "<span class=\"severity_sparkline\" values=\"%s\"></span>" % (r.t_hosts.f_vuln_graph), '6': r.t_hosts.f_exploit_count, '7': r.t_hosts.f_hostname, '8': r.t_hosts.f_netbios_name, '9': os, '10': r.auth_user.username, '11': r.t_hosts.f_asset_group, 'DT_RowId': "%s" % (r.t_hosts.id), } aaData.append(atxt) #print("Total time in vuln processing: %s seconds" % (tot_vuln)) #print("Host record processed in %s seconds" % (timedelta.total_seconds(datetime.now() - row_start))) tot_hosts += 1 result = { 'sEcho': request.vars.sEcho, 'iTotalRecords': len(aaData), 'iTotalDisplayRecords': len(aaData), 'aaData': aaData, } #print("Host_select processed %s hosts in %s seconds" % (tot_hosts, timedelta.total_seconds(datetime.now() - host_start))) return result else: add_hosts = AddModal( db.t_hosts, 'Add Host', 'Add Host', 'Add Host', fields = [ 'f_ipv4', 'f_ipv6', 'f_hostname', 'f_netbios_name', 'f_macaddr', 'f_engineer', 'f_asset_group', ], cmd = 'hosttable.fnReloadAjax();' ) db.t_hosts.id.comment = add_hosts.create() response.files.append(URL(request.application,'static','js/jquery.sparkline.js')) return dict(hostfilter=session.hostfilter, add_hosts=add_hosts)
def list(): response.title = "%s :: Accounts" % (settings.title) if request.extension == 'json': query = (db.t_accounts.id > 0) & (db.t_accounts.f_services_id == db.t_services.id) query = create_hostfilter_query(session.hostfilter, query, 't_services') if request.vars.hash_type is not None: query &= ((db.t_accounts.f_hash1_type == request.vars.hash_type) | (db.t_accounts.f_hash2_type == request.vars.hash_type)) if request.vars.has_key('iDisplayStart'): start = int(request.vars.iDisplayStart) else: start = 0 if request.vars.has_key('iDisplayLength'): if request.vars.iDisplayLength == '-1': limit = db(query).count() else: limit = start + int(request.vars.iDisplayLength) else: limit = int(auth.user.f_show_size) srch_data = request.vars.get('sSearch') if srch_data: # sSearch global search box # parse the search into fields (port:num proto:tcp etc) srch_vals = [ ["port", db.t_services.f_number], ["proto", db.t_services.f_proto], ["user", db.t_accounts.f_username], ["name", db.t_accounts.f_fullname], ["domain", db.t_accounts.f_domain], ["hash", db.t_accounts.f_hash1], ["hash1", db.t_accounts.f_hash1], ["hash2", db.t_accounts.f_hash2], ["htype", db.t_accounts.f_hash1_type], ["uid", db.t_accounts.f_uid], ["gid", db.t_accounts.f_gid], ["level", db.t_accounts.f_level], ["source", db.t_accounts.f_source], ["desc", db.t_accounts.f_description], ["msg", db.t_accounts.f_message], ["ip", db.t_hosts.f_ipaddr], ["hostname", db.t_hosts.f_hostname], ] parsed = False for val in srch_vals: srch_str = "%s:(?P<f>\w+)" % val[0] srch_res = re.findall(srch_str, srch_data) for res in srch_res: parsed = True if val[0] in ['source', 'desc', 'hostname']: query &= (val[1].upper().contains(res.upper())) else: query &= (val[1].upper() == res.upper()) if not parsed: query &= db.t_accounts.f_username.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_password.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_fullname.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_domain.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_hash1.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_hash2.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_source.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_message.like("%%%s%%" % request.vars.sSearch) | \ db.t_accounts.f_description.like("%%%s%%" % request.vars.sSearch) | \ db.t_hosts.f_ipaddr.like("%%%s%%" % request.vars.sSearch) | \ db.t_hosts.f_hostname.like("%%%s%%" % request.vars.sSearch) #total_count = db.t_vulndata.id.count() if request.vars.iSortingCols == '1': # sorting by a column - this is a little trippy because tuples start at 0 # and datatables starts at 1 so we have to subtract 1 from iSortCol_0 cols = (db.t_accounts.f_compromised, db.t_hosts.f_ipaddr, db.t_services.f_number, db.t_accounts.f_username, db.t_accounts.f_fullname, db.t_accounts.f_domain, db.t_accounts.f_password, db.t_accounts.f_hash1_type, db.t_accounts.f_hash1, db.t_accounts.f_hash2_type, db.t_accounts.f_hash2, db.t_accounts.f_uid, db.t_accounts.f_gid, db.t_accounts.f_level, db.t_accounts.f_active, db.t_accounts.f_lockout, db.t_accounts.f_source, db.t_accounts.f_message, db.t_accounts.f_description) orderby = cols[int(request.vars.iSortCol_0)] if request.vars.sSortDir_0 == 'asc': rows = db(query).select(db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, orderby=orderby, limitby=(start, limit), cache=(cache.with_prefix( cache.ram, "accounts_list"), 180)) else: rows = db(query).select(db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, orderby=~orderby, limitby=(start, limit), cache=(cache.with_prefix( cache.ram, "accounts_list"), 180)) else: rows = db(query).select(db.t_accounts.ALL, db.t_hosts.id, db.t_hosts.f_ipaddr, db.t_hosts.f_hostname, db.t_services.f_proto, db.t_services.f_number, limitby=(start, limit), cache=(cache.with_prefix( cache.ram, "accounts_list"), 180)) #rows=db(q).select( # db.t_accounts.ALL, # db.t_hosts.id, # db.t_hosts.f_ipaddr, # db.t_hosts.f_hostname, # db.t_services.f_proto, # db.t_services.f_number, # #cache=(cache.ram,60) #) aaData = [] # datatable formatting is specific for r in rows: atxt = {} if r.t_accounts.f_compromised == True: atxt[ '0'] = '<div class="acct_compromised" name="row_id" id="%s"><span class="icon-check"></span></div>' % r.t_accounts.id else: atxt[ '0'] = '<div class="acct_uncompromised" name="row_id" id="%s"/>' % r.t_accounts.id #svc = db.t_services[r.f_services_id] atxt['1'] = host_a_maker(r.t_hosts).xml() atxt['2'] = "%s/%s" % (r.t_services.f_proto, r.t_services.f_number) atxt['3'] = DIV(A(I(_class="icon-pencil", _style="display: inline-block;"), _target="accounts_update_%s" % (r.t_accounts.id), \ _href=URL('edit.html', args=r.t_accounts.id), \ ), A("%s" % (r.t_accounts.f_username), \ _target="_blank", _id="username", \ _href=URL("by_username", vars={'username':r.t_accounts.f_username}, extension="html"), \ ) ).xml() atxt['4'] = r.t_accounts.f_fullname atxt['5'] = r.t_accounts.f_domain atxt['6'] = r.t_accounts.f_password atxt['7'] = r.t_accounts.f_hash1_type atxt['8'] = r.t_accounts.f_hash1 atxt['9'] = r.t_accounts.f_hash2_type atxt['10'] = r.t_accounts.f_hash2 atxt['11'] = r.t_accounts.f_uid atxt['12'] = r.t_accounts.f_gid atxt['13'] = r.t_accounts.f_level atxt['14'] = r.t_accounts.f_active atxt['15'] = r.t_accounts.f_source atxt['16'] = r.t_accounts.f_message atxt['17'] = r.t_accounts.f_description atxt['DT_RowId'] = str(r.t_accounts.id) aaData.append(atxt) result = { 'sEcho': request.vars.sEcho, 'iTotalDisplayRecords': db(query).count(), 'iTotalRecords': db(db.t_accounts).count(), 'aaData': aaData, 'query': db._lastsql, } return result rows = db(db.t_accounts).select(db.t_accounts.f_hash1_type, groupby=db.t_accounts.f_hash1_type, cache=(cache.ram, 60)) hash_types = [] for r in rows: #if r.f_hash2_type is not None: # hash_types.append("%s/%s" % (r.f_hash1_type, r.f_hash2_type)) #else: hash_types.append(r.f_hash1_type) form = TABLE(THEAD( TR( TH(T('C'), _width="1%"), TH(T('Host')), TH(T('Port')), TH(T('Username')), TH(T('Fullname')), TH(T('Domain')), TH(T('Password')), TH(T('Hash 1 Type')), TH(T('Hash 1')), TH(T('Hash 2 Type')), TH(T('Hash 2')), TH(T('UID')), TH(T('GID')), TH(T('Level')), TH(T('Active')), TH(T('Source')), TH(T('Message')), TH(T('Description')), )), _class="datatable", _id="accounttable", _style="width:100%") add = AddModal( db.t_accounts, 'Add', 'Add', 'Add Account', #fields=[], cmd='accounttable.fnReloadAjax();') services = db(db.t_services.f_hosts_id > 0).select(cache=(cache.ram, 30)) svc_set = [] for svc in services: svc_set.append([ svc.id, "%s :: %s/%s" % (host_title_maker( db.t_hosts[svc.f_hosts_id]), svc.f_proto, svc.f_number) ]) db.t_accounts.f_services_id.requires = IS_IN_SET(svc_set) db.t_accounts.id.comment = add.create() return dict(form=form, hash_types=hash_types, add=add)
def report(): """ Genereate a HTML-report with fields from statistics, hosts, vulns, and summaries from the wiki """ statistics = db_statistics() adv_stats = adv_db_statistics() graphs = graphs_index() customer = settings.customer assessment = settings.assessment_typed start_date = settings.start_date or 'START DATE' end_date = settings.end_date or 'END DATE' # grab the filter type and value if provided or from the session if session.hostfilter is None: f_type = request.vars.f_type or None f_value = request.vars.f_value or None else: f_type = session.hostfilter[0] f_value = session.hostfilter[1] # this is a little hack to ensure a record is either blank or None # use it as "if variable not in notin:" notin = [None, ''] unknown_cpeid_counter = 0 hosts = [] vulnerabilities = {} # go through each host, adding the os, services and vulns accordingly query = create_hostfilter_query([(f_type, f_value), False]) for host_rec in db(query).select(): host = {} host['ipv4'] = host_rec.f_ipv4 host['asset_group'] = host_rec.f_asset_group if host_rec.f_ipv6: host['ipv6'] = host_rec.f_ipv6 if host_rec.f_macaddr: host['macaddr'] = host_rec.f_macaddr if host_rec.f_hostname: host['hostname'] = host_rec.f_hostname.decode('utf-8') if host_rec.f_netbios_name: host['netbios_name'] = host_rec.f_netbios_name.decode('utf-8') # build the os information using the highest certainty record highest = (0, None) for os_rec in db(db.t_host_os_refs.f_hosts_id == host_rec.id).select(): if os_rec.f_certainty > highest[0]: highest = (os_rec.f_certainty, os_rec) if highest[0] > 0: # add os element to the host record = highest[1] host['os'] = record host['os']['certainty'] = str(highest[0]) if record.f_class not in notin: host['os']['class'] = record.f_class if record.f_family not in notin: host['os']['family'] = record.f_family # since some os records may not have a cpe id we'll mask them with # using their title, replacing spaces with underscores t_os_rec = db.t_os[record.f_os_id] if t_os_rec.f_cpename in notin: cpeid = t_os_rec.f_title.replace(' ', '_') else: cpeid = t_os_rec.f_cpename host['os']['id'] = cpeid # if the id isn't in os_records, add it # if 1: # os_rec = db.t_os[highest[1].f_os_id] # host['os']['id'] = cpeid # host['os']['title'] = os_rec.f_title # # if os_rec.f_vendor not in notin: # host['os']['vendor'] = os_rec.f_vendor # # if os_rec.f_product not in notin: # host['os']['product'] = os_rec.f_product # # if os_rec.f_version not in notin: # host['os']['version'] = os_rec.f_version # # if os_rec.f_update not in notin: # host['os']['update'] = os_rec.f_update # # if os_rec.f_edition not in notin: # host['os']['edition'] = os_rec.f_edition # # if os_rec.f_language not in notin: # host['os']['language'] = os_rec.f_language # snmp strings snmp_recs = db(db.t_snmp.f_hosts_id == host_rec.id).select() if len(snmp_recs) > 0: host['snmps'] = [] for record in snmp_recs: snmp = {} if record.f_community not in notin: snmp['community'] = record.f_community.decode('utf-8') snmp['version'] = record.f_version snmp['access'] = record.f_access host['snmps'].append(snmp) # netbios information netb_record = db( db.t_netbios.f_hosts_id == host_rec.id).select().first() or None if netb_record: host['netbios'] = {} if netb_record.f_type not in notin: host['netbios']['type'] = netb_record.f_type if netb_record.f_domain not in notin: host['netbios']['domain'] = netb_record.f_domain.decode( 'utf-8') if netb_record.f_lockout_limit not in notin: host['netbios']['lockout_limit'] = str( netb_record.f_lockout_limit) if netb_record.f_lockout_duration not in notin: host['netbios']['lockout_duration'] = str( netb_record.f_lockout_duration) if netb_record.f_advertised_names is not None: for name in netb_record.f_advertised_names: host['netbios']['advertised_name'] = name.decode('utf-8') # build the services and vulnerabilities host['services'] = [] for svc_rec in db(db.t_services.f_hosts_id == host_rec.id).select(): service = {} service['proto'] = svc_rec.f_proto service['number'] = int(svc_rec.f_number) if svc_rec.f_name not in notin: service['name'] = svc_rec.f_name.decode('utf-8') else: service['name'] = T('unknown') if svc_rec.f_banner not in notin: service['banner'] = svc_rec.f_banner.decode('utf-8') # service configuration records svc_info_recs = db( db.t_service_info.f_services_id == svc_rec.id).select() if len(svc_info_recs) > 0: service['configs'] = [] for info_rec in svc_info_recs: config = {} if info_rec.f_name not in notin: config['name'] = info_rec.f_name if info_rec.f_text not in notin: config['text'] = info_rec.f_text.decode('utf-8') service['configs'].append(config) # vulnerabilities svc_vuln_recs = db( db.t_service_vulns.f_services_id == svc_rec.id).select() if len(svc_vuln_recs) > 0: service['vulns'] = [] for vuln_rec in svc_vuln_recs: vuln = {} vuln['status'] = vuln_rec.f_status vuln['proof'] = vuln_rec.f_proof vulndata = db.t_vulndata[vuln_rec.f_vulndata_id] vuln['vulninfo'] = vulndata vuln['id'] = vulndata.f_vulnid vuln['title'] = vulndata.f_title vuln['severity'] = str(vulndata.f_severity) vuln['pci_sev'] = str(vulndata.f_pci_sev) vuln['cvss_score'] = str(vulndata.f_cvss_score) vuln['cvssmetrics'] = cvss_metrics(vulndata) vuln['description'] = vulndata.f_description vuln['solution'] = vulndata.f_solution # find vulnerability references and add them vuln_refs = db(db.t_vuln_references.f_vulndata_id == vulndata.id).select() if len(vuln_refs) > 0: vuln['refs'] = [] for ref_rec in vuln_refs: ref = {} record = db.t_vuln_refs[ref_rec.f_vuln_ref_id] ref['source'] = record.f_source ref['text'] = record.f_text.decode('utf-8') vuln['refs'].append(ref) # find vulnerability exploits and add them vuln_exploits = '' #db(db.t_vuln_references.f_vulndata_id == vulndata.id).select() if len(vuln_exploits) > 0: vuln['exploits'] = [] for ref_rec in vuln_refs: ref = {} record = db.t_vuln_refs[ref_rec.f_vuln_ref_id] ref['source'] = record.f_source ref['text'] = record.f_text.decode('utf-8') vuln['refs'].append(ref) if (int(vuln['severity']) > 0): service['vulns'].append(vuln) vuln['hosts'] = [] vulnhost = {} vulnhost['ipv4'] = host['ipv4'] if 'hostname' in host: vulnhost['hostname'] = host['hostname'] else: vulnhost['hostname'] = host['ipv4'] vulnhost['svcproto'] = service['proto'] vulnhost['svcnumber'] = service['number'] vulnhost['status'] = vuln_rec.f_status vulnhost['proof'] = vuln_rec.f_proof vulnhost['url'] = '' if svc_rec.f_name not in notin: vulnhost['svcname'] = svc_rec.f_name.decode( 'utf-8') else: vulnhost['svcname'] = T('unknown') if svc_rec.f_banner not in notin: vulnhost['svcbanner'] = svc_rec.f_banner.decode( 'utf-8') id = str(vuln_rec.f_vulndata_id) if id not in vulnerabilities: vulnerabilities[id] = vuln vulnerabilities[id]['hosts'].append(vulnhost) if len(service['vulns']) is 0: del service['vulns'] host['services'].append(service) # accounts #accounts = db(db.t_accounts.f_services_id == svc_rec.id).select() # if len(accounts) > 0: # host['accounts'] = [] # # for acct_rec in accounts: # account = {} # # if acct_rec.f_username not in notin: # account['username'] = acct_rec.f_username.decode('utf-8') # # if acct_rec.f_fullname not in notin: # account['fullname'] = acct_rec.f_fullname.decode('utf-8') # # if acct_rec.f_password not in notin: # account['password'] = acct_rec.f_password.decode('utf-8') # # if acct_rec.f_hash1 not in notin: # account['hash1'] = acct_rec.f_hash1 # # if acct_rec.f_hash1_type not in notin: # account['hash1_type'] = acct_rec.f_hash1_type # # if acct_rec.f_hash2 not in notin: # account['hash2'] = acct_rec.f_hash2 # # if acct_rec.f_hash2_type not in notin: # account['hash2_type'] = acct_rec.f_hash2_type # # if acct_rec.f_uid not in notin: # account['uid'] = acct_rec.f_uid # # if acct_rec.f_gid not in notin: # account['gid'] = acct_rec.f_gid # # if acct_rec.f_level not in notin: # account['level'] = acct_rec.f_level # # if acct_rec.f_domain not in notin: # account['domain'] = acct_rec.f_domain.decode('utf-8') # # if acct_rec.f_description not in notin: # account['description'] = acct_rec.f_description.decode('utf-8') # host['accounts'].append(account) hosts.append(host) #response.files.append(URL(request.application,'static','js/jquery.sparkline.js')) #get JSON from host.list and use mockjax ext = request.extension request.extension = 'json' hostlist = list() #Not an empty list request.extension = ext #remove the engineer field from the customers report hostlist['aaData'][-1]['10'] = None import re hostlist = re.sub("href=\"[^>]*>([^<]*)", "href=\"#\\1\">\\1", str(hostlist)) listjson = hostlist.replace('\"', '\\\"').replace('\'', '\"').replace( 'L, ', ', ').replace('None', 'null') vulnlst = sorted(vulnerabilities, key=lambda x: int(vulnerabilities[x]['severity']), reverse=True) return dict(vulnlst=vulnlst, vulnerabilities=vulnerabilities, statistics=statistics, adv_stats=adv_stats, graphs=graphs, hosts=hosts, hostfilter=session.hostfilter, listjson=listjson)
def vulninfo_by_vulnid(): """ Returns the vulnerablilty details """ if request.args(0) is None: redirect( URL('default', 'error', vars={'msg': T('No Vulnerability ID sent')})) record = db(db.t_vulndata.f_vulnid == request.args(0)).select().first() if record is not None: # grab vuln references and format the table response.title = "%s :: Vulnerability Popup :: %s" % (settings.title, record.f_vulnid) #cvss_metrics = "AV:%s/AC:%s/Au:%s/C:%s/I:%s/A:%s" % (record.f_cvss_av, # record.f_cvss_ac, # record.f_cvss_au, # record.f_cvss_c, # record.f_cvss_i, # record.f_cvss_a) vulninfo = record cvssmetrics = cvss_metrics(record) refs = LOAD(request.controller, 'vuln_refs_by_vulnid', args=[record.id], ajax=True) exploits = LOAD(request.controller, 'vuln_exploits_by_vulnid', args=[record.id], ajax=True) # TODO: Add hosts with vulnerability -- include service info (proto/port) and # ability to delete vuln from service query = db.t_service_vulns.f_vulndata_id == record.id svc_vulns = db(query).select(db.t_service_vulns.f_services_id, db.t_service_vulns.f_proof, db.t_service_vulns.f_status, db.t_service_vulns.id, distinct=True) hosts_tr = [] query = (db.t_hosts.id > 0) query = create_hostfilter_query(session.hostfilter, query, 't_services') hosts_dict = db(query).select(db.t_hosts.id, cache=(cache.ram, 30)).as_dict() hostlist = map(lambda x: x['id'], hosts_dict.itervalues()) for svc_vuln in svc_vulns: svc = db.t_services[svc_vuln.f_services_id] if svc is None: logger.error( "t_servics_vuln #%s does not link to a t_services.id!" % (svc_vuln.id)) continue if svc.f_hosts_id not in hostlist: continue host_rec = db.t_hosts[svc.f_hosts_id] hosts_tr.append( TR(TD( SPAN(I(_class="icon-trash"), _name="host_del", _id=svc_vuln.id)), TD( A(IMG(_src=URL(request.application, 'static/images', 'terminal.png'), _width="20", _height="20", _style="float:left"), " ", _href="#", _onclick="launchterm('%s')" % (host_rec.id)), host_a_maker(host_rec)), TD("%s/%s" % (svc.f_proto, svc.f_number)), TD(MARKMIN(svc_vuln.f_proof)), TD(svc_vuln.f_status), _id=svc_vuln.id)) if len(hosts_tr) > 0: hosts = TABLE(THEAD( TR( TH(T('Del'), _width="5%"), TH(T('Host Information')), TH(T('Port')), TH(T('Proof')), TH(T('Status')), )), TBODY(hosts_tr), _id="vulntable", _class="datatable", _width="100%") else: hosts = None else: response.title = "%s :: Invalid Vulnerability ID" return dict(vulninfo={}, refs={}, exploits={}, hosts={}) # vuln form data vuln = crud.read(db.t_vulndata, record) #returns read-only for for t_vulndata vuln.attributes['_id'] = "vuln_record" return dict(vuln=vuln, vulninfo=vulninfo, cvssmetrics=cvssmetrics, refs=refs, exploits=exploits, hosts=hosts)