예제 #1
0
파일: sql.py 프로젝트: Phrozyn/vmintgr
    def get_compliance(self, aid):
        c = self._conn.cursor()
        c.execute('''SELECT assets.id, compliance.id AS cid,
            assets.ip, assets.hostname, assets.mac,
            compliance.lastupdated, compliance.failed,
            vulns.nxvid, vulns.title, vulns.cvss,
            assetvulns.age, assetvulns.autogroup
            FROM assets
            JOIN compliance ON assets.id = compliance.aid
            JOIN assetvulns ON (compliance.failingvid = assetvulns.id
            AND assets.id = assetvulns.aid)
            JOIN vulns ON (assetvulns.vid = vulns.id)
            WHERE assets.id = ?''', (aid,))
        rows = c.fetchall()

        if len(rows) == 0:
            return None
        i = rows[0]

        ce = vuln.ComplianceElement()

        ce.compliance_id = i['cid']
        if i['failed'] == 1:
            ce.failed = True
        else:
            ce.failed = False
        ce.lasthandled = i['lastupdated']

        v = vuln.vulnerability()
        v.assetid = aid
        v.ipaddr = i['ip'].encode('ascii', 'ignore')
        v.macaddr = i['mac'].encode('ascii', 'ignore')
        v.hostname = i['hostname'].encode('ascii', 'ignore')
        v.vid = i['nxvid']
        v.age_days = i['age']
        v.title = i['title'].encode('ascii', 'ignore')
        v.cvss = i['cvss']
        v.autogroup = i['autogroup']
        ce.failvuln = v

        return ce
예제 #2
0
    def get_workflow(self, aid):
        c = self._conn.cursor()
        c.execute('''SELECT assets.id, workflow.id AS wid,
            assets.ip, assets.hostname, vulns.id AS vid,
            assets.mac, vulns.nxvid, vulns.title, vulns.cvss,
            vulns.known_exploits, vulns.known_malware,
            assetvulns.detected, assetvulns.age,
            workflow.lasthandled, workflow.contact, workflow.status,
            assetvulns.autogroup
            FROM assetvulns
            JOIN assets ON assets.id = assetvulns.aid
            JOIN vulns ON vulns.id = assetvulns.vid
            JOIN workflow ON assetvulns.id = workflow.vid
            WHERE assets.id = %d''' % aid)
        rows = c.fetchall()

        ret = []
        for i in rows:
            wfe = vuln.WorkflowElement()

            wfe.lasthandled = i['lasthandled']
            wfe.contact = i['contact']
            wfe.workflow_id = i['wid']
            wfe.status = i['status']

            v = vuln.vulnerability()
            v.assetid = aid
            v.ipaddr = i['ip'].encode('ascii', 'ignore')
            v.macaddr = i['mac'].encode('ascii', 'ignore')
            v.hostname = i['hostname'].encode('ascii', 'ignore')
            v.vid = i['nxvid']
            v.autogroup = i['autogroup']

            # All that is stored right now is Nexpose vulnerabilities, so
            # create a classification value including that
            v.vid_classified = 'nexpose:%d' % v.vid

            rowvid = i['vid']
            v.discovered_date_unix = i['detected']
            v.title = i['title'].encode('ascii', 'ignore')
            v.cvss = i['cvss']
            v.known_malware = False
            v.known_exploits = False
            if i['known_malware'] != 0:
                v.known_malware = True
            if i['known_exploits'] != 0:
                v.known_exploits = True
            v.age_days = i['age']

            # Supplement the element with associated CVEs
            c.execute('''SELECT cve FROM cves
                WHERE vid = %d''' % rowvid)
            rows2 = c.fetchall()
            v.cves = []
            for j in rows2:
                v.cves.append(j[0].encode('ascii', 'ignore'))

            wfe.vulnerability = v

            ret.append(wfe)
        return ret
