rename qualys modules to be more accurate

This commit is contained in:
pemontto
2019-05-03 16:39:57 +01:00
parent fb76b0a1ce
commit 44d75c397f
8 changed files with 56 additions and 56 deletions

View File

@ -24,13 +24,13 @@ db_path=/opt/VulnWhisperer/data/database
trash=false trash=false
verbose=false verbose=false
[qualys_web] [qualys_was]
#Reference https://www.qualys.com/docs/qualys-was-api-user-guide.pdf to find your API #Reference https://www.qualys.com/docs/qualys-was-api-user-guide.pdf to find your API
enabled=true enabled=true
hostname=qualys_web hostname=qualys_was
username=exampleuser username=exampleuser
password=examplepass password=examplepass
write_path=/opt/VulnWhisperer/data/qualys_web/ write_path=/opt/VulnWhisperer/data/qualys_was/
db_path=/opt/VulnWhisperer/data/database db_path=/opt/VulnWhisperer/data/database
verbose=false verbose=false
@ -40,13 +40,13 @@ max_retries=10
# Template ID will need to be retrieved for each document. Please follow the reference guide above for instructions on how to get your template ID. # Template ID will need to be retrieved for each document. Please follow the reference guide above for instructions on how to get your template ID.
template_id=289109 template_id=289109
[qualys_vuln] [qualys_vm]
#Reference https://www.qualys.com/docs/qualys-was-api-user-guide.pdf to find your API #Reference https://www.qualys.com/docs/qualys-was-api-user-guide.pdf to find your API
enabled=true enabled=true
hostname=qualys_vuln hostname=qualys_vm
username=exampleuser username=exampleuser
password=examplepass password=examplepass
write_path=/opt/VulnWhisperer/data/qualys_vuln/ write_path=/opt/VulnWhisperer/data/qualys_vm/
db_path=/opt/VulnWhisperer/data/database db_path=/opt/VulnWhisperer/data/database
verbose=false verbose=false
@ -83,8 +83,8 @@ verbose=false
dns_resolv=False dns_resolv=False
#Sample jira report scan, will automatically be created for existent scans #Sample jira report scan, will automatically be created for existent scans
#[jira.qualys_vuln.test_scan] #[jira.qualys_vm.test_scan]
#source=qualys_vuln #source=qualys_vm
#scan_name=Test Scan #scan_name=Test Scan
#jira_project=PROJECT #jira_project=PROJECT
; if multiple components, separate by ","=None ; if multiple components, separate by ","=None

View File

