rename plugin to signature and cvss_x to cvss2_x

This commit is contained in:
pemontto
2019-05-03 16:25:29 +01:00
parent a1671a953f
commit fb76b0a1ce
8 changed files with 79 additions and 73 deletions

View File

@ -17,7 +17,7 @@ class NessusAPI(object):
SCANS = '/scans'
SCAN_ID = SCANS + '/{scan_id}'
HOST_VULN = SCAN_ID + '/hosts/{host_id}'
PLUGINS = HOST_VULN + '/plugins/{plugin_id}'
PLUGINS = HOST_VULN + '/plugins/{signature_id}'
EXPORT = SCAN_ID + '/export'
EXPORT_TOKEN_DOWNLOAD = '/scans/exports/{token_id}/download'
EXPORT_FILE_DOWNLOAD = EXPORT + '/{file_id}/download'
@ -25,17 +25,19 @@ class NessusAPI(object):
EXPORT_HISTORY = EXPORT + '?history_id={history_id}'
# All column mappings should be lowercase
COLUMN_MAPPING = {
'cvss base score': 'cvss_base',
'cvss temporal score': 'cvss_temporal',
'cvss temporal vector': 'cvss_temporal_vector',
'cvss base score': 'cvss2_base',
'cvss temporal score': 'cvss2_temporal',
'cvss temporal vector': 'cvss2_temporal_vector',
'cvss vector': 'cvss2_vector',
'cvss3 base score': 'cvss3_base',
'cvss3 temporal score': 'cvss3_temporal',
'cvss3 temporal vector': 'cvss3_temporal_vector',
'fqdn': 'dns',
'host': 'asset',
'ip address': 'ip',
'name': 'plugin_name',
'name': 'signature',
'os': 'operating_system',
'plugin id': 'signature_id',
'see also': 'exploitability',
'system type': 'category',
'vulnerability state': 'state'

View File

@ -83,10 +83,10 @@ class qualysVulnScan:
'impact': 'synopsis',
'ip_status': 'state',
'os': 'operating_system',
'qid': 'plugin_id',
'qid': 'signature_id',
'results': 'plugin_output',
'threat': 'description',
'title': 'plugin_name'
'title': 'signature'
}
SEVERITY_MAPPING = {0: 'none', 1: 'low', 2: 'medium', 3: 'high',4: 'critical'}
@ -164,10 +164,12 @@ class qualysVulnScan:
# Contruct the CVSS vector
self.logger.info('Extracting CVSS components')
df['cvss_vector'] = df['cvss_base'].str.extract('\((.*)\)', expand=False)
df['cvss_base'] = df['cvss_base'].str.extract('^(\d+(?:\.\d+)?)', expand=False)
df['cvss_temporal_vector'] = df['cvss_temporal'].str.extract('\((.*)\)', expand=False)
df['cvss_temporal'] = df['cvss_temporal'].str.extract('^(\d+(?:\.\d+)?)', expand=False)
df['cvss2_vector'] = df['cvss_base'].str.extract('\((.*)\)', expand=False)
df['cvss2_base'] = df['cvss_base'].str.extract('^(\d+(?:\.\d+)?)', expand=False)
df['cvss2_temporal_vector'] = df['cvss_temporal'].str.extract('\((.*)\)', expand=False)
df['cvss2_temporal'] = df['cvss_temporal'].str.extract('^(\d+(?:\.\d+)?)', expand=False)
df.drop('cvss_base', axis=1, inplace=True, errors='ignore')
df.drop('cvss_temporal', axis=1, inplace=True, errors='ignore')
# Set asset to ip
df['asset'] = df['ip']

View File

@ -289,12 +289,12 @@ class qualysScanReport:
'DescriptionSeverity': 'synopsis',
'Evidence #1': 'evidence',
'Payload #1': 'payload',
'QID': 'plugin_id',
'QID': 'signature_id',
'Request Headers #1': 'request_headers',
'Request Method #1': 'request_method',
'Request URL #1': 'request_url',
'Response #1': 'plugin_output',
'Title': 'plugin_name',
'Title': 'signature',
'Url': 'uri',
'URL': 'url',
'Vulnerability Category': 'type',

View File