예제 #3
0
파일: sql.py 프로젝트: Phrozyn/vmintgr
    def get_workflow(self, aid):
        c = self._conn.cursor()
        c.execute('''SELECT assets.id, workflow.id AS wid,
            assets.ip, assets.hostname, vulns.id AS vid,
            assets.mac, vulns.nxvid, vulns.title, vulns.cvss,
            vulns.known_exploits, vulns.known_malware,
            assetvulns.detected, assetvulns.age,
            workflow.lasthandled, workflow.contact, workflow.status,
            assetvulns.autogroup, vulns.description, vulns.cvss_vector,
            assets.nxaid, assetvulns.proof
            FROM assetvulns
            JOIN assets ON assets.id = assetvulns.aid
            JOIN vulns ON vulns.id = assetvulns.vid
            JOIN workflow ON assetvulns.id = workflow.vid
            WHERE assets.id = ?''', (aid,))
        rows = c.fetchall()

        ret = []
        for i in rows:
            wfe = vuln.WorkflowElement()
            
            wfe.lasthandled = i['lasthandled']
            wfe.contact = i['contact']
            wfe.workflow_id = i['wid']
            wfe.status = i['status']
            wfe.assetid_site = i['nxaid']

            v = vuln.vulnerability()
            v.assetid = aid
            v.ipaddr = i['ip'].encode('ascii', 'ignore')
            v.macaddr = i['mac'].encode('ascii', 'ignore')
            v.hostname = i['hostname'].encode('ascii', 'ignore')
            v.vid = i['nxvid']
            v.autogroup = i['autogroup']
            v.proof = i['proof']

            # All that is stored right now is Nexpose vulnerabilities, so
            # create a classification value including that
            v.vid_classified = 'nexpose:%d' % v.vid

            rowvid = i['vid']
            v.discovered_date_unix = i['detected']
            v.title = i['title'].encode('ascii', 'ignore')
            v.description = i['description'].encode('ascii', 'ignore')
            v.cvss = i['cvss']
            v.cvss_vector = i['cvss_vector']
            v.impact_label = vuln.cvss_to_label(v.cvss)
            v.known_malware = False
            v.known_exploits = False
            if i['known_malware'] != 0:
                v.known_malware = True
            if i['known_exploits'] != 0:
                v.known_exploits = True
            v.age_days = i['age']

            # Based on the score of the vulnerability, include the expected
            # patch time (based on initial detection)
            v.patch_in = vuln.cvss_to_patch_in(v.cvss)

            # Supplement the element with associated CVEs
            c.execute('''SELECT cve FROM cves
                WHERE vid = %d''' % rowvid)
            rows2 = c.fetchall()
            v.cves = []
            for j in rows2:
                v.cves.append(j[0].encode('ascii', 'ignore'))

            wfe.vulnerability = v

            ret.append(wfe)
        return ret