@ -6,19 +6,19 @@
input { input {
file { file {
path => [ "/opt/VulnWhisperer/data/qualys_vuln/*.json" ] path => [ "/opt/VulnWhisperer/data/qualys_vm/*.json" ]
codec => json codec => json
start_position => "beginning" start_position => "beginning"
tags => [ "qualys_vuln" ] tags => [ "qualys_vm" ]
mode => "read" mode => "read"
start_position => "beginning" start_position => "beginning"
file_completed_action => "delete" file_completed_action => "delete"
} }
file { file {
path => [ "/opt/VulnWhisperer/data/qualys_web/*.json" ] path => [ "/opt/VulnWhisperer/data/qualys_was/*.json" ]
codec => json codec => json
start_position => "beginning" start_position => "beginning"
tags => [ "qualys_web" ] tags => [ "qualys_was" ]
mode => "read" mode => "read"
start_position => "beginning" start_position => "beginning"
file_completed_action => "delete" file_completed_action => "delete"
@ -26,7 +26,7 @@ input {
} }
filter { filter {
if "qualys_vuln" in [tags] or "qualys_web" in [tags] { if "qualys_vm" in [tags] or "qualys_was" in [tags] {
date { date {
match => [ "scan_time", "UNIX" ] match => [ "scan_time", "UNIX" ]
target => "@timestamp" target => "@timestamp"
@ -82,7 +82,7 @@ filter {
} }
} }
output { output {
if "qualys_vuln" in [tags] or "qualys_web" in [tags] { if "qualys_vm" in [tags] or "qualys_was" in [tags] {
if [@metadata][id] { if [@metadata][id] {
elasticsearch { elasticsearch {
hosts => [ "elasticsearch:9200" ] hosts => [ "elasticsearch:9200" ]

View File

@ -89,20 +89,20 @@ else
fi fi
# Test Qualys signature:OpenSSL Multiple Remote Security Vulnerabilities # Test Qualys signature:OpenSSL Multiple Remote Security Vulnerabilities
qualys_vuln_doc=$(curl -s "$elasticsearch_url/logstash-vulnwhisperer-*/_search?q=tags:qualys_vuln%20AND%20ip:%22176.28.50.164%22%20AND%20signature:%22OpenSSL%20Multiple%20Remote%20Security%20Vulnerabilities%22%20AND%20port:465" | jq '.hits.hits[]._source') qualys_vm_doc=$(curl -s "$elasticsearch_url/logstash-vulnwhisperer-*/_search?q=tags:qualys_vm%20AND%20ip:%22176.28.50.164%22%20AND%20signature:%22OpenSSL%20Multiple%20Remote%20Security%20Vulnerabilities%22%20AND%20port:465" | jq '.hits.hits[]._source')
# Test @timestamp # Test @timestamp
if echo $qualys_vuln_doc | jq '.["@timestamp"]' | grep -q '2019-03-30T10:17:41.000Z'; then if echo $qualys_vm_doc | jq '.["@timestamp"]' | grep -q '2019-03-30T10:17:41.000Z'; then
green "✅ Passed: Qualys VM @timestamp == 2019-03-30T10:17:41.000Z" green "✅ Passed: Qualys VM @timestamp == 2019-03-30T10:17:41.000Z"
else else
red "❌ Failed: Qualys VM @timestamp == 2019-03-30T10:17:41.000Z was: $(echo $qualys_vuln_doc | jq '.["@timestamp"]') instead" red "❌ Failed: Qualys VM @timestamp == 2019-03-30T10:17:41.000Z was: $(echo $qualys_vm_doc | jq '.["@timestamp"]') instead"
((return_code = return_code + 1)) ((return_code = return_code + 1))
fi fi
# Test @XXXX # Test @XXXX
if echo $qualys_vuln_doc | jq '.cvss' | grep -q '5.6'; then if echo $qualys_vm_doc | jq '.cvss' | grep -q '5.6'; then
green "✅ Passed: Qualys VM cvss == 5.6" green "✅ Passed: Qualys VM cvss == 5.6"
else else
red "❌ Failed: Qualys VM cvss == 5.6 was: $(echo $qualys_vuln_doc | jq '.cvss') instead" red "❌ Failed: Qualys VM cvss == 5.6 was: $(echo $qualys_vm_doc | jq '.cvss') instead"
((return_code = return_code + 1)) ((return_code = return_code + 1))
fi fi

View File

@ -59,8 +59,8 @@ yellow "\n*********************************************"
yellow "* Test two failed scans *" yellow "* Test two failed scans *"
yellow "*********************************************" yellow "*********************************************"
rm -rf /opt/VulnWhisperer/* rm -rf /opt/VulnWhisperer/*
yellow "Removing ${TEST_PATH}/qualys_vuln/scan_1553941061.87241" yellow "Removing ${TEST_PATH}/qualys_vm/scan_1553941061.87241"
mv "${TEST_PATH}/qualys_vuln/scan_1553941061.87241"{,.bak} mv "${TEST_PATH}/qualys_vm/scan_1553941061.87241"{,.bak}
if vuln_whisperer -F -c configs/test.ini --mock --mock_dir "${TEST_PATH}"; [[ $? -eq 2 ]]; then if vuln_whisperer -F -c configs/test.ini --mock --mock_dir "${TEST_PATH}"; [[ $? -eq 2 ]]; then
green "\n✅ Passed: Test two failed scans" green "\n✅ Passed: Test two failed scans"
else else
@ -83,7 +83,7 @@ yellow "\n*********************************************"
yellow "* Test only Qualys VM with one failed scan *" yellow "* Test only Qualys VM with one failed scan *"
yellow "*********************************************" yellow "*********************************************"
rm -rf /opt/VulnWhisperer/* rm -rf /opt/VulnWhisperer/*
if vuln_whisperer -F -c configs/test.ini -s qualys_vuln --mock --mock_dir "${TEST_PATH}"; [[ $? -eq 1 ]]; then if vuln_whisperer -F -c configs/test.ini -s qualys_vm --mock --mock_dir "${TEST_PATH}"; [[ $? -eq 1 ]]; then
green "\n✅ Passed: Test only Qualys VM with one failed scan" green "\n✅ Passed: Test only Qualys VM with one failed scan"
else else
red "\n❌ Failed: Test only Qualys VM with one failed scan" red "\n❌ Failed: Test only Qualys VM with one failed scan"
@ -91,7 +91,7 @@ else
fi fi
# Restore the removed files # Restore the removed files
mv "${TEST_PATH}/qualys_vuln/scan_1553941061.87241.bak" "${TEST_PATH}/qualys_vuln/scan_1553941061.87241" mv "${TEST_PATH}/qualys_vm/scan_1553941061.87241.bak" "${TEST_PATH}/qualys_vm/scan_1553941061.87241"
mv "${TEST_PATH}/nessus/GET_scans_exports_164_download.bak" "${TEST_PATH}/nessus/GET_scans_exports_164_download" mv "${TEST_PATH}/nessus/GET_scans_exports_164_download.bak" "${TEST_PATH}/nessus/GET_scans_exports_164_download"
exit $return_code exit $return_code

View File

@ -18,7 +18,7 @@ class qualysWhisperAPI(object):
self.logger = logging.getLogger('qualysWhisperAPI') self.logger = logging.getLogger('qualysWhisperAPI')
self.config = config self.config = config
try: try:
self.qgc = qualysapi.connect(config, 'qualys_vuln') self.qgc = qualysapi.connect(config, 'qualys_vm')
# Fail early if we can't make a request or auth is incorrect # Fail early if we can't make a request or auth is incorrect
self.qgc.request('about.php') self.qgc.request('about.php')
self.logger.info('Connected to Qualys at {}'.format(self.qgc.server)) self.logger.info('Connected to Qualys at {}'.format(self.qgc.server))

View File

@ -38,7 +38,7 @@ class qualysWhisperAPI(object):
self.logger = logging.getLogger('qualysWhisperAPI') self.logger = logging.getLogger('qualysWhisperAPI')
self.config = config self.config = config
try: try:
self.qgc = qualysapi.connect(config, 'qualys_web') self.qgc = qualysapi.connect(config, 'qualys_was')
self.logger.info('Connected to Qualys at {}'.format(self.qgc.server)) self.logger.info('Connected to Qualys at {}'.format(self.qgc.server))
except Exception as e: except Exception as e:
self.logger.error('Could not connect to Qualys: {}'.format(str(e))) self.logger.error('Could not connect to Qualys: {}'.format(str(e)))
@ -46,7 +46,7 @@ class qualysWhisperAPI(object):
#"content-type": "text/xml"} #"content-type": "text/xml"}
"Accept" : "application/json", "Accept" : "application/json",
"Content-Type": "application/json"} "Content-Type": "application/json"}
self.config_parse = qcconf.QualysConnectConfig(config, 'qualys_web') self.config_parse = qcconf.QualysConnectConfig(config, 'qualys_was')
try: try:
self.template_id = self.config_parse.get_template_id() self.template_id = self.config_parse.get_template_id()
except: except:

View File

@ -37,16 +37,16 @@ class mockAPI(object):
body=open('{}/{}/{}'.format(self.mock_dir, framework, filename)).read() body=open('{}/{}/{}'.format(self.mock_dir, framework, filename)).read()
) )
def qualys_vuln_callback(self, request, uri, response_headers): def qualys_vm_callback(self, request, uri, response_headers):
self.logger.info('Simulating response for {} ({})'.format(uri, request.body)) self.logger.info('Simulating response for {} ({})'.format(uri, request.body))
if 'list' in request.parsed_body['action']: if 'list' in request.parsed_body['action']:
return [200, return [200,
response_headers, response_headers,
open(self.qualys_vuln_path + '/scans').read()] open(self.qualys_vm_path + '/scans').read()]
elif 'fetch' in request.parsed_body['action']: elif 'fetch' in request.parsed_body['action']:
try: try:
response_body = open('{}/{}'.format( response_body = open('{}/{}'.format(
self.qualys_vuln_path, self.qualys_vm_path,
request.parsed_body['scan_ref'][0].replace('/', '_')) request.parsed_body['scan_ref'][0].replace('/', '_'))
).read() ).read()
except: except:
@ -54,7 +54,7 @@ class mockAPI(object):
response_body = '' response_body = ''
return [200, response_headers, response_body] return [200, response_headers, response_body]
def create_qualys_vuln_resource(self, framework): def create_qualys_vm_resource(self, framework):
# Create health check endpoint # Create health check endpoint
self.logger.info('Adding mocked {} endpoint GET msp/about.php'.format(framework)) self.logger.info('Adding mocked {} endpoint GET msp/about.php'.format(framework))
httpretty.register_uri( httpretty.register_uri(
@ -65,15 +65,15 @@ class mockAPI(object):
self.logger.info('Adding mocked {} endpoint {} {}'.format(framework, 'POST', 'api/2.0/fo/scan')) self.logger.info('Adding mocked {} endpoint {} {}'.format(framework, 'POST', 'api/2.0/fo/scan'))
httpretty.register_uri( httpretty.register_uri(
httpretty.POST, 'https://{}:443/api/2.0/fo/scan/'.format(framework), httpretty.POST, 'https://{}:443/api/2.0/fo/scan/'.format(framework),
body=self.qualys_vuln_callback) body=self.qualys_vm_callback)
def qualys_web_callback(self, request, uri, response_headers): def qualys_was_callback(self, request, uri, response_headers):
self.logger.info('Simulating response for {} ({})'.format(uri, request.body)) self.logger.info('Simulating response for {} ({})'.format(uri, request.body))
report_id = request.parsed_body.split('<WasScan><id>')[1].split('<')[0] report_id = request.parsed_body.split('<WasScan><id>')[1].split('<')[0]
response_body = open('{}/create_{}'.format(self.qualys_web_path, report_id)).read() response_body = open('{}/create_{}'.format(self.qualys_was_path, report_id)).read()
return [200, response_headers, response_body] return [200, response_headers, response_body]
def create_qualys_web_resource(self, framework): def create_qualys_was_resource(self, framework):
for filename in self.get_files('{}/{}'.format(self.mock_dir, framework)): for filename in self.get_files('{}/{}'.format(self.mock_dir, framework)):
if filename.startswith('POST') or filename.startswith('GET'): if filename.startswith('POST') or filename.startswith('GET'):
method, resource = filename.split('_', 1) method, resource = filename.split('_', 1)
@ -87,7 +87,7 @@ class mockAPI(object):
self.logger.info('Adding mocked {} endpoint {} {}'.format(framework, 'POST', 'qps/rest/3.0/create/was/report')) self.logger.info('Adding mocked {} endpoint {} {}'.format(framework, 'POST', 'qps/rest/3.0/create/was/report'))
httpretty.register_uri( httpretty.register_uri(
httpretty.POST, 'https://{}:443/qps/rest/3.0/create/was/report'.format(framework), httpretty.POST, 'https://{}:443/qps/rest/3.0/create/was/report'.format(framework),
body=self.qualys_web_callback) body=self.qualys_was_callback)
def openvas_callback(self, request, uri, response_headers): def openvas_callback(self, request, uri, response_headers):
self.logger.info('Simulating response for {} ({})'.format(uri, request.body)) self.logger.info('Simulating response for {} ({})'.format(uri, request.body))
@ -116,12 +116,12 @@ class mockAPI(object):
for framework in self.get_directories(self.mock_dir): for framework in self.get_directories(self.mock_dir):
if framework in ['nessus', 'tenable']: if framework in ['nessus', 'tenable']:
self.create_nessus_resource(framework) self.create_nessus_resource(framework)
elif framework == 'qualys_vuln': elif framework == 'qualys_vm':
self.qualys_vuln_path = self.mock_dir + '/' + framework self.qualys_vm_path = self.mock_dir + '/' + framework
self.create_qualys_vuln_resource(framework) self.create_qualys_vm_resource(framework)
elif framework == 'qualys_web': elif framework == 'qualys_was':
self.qualys_web_path = self.mock_dir + '/' + framework self.qualys_was_path = self.mock_dir + '/' + framework
self.create_qualys_web_resource(framework) self.create_qualys_was_resource(framework)
elif framework == 'openvas': elif framework == 'openvas':
self.openvas_path = self.mock_dir + '/' + framework self.openvas_path = self.mock_dir + '/' + framework
self.create_openvas_resource(framework) self.create_openvas_resource(framework)

View File

@ -18,8 +18,8 @@ from lxml import objectify
from base.config import vwConfig from base.config import vwConfig
from frameworks.nessus import NessusAPI from frameworks.nessus import NessusAPI
from frameworks.openvas import OpenVAS_API from frameworks.openvas import OpenVAS_API
from frameworks.qualys_vuln import qualysVulnScan from frameworks.qualys_vm import qualysVulnScan
from frameworks.qualys_web import qualysScanReport from frameworks.qualys_was import qualysScanReport
from reporting.jira_api import JiraAPI from reporting.jira_api import JiraAPI
@ -544,9 +544,9 @@ class vulnWhispererNessus(vulnWhispererBase):
return self.exit_code return self.exit_code
class vulnWhispererQualys(vulnWhispererBase): class vulnWhispererQualysWAS(vulnWhispererBase):
CONFIG_SECTION = 'qualys_web' CONFIG_SECTION = 'qualys_was'
def __init__( def __init__(
self, self,
config=None, config=None,
@ -556,8 +556,8 @@ class vulnWhispererQualys(vulnWhispererBase):
debug=False, debug=False,
): ):
super(vulnWhispererQualys, self).__init__(config=config, verbose=verbose, debug=debug) super(vulnWhispererQualysWAS, self).__init__(config=config, verbose=verbose, debug=debug)
self.logger = logging.getLogger('vulnWhispererQualys') self.logger = logging.getLogger('vulnWhispererQualysWAS')
if not verbose: if not verbose:
verbose = self.config.getbool(self.CONFIG_SECTION, 'verbose') verbose = self.config.getbool(self.CONFIG_SECTION, 'verbose')
self.logger.setLevel(logging.DEBUG if debug else logging.INFO if verbose else logging.WARNING) self.logger.setLevel(logging.DEBUG if debug else logging.INFO if verbose else logging.WARNING)
@ -583,7 +583,7 @@ class vulnWhispererQualys(vulnWhispererBase):
try: try:
if 'Z' in launched_date: if 'Z' in launched_date:
launched_date = self.qualys_scan.utils.iso_to_epoch(launched_date) launched_date = self.qualys_scan.utils.iso_to_epoch(launched_date)
report_name = 'qualys_web_' + str(report_id) \ report_name = 'qualys_was_' + str(report_id) \
+ '_{last_updated}'.format(last_updated=launched_date) \ + '_{last_updated}'.format(last_updated=launched_date) \
+ '.{extension}'.format(extension=output_format) + '.{extension}'.format(extension=output_format)
@ -843,7 +843,7 @@ class vulnWhispererOpenVAS(vulnWhispererBase):
class vulnWhispererQualysVuln(vulnWhispererBase): class vulnWhispererQualysVuln(vulnWhispererBase):
CONFIG_SECTION = 'qualys_vuln' CONFIG_SECTION = 'qualys_vm'
def __init__( def __init__(
self, self,
@ -873,7 +873,7 @@ class vulnWhispererQualysVuln(vulnWhispererBase):
cleanup=True): cleanup=True):
if 'Z' in launched_date: if 'Z' in launched_date:
launched_date = self.qualys_scan.utils.iso_to_epoch(launched_date) launched_date = self.qualys_scan.utils.iso_to_epoch(launched_date)
report_name = 'qualys_vuln_' + report_id.replace('/','_') \ report_name = 'qualys_vm_' + report_id.replace('/','_') \
+ '_{last_updated}'.format(last_updated=launched_date) \ + '_{last_updated}'.format(last_updated=launched_date) \
+ '.{extension}'.format(extension=output_format) + '.{extension}'.format(extension=output_format)
@ -1122,7 +1122,7 @@ class vulnWhispererJIRA(vulnWhispererBase):
return vulnerabilities return vulnerabilities
def parse_qualys_vuln_vulnerabilities(self, fullpath, source, scan_name, min_critical, dns_resolv = False): def parse_qualys_vm_vulnerabilities(self, fullpath, source, scan_name, min_critical, dns_resolv = False):
#parsing of the qualys vulnerabilities schema #parsing of the qualys vulnerabilities schema
#parse json #parse json
vulnerabilities = [] vulnerabilities = []
@ -1230,8 +1230,8 @@ class vulnWhispererJIRA(vulnWhispererBase):
vulnerabilities = self.parse_nessus_vulnerabilities(fullpath, source, scan_name, min_critical) vulnerabilities = self.parse_nessus_vulnerabilities(fullpath, source, scan_name, min_critical)
#***Qualys VM parsing*** #***Qualys VM parsing***
if source == "qualys_vuln": if source == "qualys_vm":
vulnerabilities = self.parse_qualys_vuln_vulnerabilities(fullpath, source, scan_name, min_critical, dns_resolv) vulnerabilities = self.parse_qualys_vm_vulnerabilities(fullpath, source, scan_name, min_critical, dns_resolv)
#***JIRA sync*** #***JIRA sync***
if vulnerabilities: if vulnerabilities:
@ -1286,8 +1286,8 @@ class vulnWhisperer(object):
debug=self.debug) debug=self.debug)
self.exit_code += vw.whisper_nessus() self.exit_code += vw.whisper_nessus()
elif self.profile == 'qualys_web': elif self.profile == 'qualys_was':
vw = vulnWhispererQualys(config=self.config, vw = vulnWhispererQualysWAS(config=self.config,
verbose=self.verbose, verbose=self.verbose,
debug=self.debug) debug=self.debug)
self.exit_code += vw.process_web_assets() self.exit_code += vw.process_web_assets()
@ -1305,7 +1305,7 @@ class vulnWhisperer(object):
debug=self.debug) debug=self.debug)
self.exit_code += vw.whisper_nessus() self.exit_code += vw.whisper_nessus()
elif self.profile == 'qualys_vuln': elif self.profile == 'qualys_vm':
vw = vulnWhispererQualysVuln(config=self.config, vw = vulnWhispererQualysVuln(config=self.config,
verbose=self.verbose, verbose=self.verbose,
debug=self.debug) debug=self.debug)