@ -249,15 +249,17 @@ class vulnWhispererBase(object):
"""Map and transform common data values"""
self.logger.info('Start common normalisation')
df.replace({'': np.nan}, inplace=True)
self.logger.debug('Normalising CVSS')
for cvss_version in ['cvss', 'cvss3']:
for cvss_version in ['cvss2', 'cvss3']:
# cvssX = cvssX_temporal else cvssX_base
if cvss_version + '_base' in df:
self.logger.debug('Normalising {} base'.format(cvss_version))
# CVSS = cvss_temporal or cvss_base
df[cvss_version] = df[cvss_version + '_base']
df.loc[df[cvss_version + '_temporal'] != '', cvss_version] = df[cvss_version + '_temporal']
df[cvss_version] = df[cvss_version + '_temporal'].fillna(df[cvss_version])
# Combine CVSS and CVSS3 vectors
# Combine cvssX temporal and base vectors
if cvss_version + '_vector' in df and cvss_version + '_temporal_vector' in df:
self.logger.debug('Normalising {} vector'.format(cvss_version))
df[cvss_version + '_vector'] = (
@ -267,16 +269,22 @@ class vulnWhispererBase(object):
)
df.drop(cvss_version + '_temporal_vector', axis=1, inplace=True)
# Map cvssX to severity name
if cvss_version in df:
self.logger.debug('Normalising {} severity'.format(cvss_version))
# Map CVSS to severity name
df.loc[df[cvss_version].astype(str) == '', cvss_version] = None
df[cvss_version] = df[cvss_version].astype('float')
df[cvss_version + '_severity'] = 'informational'
df.loc[(df[cvss_version] > 0) & (df[cvss_version] < 3), cvss_version + '_severity'] = 'low'
df.loc[(df[cvss_version] >= 3) & (df[cvss_version] < 6), cvss_version + '_severity'] = 'medium'
df.loc[(df[cvss_version] >= 6) & (df[cvss_version] < 9), cvss_version + '_severity'] = 'high'
df.loc[(df[cvss_version] > 9) & (df[cvss_version].notnull()), cvss_version + '_severity'] = 'critical'
df.loc[df[cvss_version] > 9, cvss_version + '_severity'] = 'critical'
# Get a single cvss score derived from cvss3 else cvss2
if not 'cvss' in df:
if 'cvss3' in df:
df['cvss'] = df['cvss3'].fillna(df['cvss2'])
elif 'cvss2' in df:
df['cvss'] = df['cvss2']
self.logger.debug('Creating Unique Document ID')
df['_unique'] = df.index.values
@ -285,12 +293,6 @@ class vulnWhispererBase(object):
else:
df['_unique'] = df[['scan_id', '_unique']].apply(lambda x: '_'.join(x.astype(str)), axis=1)
# Rename cvss to cvss2
# Make cvss with no suffix == cvss3 else cvss2
# cvss = cvss3 if cvss3 else cvss2
# cvss_severity = cvss3_severity if cvss3_severity else cvss2_severity
df.replace({'': np.nan}, inplace=True)
return df
@ -700,7 +702,7 @@ class vulnWhispererOpenVAS(vulnWhispererBase):
'CVSS': 'cvss',
'Severity': 'severity',
'Solution Type': 'category',
'NVT Name': 'plugin_name',
'NVT Name': 'signature',
'Summary': 'synopsis',
'Specific Result': 'plugin_output',
'NVT OID': 'nvt_oid',
@ -1141,16 +1143,16 @@ class vulnWhispererJIRA(vulnWhispererBase):
continue
elif data[index]['type'] == 'Practice' or data[index]['type'] == 'Ig':
self.logger.debug("Vulnerability '{vuln}' ignored, as it is 'Practice/Potential', not verified.".format(vuln=data[index]['plugin_name']))
self.logger.debug("Vulnerability '{vuln}' ignored, as it is 'Practice/Potential', not verified.".format(vuln=data[index]['signature']))
continue
if not vulnerabilities or data[index]['plugin_name'] not in [entry['title'] for entry in vulnerabilities]:
if not vulnerabilities or data[index]['signature'] not in [entry['title'] for entry in vulnerabilities]:
vuln = {}
#vulnerabilities should have all the info for creating all JIRA labels
vuln['source'] = source
vuln['scan_name'] = scan_name
#vulnerability variables
vuln['title'] = data[index]['plugin_name']
vuln['title'] = data[index]['signature']
vuln['diagnosis'] = data[index]['threat'].replace('\\n',' ')
vuln['consequence'] = data[index]['impact'].replace('\\n',' ')
vuln['solution'] = data[index]['solution'].replace('\\n',' ')
@ -1171,7 +1173,7 @@ class vulnWhispererJIRA(vulnWhispererBase):
else:
# grouping assets by vulnerability to open on single ticket, as each asset has its own nessus entry
for vuln in vulnerabilities:
if vuln['title'] == data[index]['plugin_name']:
if vuln['title'] == data[index]['signature']:
vuln['ips'].append("{ip} - {protocol}/{port} - {dns}".format(**self.get_asset_fields(data[index], dns_resolv)))
return vulnerabilities