예제 #4
0
def vuln_extraction(scanner, vulnquery_where, writefile=None, readfile=None,
    targetcve=None):
    squery = '''
    WITH 
    vuln_references AS ( 
        SELECT vulnerability_id, array_to_string(array_agg(reference), ', ')
        AS references 
        FROM dim_vulnerability 
        JOIN dim_vulnerability_reference USING (vulnerability_id) 
        GROUP BY vulnerability_id 
    ) 
    SELECT ds.name AS site, da.asset_id, da.ip_address,
    da.host_name, da.mac_address,  
    dv.title AS vulnerability, dvs.description AS status, favi.date
    AS discovered_date, 
    CASE WHEN favi.port = -1 THEN NULL ELSE favi.port END AS port, 
    dp.name AS protocol, dsvc.name AS service,
    round(dv.cvss_score::numeric, 2) AS cvss_score, vr.references, dv.exploits,
    dv.malware_kits, dv.vulnerability_id
    FROM fact_asset_vulnerability_instance favi 
    JOIN dim_asset da USING (asset_id) 
    JOIN dim_vulnerability dv USING (vulnerability_id) 
    JOIN dim_site_asset dsa USING (asset_id) 
    JOIN dim_site ds USING (site_id) 
    JOIN dim_vulnerability_status dvs USING (status_id) 
    JOIN dim_protocol dp USING (protocol_id) 
    JOIN dim_service dsvc USING (service_id) 
    JOIN vuln_references vr USING (vulnerability_id) 
    %s
    ORDER BY ds.name, da.ip_address
    ''' % vulnquery_where

    debug.printd('requesting vulnerability details')

    sites = scanner.sitelist.keys()
    if len(sites) == 0:
        return

    agedata = vuln_get_age_data(scanner)

    if readfile != None:
        debug.printd('reading vulnerability data from %s' % readfile)
        fd = open(readfile, 'r')
        vulndata = fd.read()
        fd.close()
    else:
        vulndata = scanner.conn.adhoc_report(squery, sites,
            api_version='1.3.2')

    if writefile != None:
        fd = open(writefile, 'w')
        fd.write(vulndata)
        fd.close()
        sys.exit(0)

    reader = csv.reader(StringIO.StringIO(vulndata))
    nvulns = 0
    linked = 0
    for i in reader:
        if len(i) == 0:
            continue
        if i[0] == 'site':
            continue
        nvulns += 1
        v = vuln.vulnerability()
        v.sitename = i[0]
        v.assetid = int(i[1])
        v.ipaddr = i[2]
        v.hostname = i[3]
        v.macaddr = i[4]
        v.title = i[5]
        v.known_exploits = False
        v.known_malware = False
        if int(i[13]) > 0:
            v.known_exploits = True
        if int(i[14]) > 0:
            v.known_malware = True
        v.vid = i[15]
        idx = i[7].find('.')
        if idx > 0:
            dstr = i[7][:idx]
        else:
            dstr = i[7]
        v.age_days = vuln_age_days(v, agedata)
        dt = datetime.datetime.strptime(dstr, '%Y-%m-%d %H:%M:%S')
        dt = dt.replace(tzinfo=pytz.UTC)
        v.discovered_date = dt

        v.discovered_date_unix = int((v.discovered_date - \
            datetime.datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds())

        v.cvss = float(i[11])
        for i in i[12].split(','):
            buf = i.strip()
            if 'CVE-' in buf:
                if v.cves == None:
                    v.cves = [buf,]
                else:
                    v.cves.append(buf)
            if 'RHSA-' in buf:
                if v.rhsa == None:
                    v.rhsa = [buf,]
                else:
                    v.rhsa.append(buf)

        linked += vuln_instance_link(v, scanner)

    debug.printd('%d vulnerabilities loaded' % nvulns)
    debug.printd('%d vulnerabilities linked' % linked)

    vuln.vuln_reset_uid_cache()
    for s in scanner.sitelist.keys():
        for a in scanner.sitelist[s]['assets']:
            if len(a['vulns']) == 0:
                continue
            # If in target CVE report mode, just report on the CVE but
            # don't actually process the vulnerability
            if targetcve != None:
                vuln.vuln_cvereport(a, targetcve)
                continue
            vuln.vuln_proc_pipeline(a['vulns'],
                a['id'], a['address'], a['macaddress'],
                a['hostname'])

    if targetcve != None:
        return

    vuln.expire_hosts()
예제 #5
0
def vulns_over_time(scanner, gid, start, end):
    squery = '''
    WITH applicable_assets AS (
    SELECT asset_id FROM dim_asset_group_asset
    WHERE asset_group_id = %s
    ),
    applicable_scans AS (
    SELECT asset_id, scan_id
    FROM fact_asset_scan
    WHERE (scan_finished >= '%s') AND
    (scan_finished <= '%s') AND
    asset_id IN (SELECT asset_id FROM applicable_assets)
    ),
    all_findings AS (
    SELECT fasvf.asset_id, da.ip_address, da.host_name,
    MIN(fasvf.date) as first_seen,
    MAX(fasvf.date) as last_seen, fasvf.vulnerability_id,
    dv.title AS vulnerability,
    round(dv.cvss_score::numeric, 2) AS cvss_score
    FROM fact_asset_scan_vulnerability_finding fasvf
    JOIN dim_asset da USING (asset_id)
    JOIN dim_vulnerability dv USING (vulnerability_id)
    JOIN applicable_scans USING (asset_id, scan_id)
    GROUP BY asset_id, ip_address, host_name, vulnerability_id,
    vulnerability, cvss_score
    )
    SELECT * FROM all_findings
    ''' % (gid, start, end)

    ret = nexadhoc.nexpose_adhoc(scanner, squery, [], api_version='1.3.2',
        device_ids=device_filter)
    reader = csv.reader(StringIO.StringIO(ret))
    vulnret = {}
    cnt = 0
    for i in reader:
        if i == None or len(i) == 0:
            continue
        if i[0] == 'asset_id':
            continue
        newvuln = vuln.vulnerability()
        newvuln.assetid = int(i[0])
        newvuln.ipaddr = i[1]
        newvuln.hostname = i[2]
        newvuln.vid = i[5]
        newvuln.title = i[6]
        newvuln.cvss = float(i[7])

        idx = i[3].find('.')
        if idx > 0:
            dstr = i[3][:idx]
        else:
            dstr = i[3]
        dt = datetime.datetime.strptime(dstr, '%Y-%m-%d %H:%M:%S')
        dt = dt.replace(tzinfo=pytz.UTC)
        first_date = dt

        idx = i[4].find('.')
        if idx > 0:
            dstr = i[4][:idx]
        else:
            dstr = i[4]
        dt = datetime.datetime.strptime(dstr, '%Y-%m-%d %H:%M:%S')
        dt = dt.replace(tzinfo=pytz.UTC)
        last_date = dt

        if newvuln.assetid not in vulnret:
            vulnret[newvuln.assetid] = {}
        newfinding = {}
        newfinding['vulnerability'] = newvuln
        newfinding['first_date'] = first_date
        newfinding['last_date'] = last_date
        vulnret[newvuln.assetid][newvuln.vid] = newfinding
        cnt += 1

    debug.printd('vulns_over_time: returning %d issues from %s to %s' % \
        (cnt, start, end))
    return vulnret
예제 #6
0
def vulns_at_time(scanner, gid, timestamp):
    squery = '''
    WITH applicable_assets AS (
    SELECT asset_id FROM dim_asset_group_asset
    WHERE asset_group_id = %s
    ),
    asset_scan_map AS (
    SELECT asset_id, scanAsOf(asset_id, '%s') as scan_id
    FROM dim_asset
    WHERE asset_id IN (SELECT asset_id FROM applicable_assets)
    ),
    current_state_snapshot AS (
    SELECT
    fasvf.asset_id, da.ip_address, da.host_name,
    fasvf.date AS discovered_date,
    fasvf.vulnerability_id,
    dv.title AS vulnerability,
    round(dv.cvss_score::numeric, 2) AS cvss_score,
    dv.cvss_vector AS cvss_vector
    FROM fact_asset_scan_vulnerability_finding fasvf
    JOIN dim_asset da USING (asset_id)
    JOIN dim_vulnerability dv USING (vulnerability_id)
    JOIN asset_scan_map USING (asset_id, scan_id)
    WHERE fasvf.asset_id IN (SELECT asset_id FROM applicable_assets)
    ),
    issue_age AS (
    SELECT
    fasvf.asset_id, fasvf.vulnerability_id,
    MIN(fasvf.date) as earliest
    FROM fact_asset_scan_vulnerability_finding fasvf
    JOIN current_state_snapshot css USING (asset_id, vulnerability_id)
    GROUP BY asset_id, vulnerability_id
    )
    SELECT asset_id, ip_address, host_name, discovered_date,
    vulnerability_id, vulnerability, cvss_score, cvss_vector,
    iage.earliest,
    EXTRACT(EPOCH FROM (discovered_date - iage.earliest))
    FROM current_state_snapshot
    JOIN issue_age iage USING (asset_id, vulnerability_id)
    ''' % (gid, timestamp)

    ret = nexadhoc.nexpose_adhoc(scanner, squery, [], api_version='1.3.2',
        device_ids=device_filter)
    reader = csv.reader(StringIO.StringIO(ret))
    vulnret = {}
    cnt = 0
    duprem = 0
    for i in reader:
        if i == None or len(i) == 0:
            continue
        if i[0] == 'asset_id':
            continue
        newvuln = vuln.vulnerability()
        newvuln.assetid = int(i[0])
        newvuln.ipaddr = i[1]
        newvuln.hostname = i[2]

        if filter_dupip and \
            duplicate_test(vulnret, newvuln.assetid, newvuln.ipaddr):
            duprem += 1
            continue

        idx = i[3].find('.')
        if idx > 0:
            dstr = i[3][:idx]
        else:
            dstr = i[3]
        dt = datetime.datetime.strptime(dstr, '%Y-%m-%d %H:%M:%S')
        dt = dt.replace(tzinfo=pytz.UTC)
        newvuln.discovered_date = dt

        newvuln.vid = i[4]
        newvuln.title = i[5]
        newvuln.cvss = float(i[6])
        newvuln.cvss_vector = i[7]
        newvuln.age_days = float(i[9]) / 60 / 60 / 24

        if newvuln.assetid not in vulnret:
            vulnret[newvuln.assetid] = []
        vulnret[newvuln.assetid].append(newvuln)
        cnt += 1

    debug.printd('vulns_at_time: %s: returning %d issues for %d assets' % \
        (timestamp, cnt, len(vulnret.keys())))
    if duprem > 0:
        debug.printd('vulns_at_time: %d duplicate items were removed' % duprem)
    return vulnret