diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6ca886a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "qualysapi"] + path = deps/qualysapi + url = git@github.com:austin-taylor/qualysapi.git diff --git a/README.md b/README.md index defa808..a2c6cfc 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

-VulnWhisperer is a vulnerability report aggregator for nessus (more scanners to come). VulnWhisperer will pull all the reports +VulnWhisperer is a vulnerability report aggregator. VulnWhisperer will pull all the reports and create a file with a unique filename which is then fed into logstash. Logstash extracts data from the filename and tags all of the information inside the report (see logstash_vulnwhisp.conf file). Data is then shipped to elasticsearch to be indexed. @@ -14,7 +14,7 @@ Requirements #### * ElasticStack * Python 2.7 -* Vulnerability Scanner - (Nessus) +* Vulnerability Scanner * Optional: Message broker such as Kafka or RabbitMQ Currently Supports @@ -23,6 +23,7 @@ Currently Supports * Elasticsearch 2.x * Python 2.7 * Nessus +* Qualys - Web Application Scanner Setup @@ -56,14 +57,22 @@ There are a few configuration steps to setting up VulnWhisperer: Run ----- +To run, fill out the configuration file with your vulnerability scanner settings. Then you can execute from the command line. ```python -vuln_whisperer -c configs/example.ini +vuln_whisperer -c configs/example.ini -s nessus +or +vuln_whisperer -c configs/example.ini -s qualys ``` +Next you'll need to import the visualizations into Kibana and setup your logstash config. A more thorough README is underway with setup instructions. _For windows, you may need to type the full path of the binary in vulnWhisperer located in the bin directory._ Credit ------ Big thank you to Justin Henderson for his contributions to vulnWhisperer! + +AS SEEN ON TV +------------- +

\ No newline at end of file diff --git a/bin/vuln_whisperer b/bin/vuln_whisperer index 284b42e..c131769 100644 --- a/bin/vuln_whisperer +++ b/bin/vuln_whisperer @@ -1,9 +1,8 @@ -#!/usr/bin/env python +#!/usr/bin/python +# -*- coding: utf-8 -*- +__author__ = 'Austin Taylor' -#Written by Austin Taylor -#www.austintaylor.io - from vulnwhisp.vulnwhisp import vulnWhisperer from vulnwhisp.utils.cli import bcolors import os @@ -22,28 +21,38 @@ def main(): your vulnerability scans through aggregation of historical scans.""") parser.add_argument('-c', '--config', dest='config', required=False, default='frameworks.ini', help='Path of config file', type=lambda x: isFileValid(parser, x.strip())) + parser.add_argument('-s', '--section', dest='section', required=False, + help='Section in config') parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=True, help='Prints status out to screen (defaults to True)') parser.add_argument('-u', '--username', dest='username', required=False, default=None, type=lambda x: x.strip(), help='The NESSUS username') parser.add_argument('-p', '--password', dest='password', required=False, default=None, type=lambda x: x.strip(), help='The NESSUS password') args = parser.parse_args() + vw = vulnWhisperer(config=args.config, + profile=args.section, + verbose=args.verbose, + username=args.username, + password=args.password) + + vw.whisper_vulnerabilities() + ''' try: vw = vulnWhisperer(config=args.config, + profile=args.section, verbose=args.verbose, username=args.username, password=args.password) - vw.whisper_nessus() + vw.whisper_vulnerabilities() sys.exit(1) except Exception as e: if args.verbose: print('{red} ERROR: {error}{endc}'.format(red=bcolors.FAIL, error=e, endc=bcolors.ENDC)) sys.exit(2) - - + ''' if __name__ == '__main__': main() \ No newline at end of file diff --git a/configs/frameworks_example.ini b/configs/frameworks_example.ini index 1b015b8..2b8d7fa 100755 --- a/configs/frameworks_example.ini +++ b/configs/frameworks_example.ini @@ -4,9 +4,36 @@ hostname=localhost port=8834 username=nessus_username password=nessus_password -write_path=/opt/vulnwhisp/scans +write_path=/opt/vulnwhisp/nessus/ db_path=/opt/vulnwhisp/database trash=false verbose=true -[ \ No newline at end of file +[qualys] +#Reference https://www.qualys.com/docs/qualys-was-api-user-guide.pdf to find your API +enabled = true +hostname = qualysapi.qg2.apps.qualys.com +username = exampleuser +password = examplepass +write_path=/opt/vulnwhisp/qualys/ +db_path=/opt/vulnwhisp/database +verbose=true + +# Set the maximum number of retries each connection should attempt. +#Note, this applies only to failed connections and timeouts, never to requests where the server returns a response. +max_retries = 10 +template_id = 126024 + +#[proxy] +; This section is optional. Leave it out if you're not using a proxy. +; You can use environmental variables as well: http://www.python-requests.org/en/latest/user/advanced/#proxies + +; proxy_protocol set to https, if not specified. +#proxy_url = proxy.mycorp.com + +; proxy_port will override any port specified in proxy_url +#proxy_port = 8080 + +; proxy authentication +#proxy_username = proxyuser +#proxy_password = proxypass \ No newline at end of file diff --git a/configs/qualys.ini b/configs/qualys.ini deleted file mode 100755 index 917e316..0000000 --- a/configs/qualys.ini +++ /dev/null @@ -1,26 +0,0 @@ -[info] -#Reference https://www.qualys.com/docs/qualys-was-api-user-guide.pdf to find your API -hostname = qualysapi.qg2.apps.qualys.com -username = exampleuser -password = examplepass - -# Set the maximum number of retries each connection should attempt. Note, this applies only to failed connections and timeouts, never to requests where the server returns a response. -max_retries = 10 - -#[proxy] -; This section is optional. Leave it out if you're not using a proxy. -; You can use environmental variables as well: http://www.python-requests.org/en/latest/user/advanced/#proxies - -; proxy_protocol set to https, if not specified. -#proxy_url = proxy.mycorp.com - -; proxy_port will override any port specified in proxy_url -#proxy_port = 8080 - -; proxy authentication -#proxy_username = proxyuser -#proxy_password = proxypass - -[report] -# Default template ID for CSVs -template_id = 126024 diff --git a/deps/qualysapi/qualysapi/config.py b/deps/qualysapi/qualysapi/config.py index a9666ea..51010e5 100644 --- a/deps/qualysapi/qualysapi/config.py +++ b/deps/qualysapi/qualysapi/config.py @@ -58,44 +58,44 @@ class QualysConnectConfig: self._cfgparse.read(self._cfgfile) # if 'info' doesn't exist, create the section. - if not self._cfgparse.has_section('info'): - self._cfgparse.add_section('info') + if not self._cfgparse.has_section('qualys'): + self._cfgparse.add_section('qualys') # Use default hostname (if one isn't provided). - if not self._cfgparse.has_option('info', 'hostname'): + if not self._cfgparse.has_option('qualys', 'hostname'): if self._cfgparse.has_option('DEFAULT', 'hostname'): hostname = self._cfgparse.get('DEFAULT', 'hostname') - self._cfgparse.set('info', 'hostname', hostname) + self._cfgparse.set('qualys', 'hostname', hostname) else: raise Exception("No 'hostname' set. QualysConnect does not know who to connect to.") # Use default max_retries (if one isn't provided). - if not self._cfgparse.has_option('info', 'max_retries'): + if not self._cfgparse.has_option('qualys', 'max_retries'): self.max_retries = qcs.defaults['max_retries'] else: - self.max_retries = self._cfgparse.get('info', 'max_retries') + self.max_retries = self._cfgparse.get('qualys', 'max_retries') try: self.max_retries = int(self.max_retries) except Exception: logger.error('Value max_retries must be an integer.') print('Value max_retries must be an integer.') exit(1) - self._cfgparse.set('info', 'max_retries', str(self.max_retries)) + self._cfgparse.set('qualys', 'max_retries', str(self.max_retries)) self.max_retries = int(self.max_retries) #Get template ID... user will need to set this to pull back CSV reports - if not self._cfgparse.has_option('report', 'template_id'): + if not self._cfgparse.has_option('qualys', 'template_id'): self.report_template_id = qcs.defaults['template_id'] else: - self.report_template_id = self._cfgparse.get('report', 'template_id') + self.report_template_id = self._cfgparse.get('qualys', 'template_id') try: self.report_template_id = int(self.report_template_id) except Exception: logger.error('Report Template ID Must be set and be an integer') print('Value template ID must be an integer.') exit(1) - self._cfgparse.set('report', 'template_id', str(self.max_retries)) - self.max_retries = int(self.max_retries) + self._cfgparse.set('qualys', 'template_id', str(self.report_template_id)) + self.report_template_id = int(self.report_template_id) # Proxy support proxy_config = proxy_url = proxy_protocol = proxy_port = proxy_username = proxy_password = None @@ -168,18 +168,18 @@ class QualysConnectConfig: self.proxies = None # ask username (if one doesn't exist) - if not self._cfgparse.has_option('info', 'username'): + if not self._cfgparse.has_option('qualys', 'username'): username = input('QualysGuard Username: ') - self._cfgparse.set('info', 'username', username) + self._cfgparse.set('qualys', 'username', username) # ask password (if one doesn't exist) - if not self._cfgparse.has_option('info', 'password'): + if not self._cfgparse.has_option('qualys', 'password'): password = getpass.getpass('QualysGuard Password: ') - self._cfgparse.set('info', 'password', password) + self._cfgparse.set('qualys', 'password', password) - logging.debug(self._cfgparse.items('info')) + logging.debug(self._cfgparse.items('qualys')) if remember_me or remember_me_always: # Let's create that config file for next time... @@ -211,8 +211,11 @@ class QualysConnectConfig: def get_auth(self): ''' Returns username from the configfile. ''' - return (self._cfgparse.get('info', 'username'), self._cfgparse.get('info', 'password')) + return (self._cfgparse.get('qualys', 'username'), self._cfgparse.get('qualys', 'password')) def get_hostname(self): ''' Returns hostname. ''' - return self._cfgparse.get('info', 'hostname') + return self._cfgparse.get('qualys', 'hostname') + + def get_template_id(self): + return self._cfgparse.get('qualys','template_id') diff --git a/deps/qualysapi/qualysapi/connector.py b/deps/qualysapi/qualysapi/connector.py index 6d5812a..1f30879 100644 --- a/deps/qualysapi/qualysapi/connector.py +++ b/deps/qualysapi/qualysapi/connector.py @@ -9,7 +9,12 @@ and requesting data from it. """ import logging import time -import urllib.parse + +try: + from urllib.parse import urlparse +except ImportError: + from urlparse import urlparse + from collections import defaultdict import requests @@ -154,7 +159,7 @@ class QGConnector(api_actions.QGActions): if api_call_endpoint in self.api_methods['was get']: return 'get' # Post calls with no payload will result in HTTPError: 415 Client Error: Unsupported Media Type. - if not data: + if data is None: # No post data. Some calls change to GET with no post data. if api_call_endpoint in self.api_methods['was no data get']: return 'get' @@ -215,7 +220,8 @@ class QGConnector(api_actions.QGActions): data = data.lstrip('?') data = data.rstrip('&') # Convert to dictionary. - data = urllib.parse.parse_qs(data) + #data = urllib.parse.parse_qs(data) + data = urlparse(data) logger.debug('Converted:\n%s' % str(data)) elif api_version in ('am', 'was', 'am2'): if type(data) == etree._Element: @@ -252,7 +258,7 @@ class QGConnector(api_actions.QGActions): url = self.url_api_version(api_version) # # Set up headers. - headers = {"X-Requested-With": "Parag Baxi QualysAPI (python) v%s" % (qualysapi.version.__version__,)} + headers = {"X-Requested-With": "QualysAPI (python) v%s - VulnWhisperer" % (qualysapi.version.__version__,)} logger.debug('headers =\n%s' % (str(headers))) # Portal API takes in XML text, requiring custom header. if api_version in ('am', 'was', 'am2'): diff --git a/deps/qualysapi/qualysapi/version.py b/deps/qualysapi/qualysapi/version.py index b22e775..ee162b6 100644 --- a/deps/qualysapi/qualysapi/version.py +++ b/deps/qualysapi/qualysapi/version.py @@ -1,3 +1,3 @@ -__author__ = 'Parag Baxi ' +__author__ = 'Austin Taylor' __pkgname__ = 'qualysapi' __version__ = '4.1.0' diff --git a/deps/qualysapi/setup.py b/deps/qualysapi/setup.py index 8eedb12..e16dd66 100644 --- a/deps/qualysapi/setup.py +++ b/deps/qualysapi/setup.py @@ -1,15 +1,15 @@ #!/usr/bin/env python - from __future__ import absolute_import import os -import sys +import setuptools + try: from setuptools import setup except ImportError: from distutils.core import setup -__author__ = 'Parag Baxi ' -__copyright__ = 'Copyright 2011-2013, Parag Baxi' +__author__ = 'Austin Taylor ' +__copyright__ = 'Copyright 2017, Austin Taylor' __license__ = 'BSD-new' # Make pyflakes happy. __pkgname__ = None @@ -27,14 +27,15 @@ def read(fname): setup(name=__pkgname__, version=__version__, - author='Parag Baxi', - author_email='parag.baxi@gmail.com', - description='QualysGuard(R) Qualys API Package', + author='Austin Taylor', + author_email='vulnWhisperer@austintaylor.io', + description='QualysGuard(R) Qualys API Package modified for VulnWhisperer', license='BSD-new', keywords='Qualys QualysGuard API helper network security', - url='https://github.com/paragbaxi/qualysapi', + url='https://github.com/austin-taylor/qualysapi', package_dir={'': '.'}, - packages=['qualysapi', ], + #packages=setuptools.find_packages(), + packages=['qualysapi',], # package_data={'qualysapi':['LICENSE']}, # scripts=['src/scripts/qhostinfo.py', 'src/scripts/qscanhist.py', 'src/scripts/qreports.py'], long_description=read('README.md'), diff --git a/docs/source/as_seen_on_tv.png b/docs/source/as_seen_on_tv.png new file mode 100644 index 0000000..d0c4d98 Binary files /dev/null and b/docs/source/as_seen_on_tv.png differ diff --git a/elasticsearch/logstash-nessus-template.json b/elasticsearch/logstash-nessus-template.json index 49212b4..14928ca 100755 --- a/elasticsearch/logstash-nessus-template.json +++ b/elasticsearch/logstash-nessus-template.json @@ -1,6 +1,6 @@ { "order": 0, - "template": "logstash-nessus-*", + "template": "logstash-vulnwhisperer-*", "settings": { "index": { "routing": { @@ -217,10 +217,11 @@ "type": "string" }, "port": { + "index": "not_analyzed", "type": "integer" }, "host": { - "type": "ip" + "type": "string" }, "@version": { "index": "not_analyzed", diff --git a/kibana/vuln_whisp_kibana/1000_vulnWhispererBaseVisuals.json b/kibana/vuln_whisp_kibana/1000_vulnWhispererBaseVisuals.json new file mode 100755 index 0000000..485894a --- /dev/null +++ b/kibana/vuln_whisp_kibana/1000_vulnWhispererBaseVisuals.json @@ -0,0 +1,450 @@ +[ + { + "_id": "80158c90-57c1-11e7-b484-a970fc9d150a", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - HIPAA TL", + "visState": "{\"type\":\"timelion\",\"title\":\"VulnWhisperer - HIPAA TL\",\"params\":{\"expression\":\".es(index=logstash-vulnwhisperer-*,q='risk_score:>9 AND tags:pci_asset').label(\\\"PCI Assets\\\"),.es(index=logstash-vulnwhisperer-*,q='risk_score:>9 AND tags:has_hipaa_data').label(\\\"Has HIPAA Data\\\"),.es(index=logstash-vulnwhisperer-*,q='risk_score:>9 AND tags:hipaa_asset').label(\\\"HIPAA Assets\\\")\",\"interval\":\"auto\"}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + } + } + }, + { + "_id": "479deab0-8a39-11e7-a58a-9bfcb3761a3d", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL - TaggedAssetsPluginNames", + "visState": "{\"title\":\"VulnWhisperer - TL - TaggedAssetsPluginNames\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*', q='tags:critical_asset OR tags:hipaa_asset OR tags:pci_asset', split=\\\"plugin_name.keyword:10\\\").bars(width=4).label(regex=\\\".*:(.+)>.*\\\",label=\\\"$1\\\")\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "84f5c370-8a38-11e7-a58a-9bfcb3761a3d", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL - CriticalAssetsPluginNames", + "visState": "{\"title\":\"VulnWhisperer - TL - CriticalAssetsPluginNames\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*', q='tags:critical_asset', split=\\\"plugin_name.keyword:10\\\").bars(width=4).label(regex=\\\".*:(.+)>.*\\\",label=\\\"$1\\\")\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "307cdae0-8a38-11e7-a58a-9bfcb3761a3d", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL - PluginNames", + "visState": "{\"title\":\"VulnWhisperer - TL - PluginNames\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*', split=\\\"plugin_name.keyword:25\\\").bars(width=4).label(regex=\\\".*:(.+)>.*\\\",label=\\\"$1\\\")\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "5093c620-44e9-11e7-8014-ede06a7e69f8", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Mitigation Readme", + "visState": "{\"title\":\"VulnWhisperer - Mitigation Readme\",\"type\":\"markdown\",\"params\":{\"markdown\":\"** Legend **\\n\\n* [Common Vulnerability Scoring System (CVSS)](https://nvd.nist.gov/vuln-metrics/cvss) is the NIST vulnerability scoring system\\n* Risk Number is residual risk score calculated from CVSS, which is adjusted to be specific to Heartland which accounts for services not in use such as Java and Flash\\n* Vulnerabilities by Tag are systems tagged with HIPAA and PCI identification.\\n\\n\\n** Workflow **\\n* Select 10.0 under Risk Number to identify Critical Vulnerabilities. \\n* For more information about a CVE, scroll down and click the CVE link.\\n* To filter by tags, use one of the following filters:\\n** tags:has_hipaa_data, tags:pci_asset, tags:hipaa_asset, tags:critical_asset**\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "7e7fbc90-3df2-11e7-a44e-c79ca8efb780", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-PluginID", + "visState": "{\"title\":\"VulnWhisperer-PluginID\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"plugin_id\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "5a3c0340-3eb3-11e7-a192-93f36fbd9d05", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-CVSSHeatmap", + "visState": "{\"title\":\"VulnWhisperer-CVSSHeatmap\",\"type\":\"heatmap\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Yellow to Red\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"color\":\"#555\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"host\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"cvss\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"_term\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 3500\":\"rgb(255,255,204)\",\"3500 - 7000\":\"rgb(254,217,118)\",\"7000 - 10500\":\"rgb(253,141,60)\",\"10500 - 14000\":\"rgb(227,27,28)\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "1de9e550-3df1-11e7-a44e-c79ca8efb780", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-Description", + "visState": "{\"title\":\"VulnWhisperer-Description\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"description.keyword\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Description\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "13c7d4e0-3df3-11e7-a44e-c79ca8efb780", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-Solution", + "visState": "{\"title\":\"VulnWhisperer-Solution\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"solution.keyword\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Solution\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "297df800-3f7e-11e7-bd24-6903e3283192", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Plugin Name", + "visState": "{\"title\":\"VulnWhisperer - Plugin Name\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"plugin_name.keyword\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Plugin Name\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "de1a5f40-3f85-11e7-97f9-3777d794626d", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - ScanName", + "visState": "{\"title\":\"VulnWhisperer - ScanName\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"plugin_name.keyword\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Scan Name\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "ecbb99c0-3f84-11e7-97f9-3777d794626d", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Total", + "visState": "{\"title\":\"VulnWhisperer - Total\",\"type\":\"metric\",\"params\":{\"handleNoResults\":true,\"fontSize\":60},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Total\"}}],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "471a3580-3f6b-11e7-88e7-df1abe6547fb", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Vulnerabilities by Tag", + "visState": "{\"title\":\"VulnWhisperer - Vulnerabilities by Tag\",\"type\":\"table\",\"params\":{\"perPage\":3,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"bucket\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"tags:has_hipaa_data\",\"analyze_wildcard\":true}}},\"label\":\"Systems with HIPAA data\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"tags:pci_asset\",\"analyze_wildcard\":true}}},\"label\":\"PCI Systems\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"tags:hipaa_asset\",\"analyze_wildcard\":true}}},\"label\":\"HIPAA Systems\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "35b6d320-3f7f-11e7-bd24-6903e3283192", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Residual Risk", + "visState": "{\"title\":\"VulnWhisperer - Residual Risk\",\"type\":\"table\",\"params\":{\"perPage\":15,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"risk_score\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Risk Number\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "a9225930-3df2-11e7-a44e-c79ca8efb780", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-Risk", + "visState": "{\"title\":\"VulnWhisperer-Risk\",\"type\":\"table\",\"params\":{\"perPage\":4,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"risk\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Risk Severity\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "2f979030-44b9-11e7-a818-f5f80dfc3590", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - ScanBarChart", + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customLabel\":\"Scan Name\",\"field\":\"plugin_name.keyword\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":10},\"schema\":\"segment\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"legendPosition\":\"right\",\"mode\":\"stacked\",\"scale\":\"linear\",\"setYExtents\":false,\"times\":[]},\"title\":\"VulnWhisperer - ScanBarChart\",\"type\":\"histogram\"}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "a6508640-897a-11e7-bbc0-33592ce0be1e", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Critical Assets Aggregated", + "visState": "{\"title\":\"VulnWhisperer - Critical Assets Aggregated\",\"type\":\"heatmap\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"enableHover\":true,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Green to Red\",\"setColorRange\":true,\"colorsRange\":[{\"from\":0,\"to\":3},{\"from\":3,\"to\":7},{\"from\":7,\"to\":9},{\"from\":9,\"to\":11}],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":true,\"rotate\":0,\"color\":\"white\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"risk_score\",\"customLabel\":\"Residual Risk Score\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Date\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"host\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Critical Asset IP\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"plugin_name.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":true}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"colors\":{\"0 - 3\":\"#7EB26D\",\"3 - 7\":\"#EAB839\",\"7 - 9\":\"#EF843C\",\"8 - 10\":\"#BF1B00\",\"9 - 11\":\"#BF1B00\"},\"defaultColors\":{\"0 - 3\":\"rgb(0,104,55)\",\"3 - 7\":\"rgb(135,203,103)\",\"7 - 9\":\"rgb(255,255,190)\",\"9 - 11\":\"rgb(249,142,82)\"},\"legendOpen\":false}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":\"Critical Asset\",\"disabled\":false,\"index\":\"logstash-vulnwhisperer-*\",\"key\":\"tags\",\"negate\":false,\"type\":\"phrase\",\"value\":\"critical_asset\"},\"query\":{\"match\":{\"tags\":{\"query\":\"critical_asset\",\"type\":\"phrase\"}}}}]}" + } + } + }, + { + "_id": "099a3820-3f68-11e7-a6bd-e764d950e506", + "_type": "visualization", + "_source": { + "title": "Timelion VulnWhisperer Example", + "visState": "{\"type\":\"timelion\",\"title\":\"Timelion VulnWhisperer Example\",\"params\":{\"expression\":\".es(index=logstash-vulnwhisperer-*,q=risk:high).label(\\\"Current High Risk\\\"),.es(index=logstash-vulnwhisperer-*,q=risk:high,offset=-1y).label(\\\"Last 1 Year High Risk\\\"),.es(index=logstash-vulnwhisperer-*,q=risk:medium).label(\\\"Current Medium Risk\\\"),.es(index=logstash-vulnwhisperer-*,q=risk:medium,offset=-1y).label(\\\"Last 1 Year Medium Risk\\\")\",\"interval\":\"auto\"}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + } + } + }, + { + "_id": "67d432e0-44ec-11e7-a05f-d9719b331a27", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL-Critical Risk", + "visState": "{\"title\":\"VulnWhisperer - TL-Critical Risk\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*',q='(risk_score:>=9 AND risk_score:<=10)').label(\\\"Original\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=9 AND risk_score:<=10)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=9 AND risk_score:<=10)').subtract(.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=9 AND risk_score:<=10)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "a91b9fe0-44ec-11e7-a05f-d9719b331a27", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL-Medium Risk", + "visState": "{\"title\":\"VulnWhisperer - TL-Medium Risk\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*',q='(risk_score:>=4 AND risk_score:<7)').label(\\\"Original\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=4 AND risk_score:<7)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=4 AND risk_score:<7)').subtract(.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=4 AND risk_score:<7)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "8d9592d0-44ec-11e7-a05f-d9719b331a27", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL-High Risk", + "visState": "{\"title\":\"VulnWhisperer - TL-High Risk\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*',q='(risk_score:>=7 AND risk_score:<9)').label(\\\"Original\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=7 AND risk_score:<9)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=7 AND risk_score:<9)').subtract(.es(index='logstash-vulnwhisperer-*',q='(risk_score:>=7 AND risk_score:<9)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "a2d66660-44ec-11e7-a05f-d9719b331a27", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL-Low Risk", + "visState": "{\"title\":\"VulnWhisperer - TL-Low Risk\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*',q='(risk_score:>0 AND risk_score:<4)').label(\\\"Original\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk_score:>0 AND risk_score:<4)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk_score:>0 AND risk_score:<4)').subtract(.es(index='logstash-vulnwhisperer-*',q='(risk_score:>0 AND risk_score:<4)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "fb6eb020-49ab-11e7-8f8c-57ad64ec48a6", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Critical Risk Score for Tagged Assets", + "visState": "{\"title\":\"VulnWhisperer - Critical Risk Score for Tagged Assets\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=logstash-vulnwhisperer-*,q='risk_score:>9 AND tags:hipaa_asset').label(\\\"HIPAA Assets\\\"),.es(index=logstash-vulnwhisperer-*,q='risk_score:>9 AND tags:pci_asset').label(\\\"PCI Systems\\\"),.es(index=logstash-vulnwhisperer-*,q='risk_score:>9 AND tags:has_hipaa_data').label(\\\"Has HIPAA Data\\\")\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "b2f2adb0-897f-11e7-a2d2-c57bca21b3aa", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: Total", + "visState": "{\"title\":\"VulnWhisperer - Risk: Total\",\"type\":\"goal\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"gaugeColorMode\":\"Background\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":false},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":true,\"width\":2},\"style\":{\"bgColor\":true,\"bgFill\":\"white\",\"fontSize\":\"34\",\"labelColor\":false,\"subText\":\"Risk\"},\"type\":\"simple\",\"useRanges\":false,\"verticalSplit\":false},\"type\":\"gauge\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Total\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}}},\"label\":\"Critical\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"colors\":{\"0 - 10000\":\"#64B0C8\"},\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "465c5820-8977-11e7-857e-e1d56b17746d", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Critical Assets", + "visState": "{\"title\":\"VulnWhisperer - Critical Assets\",\"type\":\"heatmap\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"enableHover\":true,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Green to Red\",\"setColorRange\":true,\"colorsRange\":[{\"from\":0,\"to\":3},{\"from\":3,\"to\":7},{\"from\":7,\"to\":9},{\"from\":9,\"to\":11}],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":true,\"rotate\":0,\"color\":\"white\"}}],\"type\":\"heatmap\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"risk_score\",\"customLabel\":\"Residual Risk Score\"}},{\"id\":\"2\",\"enabled\":false,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"risk_score\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":true}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Date\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"asset.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Critical Asset\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 3\":\"rgb(0,104,55)\",\"3 - 7\":\"rgb(135,203,103)\",\"7 - 9\":\"rgb(255,255,190)\",\"9 - 11\":\"rgb(249,142,82)\"},\"colors\":{\"8 - 10\":\"#BF1B00\",\"9 - 11\":\"#BF1B00\",\"7 - 9\":\"#EF843C\",\"3 - 7\":\"#EAB839\",\"0 - 3\":\"#7EB26D\"},\"legendOpen\":false}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[{\"meta\":{\"index\":\"logstash-vulnwhisperer-*\",\"negate\":false,\"disabled\":false,\"alias\":\"Critical Asset\",\"type\":\"phrase\",\"key\":\"tags\",\"value\":\"critical_asset\"},\"query\":{\"match\":{\"tags\":{\"query\":\"critical_asset\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" + } + } + }, + { + "_id": "852816e0-3eb1-11e7-90cb-918f9cb01e3d", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-CVSS", + "visState": "{\"title\":\"VulnWhisperer-CVSS\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\",\"type\":\"table\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"cvss\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"CVSS Score\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"asset.keyword\",\"customLabel\":\"# of Assets\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "d048c220-80b3-11e7-8790-73b60225f736", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: High", + "visState": "{\"title\":\"VulnWhisperer - Risk: High\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":1000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":true}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"High Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score_name:high\"}}},\"label\":\"\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#EF843C\",\"0 - 1000\":\"#E0752D\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "db55bce0-80b3-11e7-8790-73b60225f736", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: Critical", + "visState": "{\"title\":\"VulnWhisperer - Risk: Critical\",\"type\":\"goal\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"gaugeColorMode\":\"Background\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":false},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":true,\"width\":2},\"style\":{\"bgColor\":true,\"bgFill\":\"white\",\"fontSize\":\"34\",\"labelColor\":false,\"subText\":\"Risk\"},\"type\":\"simple\",\"useRanges\":false,\"verticalSplit\":false},\"type\":\"gauge\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Critical Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score_name:critical\"}}},\"label\":\"Critical\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"colors\":{\"0 - 10000\":\"#BF1B00\"},\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "56f0f5f0-3ebe-11e7-a192-93f36fbd9d05", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-RiskOverTime", + "visState": "{\"title\":\"VulnWhisperer-RiskOverTime\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"@timestamp per 12 hours\"},\"type\":\"category\"}],\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"},\"valueAxis\":\"ValueAxis-1\"},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"orderBucketsBySum\":false,\"radiusRatio\":9,\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"mode\":\"normal\",\"show\":\"true\",\"showCircles\":true,\"type\":\"line\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"showCircles\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}],\"type\":\"line\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score_name:info\"}}},\"label\":\"Info\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score_name:low\"}}},\"label\":\"Low\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score_name:medium\"}}},\"label\":\"Medium\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score_name:high\"}}},\"label\":\"High\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score_name:critical\"}}},\"label\":\"Critical\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"colors\":{\"Critical\":\"#962D82\",\"High\":\"#BF1B00\",\"Low\":\"#629E51\",\"Medium\":\"#EAB839\",\"Info\":\"#65C5DB\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "c1361da0-80b3-11e7-8790-73b60225f736", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: Medium", + "visState": "{\"title\":\"VulnWhisperer - Risk: Medium\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":false}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Medium Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score:medium\"}}},\"label\":\"Medium Risk\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#EAB839\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "e46ff7f0-897d-11e7-934b-67cec0a7da65", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: Low", + "visState": "{\"title\":\"VulnWhisperer - Risk: Low\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":false}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Low Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk_score_name:low\"}}},\"label\":\"Low Risk\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#629E51\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "995e2280-3df3-11e7-a44e-c79ca8efb780", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-Asset", + "visState": "{\"title\":\"VulnWhisperer-Asset\",\"type\":\"table\",\"params\":{\"perPage\":15,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\",\"type\":\"table\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"asset.keyword\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Asset\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + } +] \ No newline at end of file diff --git a/kibana/vuln_whisp_kibana/vuln_whisperer_kibana_dashboard.json b/kibana/vuln_whisp_kibana/1001_vulnWhisperer_ReportingMitigationDashboard.json similarity index 53% rename from kibana/vuln_whisp_kibana/vuln_whisperer_kibana_dashboard.json rename to kibana/vuln_whisp_kibana/1001_vulnWhisperer_ReportingMitigationDashboard.json index bf9bb80..1c38611 100755 --- a/kibana/vuln_whisp_kibana/vuln_whisperer_kibana_dashboard.json +++ b/kibana/vuln_whisp_kibana/1001_vulnWhisperer_ReportingMitigationDashboard.json @@ -1,41 +1,41 @@ [ - { - "_id": "5dba30c0-3df3-11e7-a44e-c79ca8efb780", - "_type": "dashboard", - "_source": { - "title": "Nessus - Risk Mitigation", - "hits": 0, - "description": "", - "panelsJSON": "[{\"col\":11,\"id\":\"995e2280-3df3-11e7-a44e-c79ca8efb780\",\"panelIndex\":20,\"row\":7,\"size_x\":2,\"size_y\":6,\"type\":\"visualization\"},{\"col\":1,\"id\":\"852816e0-3eb1-11e7-90cb-918f9cb01e3d\",\"panelIndex\":21,\"row\":8,\"size_x\":3,\"size_y\":5,\"type\":\"visualization\"},{\"col\":4,\"id\":\"297df800-3f7e-11e7-bd24-6903e3283192\",\"panelIndex\":27,\"row\":8,\"size_x\":3,\"size_y\":5,\"type\":\"visualization\"},{\"col\":9,\"id\":\"35b6d320-3f7f-11e7-bd24-6903e3283192\",\"panelIndex\":28,\"row\":7,\"size_x\":2,\"size_y\":6,\"type\":\"visualization\"},{\"col\":1,\"id\":\"471a3580-3f6b-11e7-88e7-df1abe6547fb\",\"panelIndex\":30,\"row\":4,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":7,\"id\":\"de1a5f40-3f85-11e7-97f9-3777d794626d\",\"panelIndex\":31,\"row\":8,\"size_x\":2,\"size_y\":5,\"type\":\"visualization\"},{\"col\":9,\"id\":\"5093c620-44e9-11e7-8014-ede06a7e69f8\",\"panelIndex\":37,\"row\":4,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"host\",\"risk\",\"risk_score\",\"cve\",\"plugin_name\",\"solution\",\"plugin_output\"],\"id\":\"54648700-3f74-11e7-852e-69207a3d0726\",\"panelIndex\":38,\"row\":13,\"size_x\":12,\"size_y\":6,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":1,\"id\":\"fb6eb020-49ab-11e7-8f8c-57ad64ec48a6\",\"panelIndex\":39,\"row\":6,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":4,\"id\":\"465c5820-8977-11e7-857e-e1d56b17746d\",\"panelIndex\":40,\"row\":4,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"db55bce0-80b3-11e7-8790-73b60225f736\",\"panelIndex\":41,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"e46ff7f0-897d-11e7-934b-67cec0a7da65\",\"panelIndex\":42,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"d048c220-80b3-11e7-8790-73b60225f736\",\"panelIndex\":43,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":3,\"id\":\"c1361da0-80b3-11e7-8790-73b60225f736\",\"panelIndex\":44,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"b2f2adb0-897f-11e7-a2d2-c57bca21b3aa\",\"panelIndex\":45,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"size_x\":2,\"size_y\":3,\"panelIndex\":46,\"type\":\"visualization\",\"id\":\"56f0f5f0-3ebe-11e7-a192-93f36fbd9d05\",\"col\":11,\"row\":1}]", - "optionsJSON": "{\"darkTheme\":false}", - "uiStateJSON": "{\"P-11\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-20\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-21\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}},\"P-27\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-28\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}},\"P-3\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"asc\"}}}},\"P-30\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-31\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-40\":{\"vis\":{\"defaultColors\":{\"0 - 3\":\"rgb(0,104,55)\",\"3 - 7\":\"rgb(135,203,103)\",\"7 - 9\":\"rgb(255,255,190)\",\"9 - 11\":\"rgb(249,142,82)\"}}},\"P-41\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-42\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-43\":{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-44\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-6\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-8\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-45\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-46\":{\"vis\":{\"legendOpen\":false}}}", - "version": 1, - "timeRestore": true, - "timeTo": "now", - "timeFrom": "now-30d", - "refreshInterval": { - "display": "Off", - "pause": false, - "value": 0 - }, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" - } - } - }, { "_id": "72051530-448e-11e7-a818-f5f80dfc3590", "_type": "dashboard", "_source": { - "title": "Nessus - Reporting", + "title": "VulnWhisperer - Reporting", "hits": 0, "description": "", - "panelsJSON": "[{\"col\":1,\"id\":\"2f979030-44b9-11e7-a818-f5f80dfc3590\",\"panelIndex\":5,\"row\":12,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"8d9592d0-44ec-11e7-a05f-d9719b331a27\",\"panelIndex\":12,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"67d432e0-44ec-11e7-a05f-d9719b331a27\",\"panelIndex\":14,\"row\":4,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":10,\"id\":\"297df800-3f7e-11e7-bd24-6903e3283192\",\"panelIndex\":15,\"row\":8,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"471a3580-3f6b-11e7-88e7-df1abe6547fb\",\"panelIndex\":20,\"row\":8,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":11,\"id\":\"995e2280-3df3-11e7-a44e-c79ca8efb780\",\"panelIndex\":22,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"b2f2adb0-897f-11e7-a2d2-c57bca21b3aa\",\"panelIndex\":23,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"db55bce0-80b3-11e7-8790-73b60225f736\",\"panelIndex\":25,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"d048c220-80b3-11e7-8790-73b60225f736\",\"panelIndex\":26,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"e46ff7f0-897d-11e7-934b-67cec0a7da65\",\"panelIndex\":27,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":3,\"id\":\"c1361da0-80b3-11e7-8790-73b60225f736\",\"panelIndex\":28,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"size_x\":6,\"size_y\":4,\"panelIndex\":29,\"type\":\"visualization\",\"id\":\"479deab0-8a39-11e7-a58a-9bfcb3761a3d\",\"col\":1,\"row\":4}]", + "panelsJSON": "[{\"col\":1,\"id\":\"2f979030-44b9-11e7-a818-f5f80dfc3590\",\"panelIndex\":5,\"row\":12,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"8d9592d0-44ec-11e7-a05f-d9719b331a27\",\"panelIndex\":12,\"row\":8,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"67d432e0-44ec-11e7-a05f-d9719b331a27\",\"panelIndex\":14,\"row\":4,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":10,\"id\":\"297df800-3f7e-11e7-bd24-6903e3283192\",\"panelIndex\":15,\"row\":8,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"471a3580-3f6b-11e7-88e7-df1abe6547fb\",\"panelIndex\":20,\"row\":8,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":11,\"id\":\"995e2280-3df3-11e7-a44e-c79ca8efb780\",\"panelIndex\":22,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"b2f2adb0-897f-11e7-a2d2-c57bca21b3aa\",\"panelIndex\":23,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"db55bce0-80b3-11e7-8790-73b60225f736\",\"panelIndex\":25,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"d048c220-80b3-11e7-8790-73b60225f736\",\"panelIndex\":26,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"e46ff7f0-897d-11e7-934b-67cec0a7da65\",\"panelIndex\":27,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":3,\"id\":\"c1361da0-80b3-11e7-8790-73b60225f736\",\"panelIndex\":28,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"479deab0-8a39-11e7-a58a-9bfcb3761a3d\",\"panelIndex\":29,\"row\":4,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"}]", "optionsJSON": "{\"darkTheme\":false}", "uiStateJSON": "{\"P-15\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-20\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-21\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}},\"P-22\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-23\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-24\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-25\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-26\":{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-27\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-28\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-5\":{\"vis\":{\"legendOpen\":false}}}", "version": 1, "timeRestore": true, "timeTo": "now", + "timeFrom": "now-1y", + "refreshInterval": { + "display": "Off", + "pause": false, + "value": 0 + }, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"-vulnerability_category:\\\"INFORMATION_GATHERED\\\"\"}}}],\"highlightAll\":true,\"version\":true}" + } + } + }, + { + "_id": "AWCUqesWib22Ai8JwW3u", + "_type": "dashboard", + "_source": { + "title": "VulnWhisperer - Risk Mitigation", + "hits": 0, + "description": "", + "panelsJSON": "[{\"col\":11,\"id\":\"995e2280-3df3-11e7-a44e-c79ca8efb780\",\"panelIndex\":20,\"row\":8,\"size_x\":2,\"size_y\":6,\"type\":\"visualization\"},{\"col\":1,\"id\":\"852816e0-3eb1-11e7-90cb-918f9cb01e3d\",\"panelIndex\":21,\"row\":10,\"size_x\":3,\"size_y\":5,\"type\":\"visualization\"},{\"col\":4,\"id\":\"297df800-3f7e-11e7-bd24-6903e3283192\",\"panelIndex\":27,\"row\":8,\"size_x\":3,\"size_y\":5,\"type\":\"visualization\"},{\"col\":9,\"id\":\"35b6d320-3f7f-11e7-bd24-6903e3283192\",\"panelIndex\":28,\"row\":8,\"size_x\":2,\"size_y\":6,\"type\":\"visualization\"},{\"col\":11,\"id\":\"471a3580-3f6b-11e7-88e7-df1abe6547fb\",\"panelIndex\":30,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"de1a5f40-3f85-11e7-97f9-3777d794626d\",\"panelIndex\":31,\"row\":8,\"size_x\":2,\"size_y\":5,\"type\":\"visualization\"},{\"col\":10,\"id\":\"5093c620-44e9-11e7-8014-ede06a7e69f8\",\"panelIndex\":37,\"row\":4,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"host\",\"risk\",\"risk_score\",\"cve\",\"plugin_name\",\"solution\",\"plugin_output\"],\"id\":\"54648700-3f74-11e7-852e-69207a3d0726\",\"panelIndex\":38,\"row\":15,\"size_x\":12,\"size_y\":6,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":1,\"id\":\"fb6eb020-49ab-11e7-8f8c-57ad64ec48a6\",\"panelIndex\":39,\"row\":8,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":5,\"id\":\"465c5820-8977-11e7-857e-e1d56b17746d\",\"panelIndex\":40,\"row\":4,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"56f0f5f0-3ebe-11e7-a192-93f36fbd9d05\",\"panelIndex\":46,\"row\":4,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"id\":\"e46ff7f0-897d-11e7-934b-67cec0a7da65\",\"panelIndex\":47,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":3,\"id\":\"c1361da0-80b3-11e7-8790-73b60225f736\",\"panelIndex\":48,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"d048c220-80b3-11e7-8790-73b60225f736\",\"panelIndex\":49,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"db55bce0-80b3-11e7-8790-73b60225f736\",\"panelIndex\":50,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"b2f2adb0-897f-11e7-a2d2-c57bca21b3aa\",\"panelIndex\":51,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"}]", + "optionsJSON": "{\"darkTheme\":false}", + "uiStateJSON": "{\"P-11\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-20\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-21\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}},\"P-27\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-28\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}},\"P-3\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"asc\"}}}},\"P-30\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-31\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-40\":{\"vis\":{\"defaultColors\":{\"0 - 3\":\"rgb(0,104,55)\",\"3 - 7\":\"rgb(135,203,103)\",\"7 - 9\":\"rgb(255,255,190)\",\"9 - 11\":\"rgb(249,142,82)\"}}},\"P-41\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-42\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-43\":{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"}}},\"P-44\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-45\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-46\":{\"vis\":{\"legendOpen\":true}},\"P-47\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-48\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-49\":{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-50\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-51\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-6\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-8\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "version": 1, + "timeRestore": true, + "timeTo": "now", "timeFrom": "now-30d", "refreshInterval": { "display": "Off", @@ -43,7 +43,7 @@ "value": 0 }, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}],\"highlightAll\":true,\"version\":true}" + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"-vulnerability_category:\\\"INFORMATION_GATHERED\\\"\"}}}],\"highlightAll\":true,\"version\":true}" } } } diff --git a/kibana/vuln_whisp_kibana/2000_vulnWhisperer_QualysVisuals (required with Dashboard).json b/kibana/vuln_whisp_kibana/2000_vulnWhisperer_QualysVisuals (required with Dashboard).json new file mode 100755 index 0000000..b55fe40 --- /dev/null +++ b/kibana/vuln_whisp_kibana/2000_vulnWhisperer_QualysVisuals (required with Dashboard).json @@ -0,0 +1,170 @@ +[ + { + "_id": "AWCUo-jRib22Ai8JwW1N", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: High Qualys Scoring", + "visState": "{\"title\":\"VulnWhisperer - Risk: High Qualys Scoring\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":1000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":true}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"High Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:high\"}}},\"label\":\"\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#EF843C\",\"0 - 1000\":\"#E0752D\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCUozGBib22Ai8JwW1B", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: Medium Qualys Scoring", + "visState": "{\"title\":\"VulnWhisperer - Risk: Medium Qualys Scoring\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":false}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Medium Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:medium\"}}},\"label\":\"Medium Risk\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#EAB839\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCUpE3Kib22Ai8JwW1c", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: Critical Qualys Scoring", + "visState": "{\"title\":\"VulnWhisperer - Risk: Critical Qualys Scoring\",\"type\":\"goal\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"gaugeColorMode\":\"Background\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":false},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":true,\"width\":2},\"style\":{\"bgColor\":true,\"bgFill\":\"white\",\"fontSize\":\"34\",\"labelColor\":false,\"subText\":\"Risk\"},\"type\":\"simple\",\"useRanges\":false,\"verticalSplit\":false},\"type\":\"gauge\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Critical Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:critical\"}}},\"label\":\"Critical\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"colors\":{\"0 - 10000\":\"#BF1B00\"},\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCUyeHGib22Ai8JwX62", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer-RiskOverTime Qualys Scoring", + "visState": "{\"title\":\"VulnWhisperer-RiskOverTime Qualys Scoring\",\"type\":\"line\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"@timestamp per 12 hours\"},\"type\":\"category\"}],\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"},\"valueAxis\":\"ValueAxis-1\"},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"orderBucketsBySum\":false,\"radiusRatio\":9,\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"mode\":\"normal\",\"show\":\"true\",\"showCircles\":true,\"type\":\"line\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"showCircles\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}],\"type\":\"line\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:info\"}}},\"label\":\"Info\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:low\"}}},\"label\":\"Low\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:medium\"}}},\"label\":\"Medium\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:high\"}}},\"label\":\"High\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:critical\"}}},\"label\":\"Critical\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"colors\":{\"Critical\":\"#962D82\",\"High\":\"#BF1B00\",\"Low\":\"#629E51\",\"Medium\":\"#EAB839\",\"Info\":\"#65C5DB\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCUos-Fib22Ai8JwW0y", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Risk: Low Qualys Scoring", + "visState": "{\"title\":\"VulnWhisperer - Risk: Low Qualys Scoring\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":false}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Low Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:low\"}}},\"label\":\"Low Risk\"}]}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#629E51\"}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCg9Wsfib22Ai8Jww3v", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Qualys: Category Description", + "visState": "{\"title\":\"VulnWhisperer - Qualys: Category Description\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"type\":\"table\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"category_description.keyword\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Category Description\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"match_all\":{}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCg88f1ib22Ai8Jww3C", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - QualysOS", + "visState": "{\"title\":\"VulnWhisperer - QualysOS\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"type\":\"table\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"operating_system.keyword\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"match_all\":{}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCg9JUAib22Ai8Jww3Y", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - QualysOwner", + "visState": "{\"title\":\"VulnWhisperer - QualysOwner\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"type\":\"table\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"owner.keyword\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"match_all\":{}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCg9tE6ib22Ai8Jww4R", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Qualys: Impact", + "visState": "{\"title\":\"VulnWhisperer - Qualys: Impact\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"type\":\"table\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"impact.keyword\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Impact\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"match_all\":{}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCg9igvib22Ai8Jww36", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - Qualys: Level", + "visState": "{\"title\":\"VulnWhisperer - Qualys: Level\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"type\":\"table\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"level.keyword\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Level\"}}],\"listeners\":{}}", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"match_all\":{}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCUsp_3ib22Ai8JwW7R", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL-Critical Risk Qualys Scoring", + "visState": "{\"title\":\"VulnWhisperer - TL-Critical Risk Qualys Scoring\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*',q='(risk:critical)').label(\\\"Original\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk:critical)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk:critical)').subtract(.es(index='logstash-vulnwhisperer-*',q='(risk:critical)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\",\"type\":\"timelion\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + }, + { + "_id": "AWCUtHETib22Ai8JwW79", + "_type": "visualization", + "_source": { + "title": "VulnWhisperer - TL-High Risk Qualys Scoring", + "visState": "{\"title\":\"VulnWhisperer - TL-High Risk Qualys Scoring\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-vulnwhisperer-*',q='(risk:high)').label(\\\"Original\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk:high)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-vulnwhisperer-*',q='(risk:high)').subtract(.es(index='logstash-vulnwhisperer-*',q='(risk:high)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\",\"type\":\"timelion\"},\"aggs\":[],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + } + } +] \ No newline at end of file diff --git a/kibana/vuln_whisp_kibana/2001_vulnWhisperer_ReportingMitigationDashboardQualysRisk.json b/kibana/vuln_whisp_kibana/2001_vulnWhisperer_ReportingMitigationDashboardQualysRisk.json new file mode 100755 index 0000000..06bbc0b --- /dev/null +++ b/kibana/vuln_whisp_kibana/2001_vulnWhisperer_ReportingMitigationDashboardQualysRisk.json @@ -0,0 +1,50 @@ +[ + { + "_id": "AWCUrIBqib22Ai8JwW43", + "_type": "dashboard", + "_source": { + "title": "VulnWhisperer - Reporting Qualys Scoring", + "hits": 0, + "description": "", + "panelsJSON": "[{\"col\":1,\"id\":\"2f979030-44b9-11e7-a818-f5f80dfc3590\",\"panelIndex\":5,\"row\":11,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"col\":10,\"id\":\"297df800-3f7e-11e7-bd24-6903e3283192\",\"panelIndex\":15,\"row\":7,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":7,\"id\":\"471a3580-3f6b-11e7-88e7-df1abe6547fb\",\"panelIndex\":20,\"row\":7,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":11,\"id\":\"995e2280-3df3-11e7-a44e-c79ca8efb780\",\"panelIndex\":22,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":9,\"id\":\"b2f2adb0-897f-11e7-a2d2-c57bca21b3aa\",\"panelIndex\":23,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"479deab0-8a39-11e7-a58a-9bfcb3761a3d\",\"panelIndex\":29,\"row\":4,\"size_x\":6,\"size_y\":4,\"type\":\"visualization\"},{\"size_x\":6,\"size_y\":3,\"panelIndex\":30,\"type\":\"visualization\",\"id\":\"AWCUtHETib22Ai8JwW79\",\"col\":1,\"row\":8},{\"size_x\":6,\"size_y\":3,\"panelIndex\":31,\"type\":\"visualization\",\"id\":\"AWCUsp_3ib22Ai8JwW7R\",\"col\":7,\"row\":4},{\"size_x\":2,\"size_y\":3,\"panelIndex\":33,\"type\":\"visualization\",\"id\":\"AWCUozGBib22Ai8JwW1B\",\"col\":3,\"row\":1},{\"size_x\":2,\"size_y\":3,\"panelIndex\":34,\"type\":\"visualization\",\"id\":\"AWCUo-jRib22Ai8JwW1N\",\"col\":5,\"row\":1},{\"size_x\":2,\"size_y\":3,\"panelIndex\":35,\"type\":\"visualization\",\"id\":\"AWCUpE3Kib22Ai8JwW1c\",\"col\":7,\"row\":1},{\"size_x\":2,\"size_y\":3,\"panelIndex\":36,\"type\":\"visualization\",\"id\":\"AWCUos-Fib22Ai8JwW0y\",\"col\":1,\"row\":1}]", + "optionsJSON": "{\"darkTheme\":false}", + "uiStateJSON": "{\"P-15\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-20\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-21\":{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}},\"P-22\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-23\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-24\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-5\":{\"vis\":{\"legendOpen\":false}},\"P-33\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-34\":{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-35\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-27\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-28\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-26\":{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"}}},\"P-25\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-32\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-36\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}}}", + "version": 1, + "timeRestore": true, + "timeTo": "now", + "timeFrom": "now-30d", + "refreshInterval": { + "display": "Off", + "pause": false, + "value": 0 + }, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"-vulnerability_category:\\\"INFORMATION_GATHERED\\\"\"}}}],\"highlightAll\":true,\"version\":true}" + } + } + }, + { + "_id": "5dba30c0-3df3-11e7-a44e-c79ca8efb780", + "_type": "dashboard", + "_source": { + "title": "VulnWhisperer - Risk Mitigation Qualys Web Scoring", + "hits": 0, + "description": "", + "panelsJSON": "[{\"col\":11,\"id\":\"995e2280-3df3-11e7-a44e-c79ca8efb780\",\"panelIndex\":20,\"row\":8,\"size_x\":2,\"size_y\":7,\"type\":\"visualization\"},{\"col\":1,\"id\":\"852816e0-3eb1-11e7-90cb-918f9cb01e3d\",\"panelIndex\":21,\"row\":10,\"size_x\":3,\"size_y\":5,\"type\":\"visualization\"},{\"col\":4,\"id\":\"297df800-3f7e-11e7-bd24-6903e3283192\",\"panelIndex\":27,\"row\":8,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"35b6d320-3f7f-11e7-bd24-6903e3283192\",\"panelIndex\":28,\"row\":8,\"size_x\":2,\"size_y\":7,\"type\":\"visualization\"},{\"col\":11,\"id\":\"471a3580-3f6b-11e7-88e7-df1abe6547fb\",\"panelIndex\":30,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"de1a5f40-3f85-11e7-97f9-3777d794626d\",\"panelIndex\":31,\"row\":8,\"size_x\":2,\"size_y\":4,\"type\":\"visualization\"},{\"col\":10,\"id\":\"5093c620-44e9-11e7-8014-ede06a7e69f8\",\"panelIndex\":37,\"row\":4,\"size_x\":3,\"size_y\":4,\"type\":\"visualization\"},{\"col\":1,\"columns\":[\"host\",\"risk\",\"risk_score\",\"cve\",\"plugin_name\",\"solution\",\"plugin_output\"],\"id\":\"54648700-3f74-11e7-852e-69207a3d0726\",\"panelIndex\":38,\"row\":15,\"size_x\":12,\"size_y\":6,\"sort\":[\"@timestamp\",\"desc\"],\"type\":\"search\"},{\"col\":1,\"id\":\"fb6eb020-49ab-11e7-8f8c-57ad64ec48a6\",\"panelIndex\":39,\"row\":8,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"col\":5,\"id\":\"465c5820-8977-11e7-857e-e1d56b17746d\",\"panelIndex\":40,\"row\":4,\"size_x\":5,\"size_y\":4,\"type\":\"visualization\"},{\"col\":9,\"id\":\"b2f2adb0-897f-11e7-a2d2-c57bca21b3aa\",\"panelIndex\":45,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"AWCUos-Fib22Ai8JwW0y\",\"panelIndex\":47,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":3,\"id\":\"AWCUozGBib22Ai8JwW1B\",\"panelIndex\":48,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"AWCUo-jRib22Ai8JwW1N\",\"panelIndex\":49,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"AWCUpE3Kib22Ai8JwW1c\",\"panelIndex\":50,\"row\":1,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"AWCUyeHGib22Ai8JwX62\",\"panelIndex\":51,\"row\":4,\"size_x\":4,\"size_y\":4,\"type\":\"visualization\"},{\"col\":4,\"id\":\"AWCg88f1ib22Ai8Jww3C\",\"panelIndex\":52,\"row\":12,\"size_x\":3,\"size_y\":3,\"type\":\"visualization\"},{\"col\":7,\"id\":\"AWCg9JUAib22Ai8Jww3Y\",\"panelIndex\":53,\"row\":12,\"size_x\":2,\"size_y\":3,\"type\":\"visualization\"}]", + "optionsJSON": "{\"darkTheme\":false}", + "uiStateJSON": "{\"P-11\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-2\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-20\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-21\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}},\"P-27\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-28\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}},\"P-3\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"asc\"}}}},\"P-30\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-31\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-40\":{\"vis\":{\"defaultColors\":{\"0 - 3\":\"rgb(0,104,55)\",\"3 - 7\":\"rgb(135,203,103)\",\"7 - 9\":\"rgb(255,255,190)\",\"9 - 11\":\"rgb(249,142,82)\"}}},\"P-41\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-42\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-43\":{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"}}},\"P-44\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-45\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-47\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-48\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-49\":{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"},\"legendOpen\":false}},\"P-5\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-50\":{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}},\"P-6\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-8\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-52\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}},\"P-53\":{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}}", + "version": 1, + "timeRestore": true, + "timeTo": "now", + "timeFrom": "now-30d", + "refreshInterval": { + "display": "Off", + "pause": false, + "value": 0 + }, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"-vulnerability_category:\\\"INFORMATION_GATHERED\\\"\"}}}],\"highlightAll\":true,\"version\":true}" + } + } + } +] \ No newline at end of file diff --git a/kibana/vuln_whisp_kibana/vulnWhispererSavedSearches.json b/kibana/vuln_whisp_kibana/9000_vulnWhisperer_SavedSearch.json similarity index 52% rename from kibana/vuln_whisp_kibana/vulnWhispererSavedSearches.json rename to kibana/vuln_whisp_kibana/9000_vulnWhisperer_SavedSearch.json index cd67942..038f46d 100755 --- a/kibana/vuln_whisp_kibana/vulnWhispererSavedSearches.json +++ b/kibana/vuln_whisp_kibana/9000_vulnWhisperer_SavedSearch.json @@ -3,7 +3,7 @@ "_id": "54648700-3f74-11e7-852e-69207a3d0726", "_type": "search", "_source": { - "title": "Nessus - Saved Search", + "title": "VulnWhisperer - Saved Search", "description": "", "hits": 0, "columns": [ @@ -21,7 +21,7 @@ ], "version": 1, "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" + "searchSourceJSON": "{\"index\":\"logstash-vulnwhisperer-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[],\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"require_field_match\":false,\"fragment_size\":2147483647}}" } } } diff --git a/kibana/vuln_whisp_kibana/vulnWhispererVisualiations.json b/kibana/vuln_whisp_kibana/vulnWhispererVisualiations.json deleted file mode 100755 index bfb5300..0000000 --- a/kibana/vuln_whisp_kibana/vulnWhispererVisualiations.json +++ /dev/null @@ -1,548 +0,0 @@ -[ - { - "_id": "7e7fbc90-3df2-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-PluginID", - "visState": "{\"title\":\"Nessus-PluginID\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"plugin_id.raw\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "c786bc20-3df4-11e7-a3dd-33f478b7be91", - "_type": "visualization", - "_source": { - "title": "Nessus-RiskPie", - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"field\":\"risk.raw\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":50},\"schema\":\"segment\",\"type\":\"terms\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"field\":\"name.raw\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":50},\"schema\":\"segment\",\"type\":\"terms\"},{\"enabled\":true,\"id\":\"4\",\"params\":{\"field\":\"synopsis.raw\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":50},\"schema\":\"segment\",\"type\":\"terms\"},{\"enabled\":true,\"id\":\"5\",\"params\":{\"field\":\"host\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":50},\"schema\":\"segment\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTooltip\":true,\"isDonut\":true,\"legendPosition\":\"right\"},\"title\":\"Nessus-RiskPie\",\"type\":\"pie\"}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"!(None)\"}},\"filter\":[]}" - } - } - }, - { - "_id": "5a3c0340-3eb3-11e7-a192-93f36fbd9d05", - "_type": "visualization", - "_source": { - "title": "Nessus-CVSSHeatmap", - "visState": "{\"title\":\"Nessus-CVSSHeatmap\",\"type\":\"heatmap\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Yellow to Red\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"color\":\"#555\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"host\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"cvss\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"_term\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 3500\":\"rgb(255,255,204)\",\"3500 - 7000\":\"rgb(254,217,118)\",\"7000 - 10500\":\"rgb(253,141,60)\",\"10500 - 14000\":\"rgb(227,27,28)\"}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "60418690-3eb1-11e7-90cb-918f9cb01e3d", - "_type": "visualization", - "_source": { - "title": "Nessus-TopPorts", - "visState": "{\"title\":\"Nessus-TopPorts\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"port\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "983687e0-3df2-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-Protocol", - "visState": "{\"title\":\"Nessus-Protocol\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"protocol.raw\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Protocol\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "995e2280-3df3-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-Host", - "visState": "{\"title\":\"Nessus-Host\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"host\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Host IP\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "87338510-3df2-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-PluginOutput", - "visState": "{\"title\":\"Nessus-PluginOutput\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"plugin_output.raw\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Plugin Output\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "068d4bc0-3df3-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-SeeAlso", - "visState": "{\"title\":\"Nessus-SeeAlso\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"see_also.raw\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"See Also\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "1de9e550-3df1-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-Description", - "visState": "{\"title\":\"Nessus-Description\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"description.raw\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Description\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "1e59fa50-3df3-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-Synopsis", - "visState": "{\"title\":\"Nessus-Synopsis\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"synopsis.raw\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Synopsis\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "13c7d4e0-3df3-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-Solution", - "visState": "{\"title\":\"Nessus-Solution\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"solution.raw\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Solution\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "69765d50-3f5e-11e7-98cc-d924fd28047d", - "_type": "visualization", - "_source": { - "title": "Nessus-CVE", - "visState": "{\"title\":\"Nessus-CVE\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"cve.raw\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"CVE ID\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"!(nan)\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "852816e0-3eb1-11e7-90cb-918f9cb01e3d", - "_type": "visualization", - "_source": { - "title": "Nessus-CVSS", - "visState": "{\"title\":\"Nessus-CVSS\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"cvss\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"CVSS Score\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"host\",\"customLabel\":\"# of Hosts\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "099a3820-3f68-11e7-a6bd-e764d950e506", - "_type": "visualization", - "_source": { - "title": "Timelion Nessus Example", - "visState": "{\"type\":\"timelion\",\"title\":\"Timelion Nessus Example\",\"params\":{\"expression\":\".es(index=logstash-nessus-*,q=risk:high).label(\\\"Current High Risk\\\"),.es(index=logstash-nessus-*,q=risk:high,offset=-1y).label(\\\"Last 1 Year High Risk\\\"),.es(index=logstash-nessus-*,q=risk:medium).label(\\\"Current Medium Risk\\\"),.es(index=logstash-nessus-*,q=risk:medium,offset=-1y).label(\\\"Last 1 Year Medium Risk\\\")\",\"interval\":\"auto\"}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{}" - } - } - }, - { - "_id": "297df800-3f7e-11e7-bd24-6903e3283192", - "_type": "visualization", - "_source": { - "title": "Nessus - Plugin Name", - "visState": "{\"title\":\"Nessus - Plugin Name\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"plugin_name.raw\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Plugin Name\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "de1a5f40-3f85-11e7-97f9-3777d794626d", - "_type": "visualization", - "_source": { - "title": "Nessus - ScanName", - "visState": "{\"title\":\"Nessus - ScanName\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"scan_name.raw\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Scan Name\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "ecbb99c0-3f84-11e7-97f9-3777d794626d", - "_type": "visualization", - "_source": { - "title": "Nessus - Total", - "visState": "{\"title\":\"Nessus - Total\",\"type\":\"metric\",\"params\":{\"handleNoResults\":true,\"fontSize\":60},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Total\"}}],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "471a3580-3f6b-11e7-88e7-df1abe6547fb", - "_type": "visualization", - "_source": { - "title": "Nessus - Vulnerabilities by Tag", - "visState": "{\"title\":\"Nessus - Vulnerabilities by Tag\",\"type\":\"table\",\"params\":{\"perPage\":3,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"bucket\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"tags:has_hipaa_data\",\"analyze_wildcard\":true}}},\"label\":\"Systems with HIPAA data\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"tags:pci_asset\",\"analyze_wildcard\":true}}},\"label\":\"PCI Systems\"},{\"input\":{\"query\":{\"query_string\":{\"query\":\"tags:hipaa_asset\",\"analyze_wildcard\":true}}},\"label\":\"HIPAA Systems\"}]}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "35b6d320-3f7f-11e7-bd24-6903e3283192", - "_type": "visualization", - "_source": { - "title": "Nessus - Residual Risk", - "visState": "{\"title\":\"Nessus - Residual Risk\",\"type\":\"table\",\"params\":{\"perPage\":15,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"risk_score\",\"size\":50,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Risk Number\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"desc\"}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "a9225930-3df2-11e7-a44e-c79ca8efb780", - "_type": "visualization", - "_source": { - "title": "Nessus-Risk", - "visState": "{\"title\":\"Nessus-Risk\",\"type\":\"table\",\"params\":{\"perPage\":4,\"showMeticsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"risk\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Risk Severity\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "2f979030-44b9-11e7-a818-f5f80dfc3590", - "_type": "visualization", - "_source": { - "title": "Nessus - ScanBarChart", - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customLabel\":\"Scan Name\",\"field\":\"scan_name.raw\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":10},\"schema\":\"segment\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"legendPosition\":\"right\",\"mode\":\"stacked\",\"scale\":\"linear\",\"setYExtents\":false,\"times\":[]},\"title\":\"Nessus - ScanBarChart\",\"type\":\"histogram\"}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "67d432e0-44ec-11e7-a05f-d9719b331a27", - "_type": "visualization", - "_source": { - "title": "Nessus - TL-Critical Risk", - "visState": "{\"title\":\"Nessus - TL-Critical Risk\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-nessus-*',q='(risk_score:>=9 AND risk_score:<=10)').label(\\\"Original\\\"),.es(index='logstash-nessus-*',q='(risk_score:>=9 AND risk_score:<=10)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-nessus-*',q='(risk_score:>=9 AND risk_score:<=10)').subtract(.es(index='logstash-nessus-*',q='(risk_score:>=9 AND risk_score:<=10)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "a91b9fe0-44ec-11e7-a05f-d9719b331a27", - "_type": "visualization", - "_source": { - "title": "Nessus - TL-Medium Risk", - "visState": "{\"title\":\"Nessus - TL-Medium Risk\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-nessus-*',q='(risk_score:>=4 AND risk_score:<7)').label(\\\"Original\\\"),.es(index='logstash-nessus-*',q='(risk_score:>=4 AND risk_score:<7)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-nessus-*',q='(risk_score:>=4 AND risk_score:<7)').subtract(.es(index='logstash-nessus-*',q='(risk_score:>=4 AND risk_score:<7)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "8d9592d0-44ec-11e7-a05f-d9719b331a27", - "_type": "visualization", - "_source": { - "title": "Nessus - TL-High Risk", - "visState": "{\"title\":\"Nessus - TL-High Risk\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-nessus-*',q='(risk_score:>=7 AND risk_score:<9)').label(\\\"Original\\\"),.es(index='logstash-nessus-*',q='(risk_score:>=7 AND risk_score:<9)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-nessus-*',q='(risk_score:>=7 AND risk_score:<9)').subtract(.es(index='logstash-nessus-*',q='(risk_score:>=7 AND risk_score:<9)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "a2d66660-44ec-11e7-a05f-d9719b331a27", - "_type": "visualization", - "_source": { - "title": "Nessus - TL-Low Risk", - "visState": "{\"title\":\"Nessus - TL-Low Risk\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-nessus-*',q='(risk_score:>0 AND risk_score:<4)').label(\\\"Original\\\"),.es(index='logstash-nessus-*',q='(risk_score:>0 AND risk_score:<4)',offset=-1w).label(\\\"One week offset\\\"),.es(index='logstash-nessus-*',q='(risk_score:>0 AND risk_score:<4)').subtract(.es(index='logstash-nessus-*',q='(risk_score:>0 AND risk_score:<4)',offset=-1w)).label(\\\"Difference\\\").lines(steps=3,fill=2,width=1)\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "fb6eb020-49ab-11e7-8f8c-57ad64ec48a6", - "_type": "visualization", - "_source": { - "title": "Nessus - Critical Risk Score for Tagged Assets", - "visState": "{\"title\":\"Nessus - Critical Risk Score for Tagged Assets\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index=logstash-nessus-*,q='risk_score:>9 AND tags:hipaa_asset').label(\\\"HIPAA Assets\\\"),.es(index=logstash-nessus-*,q='risk_score:>9 AND tags:pci_asset').label(\\\"PCI Systems\\\"),.es(index=logstash-nessus-*,q='risk_score:>9 AND tags:has_hipaa_data').label(\\\"Has HIPAA Data\\\")\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "80158c90-57c1-11e7-b484-a970fc9d150a", - "_type": "visualization", - "_source": { - "title": "Nessus - HIPAA TL", - "visState": "{\"type\":\"timelion\",\"title\":\"Nessus - HIPAA TL\",\"params\":{\"expression\":\".es(index=logstash-nessus-*,q='risk_score:>9 AND tags:pci_asset').label(\\\"PCI Assets\\\"),.es(index=logstash-nessus-*,q='risk_score:>9 AND tags:has_hipaa_data').label(\\\"Has HIPAA Data\\\"),.es(index=logstash-nessus-*,q='risk_score:>9 AND tags:hipaa_asset').label(\\\"HIPAA Assets\\\")\",\"interval\":\"auto\"}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{}" - } - } - }, - { - "_id": "a6508640-897a-11e7-bbc0-33592ce0be1e", - "_type": "visualization", - "_source": { - "title": "Nessus - Critical Assets Aggregated", - "visState": "{\"title\":\"Nessus - Critical Assets Aggregated\",\"type\":\"heatmap\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"enableHover\":true,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Green to Red\",\"setColorRange\":true,\"colorsRange\":[{\"from\":0,\"to\":3},{\"from\":3,\"to\":7},{\"from\":7,\"to\":9},{\"from\":9,\"to\":11}],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":true,\"rotate\":0,\"color\":\"white\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"risk_score\",\"customLabel\":\"Residual Risk Score\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Date\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"host\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Critical Asset IP\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"plugin_name.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":true}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"colors\":{\"0 - 3\":\"#7EB26D\",\"3 - 7\":\"#EAB839\",\"7 - 9\":\"#EF843C\",\"8 - 10\":\"#BF1B00\",\"9 - 11\":\"#BF1B00\"},\"defaultColors\":{\"0 - 3\":\"rgb(0,104,55)\",\"3 - 7\":\"rgb(135,203,103)\",\"7 - 9\":\"rgb(255,255,190)\",\"9 - 11\":\"rgb(249,142,82)\"},\"legendOpen\":false}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":\"Critical Asset\",\"disabled\":false,\"index\":\"logstash-nessus-*\",\"key\":\"tags\",\"negate\":false,\"type\":\"phrase\",\"value\":\"critical_asset\"},\"query\":{\"match\":{\"tags\":{\"query\":\"critical_asset\",\"type\":\"phrase\"}}}}]}" - } - } - }, - { - "_id": "465c5820-8977-11e7-857e-e1d56b17746d", - "_type": "visualization", - "_source": { - "title": "Nessus - Critical Assets", - "visState": "{\"title\":\"Nessus - Critical Assets\",\"type\":\"heatmap\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"enableHover\":true,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Green to Red\",\"setColorRange\":true,\"colorsRange\":[{\"from\":0,\"to\":3},{\"from\":3,\"to\":7},{\"from\":7,\"to\":9},{\"from\":9,\"to\":11}],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":true,\"rotate\":0,\"color\":\"white\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"risk_score\",\"customLabel\":\"Residual Risk Score\"}},{\"id\":\"2\",\"enabled\":false,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"host\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":true}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Date\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"host\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"Critical Asset IP\"}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 3\":\"rgb(0,104,55)\",\"3 - 7\":\"rgb(135,203,103)\",\"7 - 9\":\"rgb(255,255,190)\",\"9 - 11\":\"rgb(249,142,82)\"},\"colors\":{\"8 - 10\":\"#BF1B00\",\"9 - 11\":\"#BF1B00\",\"7 - 9\":\"#EF843C\",\"3 - 7\":\"#EAB839\",\"0 - 3\":\"#7EB26D\"},\"legendOpen\":false}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[{\"meta\":{\"index\":\"logstash-nessus-*\",\"negate\":false,\"disabled\":false,\"alias\":\"Critical Asset\",\"type\":\"phrase\",\"key\":\"tags\",\"value\":\"critical_asset\"},\"query\":{\"match\":{\"tags\":{\"query\":\"critical_asset\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}" - } - } - }, - { - "_id": "56f0f5f0-3ebe-11e7-a192-93f36fbd9d05", - "_type": "visualization", - "_source": { - "title": "Nessus-RiskOverTime", - "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"customInterval\":\"2h\",\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"field\":\"risk\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"group\",\"type\":\"terms\"}],\"listeners\":{},\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"defaultYExtents\":false,\"drawLinesBetweenPoints\":true,\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"},\"valueAxis\":\"ValueAxis-1\"},\"interpolate\":\"linear\",\"legendPosition\":\"right\",\"orderBucketsBySum\":false,\"radiusRatio\":9,\"scale\":\"linear\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"interpolate\":\"linear\",\"mode\":\"normal\",\"show\":\"true\",\"showCircles\":true,\"type\":\"line\",\"valueAxis\":\"ValueAxis-1\"}],\"setYExtents\":false,\"showCircles\":true,\"times\":[],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}]},\"title\":\"Nessus-RiskOverTime\",\"type\":\"line\"}", - "uiStateJSON": "{\"vis\":{\"colors\":{\"Critical\":\"#E24D42\",\"High\":\"#E0752D\",\"Low\":\"#7EB26D\",\"Medium\":\"#F2C96D\"}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "479deab0-8a39-11e7-a58a-9bfcb3761a3d", - "_type": "visualization", - "_source": { - "title": "Nessus - TL - TaggedAssetsPluginNames", - "visState": "{\"title\":\"Nessus - TL - TaggedAssetsPluginNames\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-nessus-*', q='tags:critical_asset OR tags:hipaa_asset OR tags:pci_asset', split=\\\"plugin_name.raw:10\\\").bars(width=4).label(regex=\\\".*:(.+)>.*\\\",label=\\\"$1\\\")\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "84f5c370-8a38-11e7-a58a-9bfcb3761a3d", - "_type": "visualization", - "_source": { - "title": "Nessus - TL - CriticalAssetsPluginNames", - "visState": "{\"title\":\"Nessus - TL - CriticalAssetsPluginNames\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-nessus-*', q='tags:critical_asset', split=\\\"plugin_name.raw:10\\\").bars(width=4).label(regex=\\\".*:(.+)>.*\\\",label=\\\"$1\\\")\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "307cdae0-8a38-11e7-a58a-9bfcb3761a3d", - "_type": "visualization", - "_source": { - "title": "Nessus - TL - PluginNames", - "visState": "{\"title\":\"Nessus - TL - PluginNames\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(index='logstash-nessus-*', split=\\\"plugin_name.raw:25\\\").bars(width=4).label(regex=\\\".*:(.+)>.*\\\",label=\\\"$1\\\")\",\"interval\":\"auto\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "d048c220-80b3-11e7-8790-73b60225f736", - "_type": "visualization", - "_source": { - "title": "Nessus - Risk: High", - "visState": "{\"title\":\"Nessus - Risk: High\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":1000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":true}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"High Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:High\",\"analyze_wildcard\":true}}},\"label\":\"\"}]}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 1000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#EF843C\",\"0 - 1000\":\"#E0752D\"}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "c1361da0-80b3-11e7-8790-73b60225f736", - "_type": "visualization", - "_source": { - "title": "Nessus - Risk: Medium", - "visState": "{\"title\":\"Nessus - Risk: Medium\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":false}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Medium Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:Medium\",\"analyze_wildcard\":true}}},\"label\":\"Medium Risk\"}]}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#EAB839\"}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "e46ff7f0-897d-11e7-934b-67cec0a7da65", - "_type": "visualization", - "_source": { - "title": "Nessus - Risk: Low", - "visState": "{\"title\":\"Nessus - Risk: Low\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":true,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Metric\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Background\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":false,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"simple\",\"style\":{\"bgFill\":\"white\",\"bgColor\":true,\"labelColor\":false,\"subText\":\"\",\"fontSize\":\"34\"},\"extendRange\":false}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Low Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:Low\",\"analyze_wildcard\":true}}},\"label\":\"Low Risk\"}]}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":true,\"colors\":{\"0 - 10000\":\"#629E51\"}}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - }, - { - "_id": "db55bce0-80b3-11e7-8790-73b60225f736", - "_type": "visualization", - "_source": { - "title": "Nessus - Risk: Critical", - "visState": "{\"title\":\"Nessus - Risk: Critical\",\"type\":\"goal\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"gaugeColorMode\":\"Background\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":false},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":true,\"width\":2},\"style\":{\"bgColor\":true,\"bgFill\":\"white\",\"fontSize\":\"34\",\"labelColor\":false,\"subText\":\"Risk\"},\"type\":\"simple\",\"useRanges\":false,\"verticalSplit\":false},\"type\":\"gauge\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Critical Risk\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"risk:Critical\",\"analyze_wildcard\":true}}},\"label\":\"Critical\"}]}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"colors\":{\"0 - 10000\":\"#BF1B00\"},\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "b2f2adb0-897f-11e7-a2d2-c57bca21b3aa", - "_type": "visualization", - "_source": { - "title": "Nessus - Risk: Total", - "visState": "{\"title\":\"Nessus - Risk: Total\",\"type\":\"goal\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"gauge\":{\"autoExtend\":false,\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"gaugeColorMode\":\"Background\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Metric\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":false},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":true,\"width\":2},\"style\":{\"bgColor\":true,\"bgFill\":\"white\",\"fontSize\":\"34\",\"labelColor\":false,\"subText\":\"Risk\"},\"type\":\"simple\",\"useRanges\":false,\"verticalSplit\":false},\"type\":\"gauge\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"Total\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}}},\"label\":\"Critical\"}]}}],\"listeners\":{}}", - "uiStateJSON": "{\"vis\":{\"colors\":{\"0 - 10000\":\"#64B0C8\"},\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"},\"legendOpen\":false}}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-nessus-*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}" - } - } - }, - { - "_id": "5093c620-44e9-11e7-8014-ede06a7e69f8", - "_type": "visualization", - "_source": { - "title": "Nessus - Mitigation Readme", - "visState": "{\"title\":\"Nessus - Mitigation Readme\",\"type\":\"markdown\",\"params\":{\"markdown\":\"** Legend **\\n\\n* [Common Vulnerability Scoring System (CVSS)](https://nvd.nist.gov/vuln-metrics/cvss) is the NIST vulnerability scoring system\\n* Risk Number is residual risk score calculated from CVSS, which is adjusted to be specific to Heartland which accounts for services not in use such as Java and Flash\\n* Vulnerabilities by Tag are systems tagged with HIPAA and PCI identification.\\n\\n\\n** Workflow **\\n* Select 10.0 under Risk Number to identify Critical Vulnerabilities. \\n* For more information about a CVE, scroll down and click the CVE link.\\n* To filter by tags, use one of the following filters:\\n** tags:has_hipaa_data, tags:pci_asset, tags:hipaa_asset, tags:critical_asset**\"},\"aggs\":[],\"listeners\":{}}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" - } - } - } -] \ No newline at end of file diff --git a/logstash/1000_nessus_preprocess_nessus.conf b/logstash/1000_nessus_preprocess_nessus.conf deleted file mode 100755 index 0f65742..0000000 --- a/logstash/1000_nessus_preprocess_nessus.conf +++ /dev/null @@ -1,141 +0,0 @@ -# Author: Austin Taylor and Justin Henderson -# Email: email@austintaylor.io -# Last Update: 05/22/2017 -# Version 0.2 -# Description: Take in nessus reports from vulnWhisperer and pumps into logstash -#Replace "filebeathost" with the name of your computer - -input { - beats { - port => 5044 - tags => "beats" - } -} - -filter { - if [beat][hostname] == "filebeathost" { - mutate { - add_tag => ["nessus"] - } - } -} - - -filter { - if "nessus" in [tags]{ - mutate { - gsub => [ - "message", "\|\|\|", " ", - "message", "\t\t", " ", - "message", " ", " ", - "message", " ", " ", - "message", " ", " " - ] - } - - csv { - columns => ["plugin_id", "cve", "cvss", "risk", "host", "protocol", "port", "plugin_name", "synopsis", "description", "solution", "see_also", "plugin_output"] - separator => "," - source => "message" - } - - grok { - match => { "source" => "(?[\\\:a-z A-Z_]*\\)(?[a-z-0-9\.A-Z_\-]*)_%{INT:scan_id}_%{INT:history_id}_%{INT:last_updated}" } - tag_on_failure => [] - } - date { - match => [ "last_updated" , "UNIX" ] - target => "@timestamp" - remove_field => ["last_updated"] - } - if [risk] == "None" { - mutate { add_field => { "risk_number" => 0 }} - } - if [risk] == "Low" { - mutate { add_field => { "risk_number" => 1 }} - } - if [risk] == "Medium" { - mutate { add_field => { "risk_number" => 2 }} - } - if [risk] == "High" { - mutate { add_field => { "risk_number" => 3 }} - } - if [risk] == "Critical" { - mutate { add_field => { "risk_number" => 4 }} - } - if [cve] == "nan" { - mutate { remove_field => [ "cve" ] } - } - if [see_also] == "nan" { - mutate { remove_field => [ "see_also" ] } - } - if [description] == "nan" { - mutate { remove_field => [ "description" ] } - } - if [plugin_output] == "nan" { - mutate { remove_field => [ "plugin_output" ] } - } - if [synopsis] == "nan" { - mutate { remove_field => [ "synopsis" ] } - } - - mutate { - remove_field => [ "message" ] - add_field => { "risk_score" => "%{cvss}" } - } - mutate { - convert => { "risk_score" => "float" } - } - - # Compensating controls - adjust risk_score - # Adobe and Java are not allowed to run in browser unless whitelisted - # Therefore, lower score by dividing by 3 (score is subjective to risk) - if [risk_score] != 0 { - if [plugin_name] =~ "Adobe" and [risk_score] > 6 or [plugin_name] =~ "Java" and [risk_score] > 6 { - ruby { - code => "event.set('risk_score', event.get('risk_score') / 3)" - } - mutate { - add_field => { "compensating_control" => "Adobe and Flash removed from browsers unless whitelisted site." } - } - } - } - - # Add tags for reporting based on assets or criticality - if [host] == "192.168.0.1" or [host] == "192.168.0.50" or [host] =~ "^192\.168\.10\." or [host] =~ "^42.42.42." { - mutate { - add_tag => [ "critical_asset" ] - } - } - if [host] =~ "^192\.168\.[45][0-9][0-9]\.1$" or [host] =~ "^192.168\.[50]\.[0-9]{1,2}\.1$"{ - mutate { - add_tag => [ "has_hipaa_data" ] - } - } - if [host] =~ "^192\.168\.[45][0-9][0-9]\." { - mutate { - add_tag => [ "hipaa_asset" ] - } - } - if [host] =~ "^192\.168\.5\." { - mutate { - add_tag => [ "pci_asset" ] - } - if [host] =~ "^10\.0\.50\." { - mutate { - add_tag => [ "web_servers" ] - } - } - } -} -} - -output { - if "nessus" in [tags] or [type] == "nessus" { - #stdout { codec => rubydebug } - elasticsearch { - hosts => [ "localhost" ] - index => "logstash-nessus-%{+YYYY.MM}" - } - } -} diff --git a/logstash/2000_qualys_web_scans.conf b/logstash/2000_qualys_web_scans.conf new file mode 100644 index 0000000..758bc43 --- /dev/null +++ b/logstash/2000_qualys_web_scans.conf @@ -0,0 +1,147 @@ +# Author: Austin Taylor and Justin Henderson +# Email: austin@hasecuritysolutions.com +# Last Update: 12/30/2017 +# Version 0.3 +# Description: Take in qualys web scan reports from vulnWhisperer and pumps into logstash + +input { + file { + path => "/opt/vulnwhisperer/scans/**/*.json" + type => json + codec => json + start_position => "beginning" + tags => [ "qualys_web", "qualys" ] + } +} + +filter { + if "qualys_web" in [tags] { + mutate { + replace => [ "message", "%{message}" ] + #gsub => [ + # "message", "\|\|\|", " ", + # "message", "\t\t", " ", + # "message", " ", " ", + # "message", " ", " ", + # "message", " ", " ", + # "message", "nan", " ", + # "message",'\n','' + #] + } + + + grok { + match => { "path" => "qualys_web_%{INT:app_id}_%{INT:last_updated}.json$" } + tag_on_failure => [] + } + + mutate { + add_field => { "asset" => "%{web_application_name}" } + add_field => { "risk_score" => "%{cvss}" } + } + + if [risk] == "1" { + mutate { add_field => { "risk_number" => 0 }} + mutate { replace => { "risk" => "info" }} + } + if [risk] == "2" { + mutate { add_field => { "risk_number" => 1 }} + mutate { replace => { "risk" => "low" }} + } + if [risk] == "3" { + mutate { add_field => { "risk_number" => 2 }} + mutate { replace => { "risk" => "medium" }} + } + if [risk] == "4" { + mutate { add_field => { "risk_number" => 3 }} + mutate { replace => { "risk" => "high" }} + } + if [risk] == "5" { + mutate { add_field => { "risk_number" => 4 }} + mutate { replace => { "risk" => "critical" }} + } + + mutate { + remove_field => "message" + } + + if [first_time_detected] { + date { + match => [ "first_time_detected", "dd MMM yyyy HH:mma 'GMT'ZZ", "dd MMM yyyy HH:mma 'GMT'" ] + target => "first_time_detected" + } + } + if [first_time_tested] { + date { + match => [ "first_time_tested", "dd MMM yyyy HH:mma 'GMT'ZZ", "dd MMM yyyy HH:mma 'GMT'" ] + target => "first_time_tested" + } + } + if [last_time_detected] { + date { + match => [ "last_time_detected", "dd MMM yyyy HH:mma 'GMT'ZZ", "dd MMM yyyy HH:mma 'GMT'" ] + target => "last_time_detected" + } + } + if [last_time_tested] { + date { + match => [ "last_time_tested", "dd MMM yyyy HH:mma 'GMT'ZZ", "dd MMM yyyy HH:mma 'GMT'" ] + target => "last_time_tested" + } + } + date { + match => [ "last_updated", "UNIX" ] + target => "@timestamp" + remove_field => "last_updated" + } + mutate { + convert => { "plugin_id" => "integer"} + convert => { "id" => "integer"} + convert => { "risk_number" => "integer"} + convert => { "risk_score" => "float"} + convert => { "total_times_detected" => "integer"} + convert => { "cvss_temporal" => "float"} + convert => { "cvss" => "float"} + } + if [risk_score] == 0 { + mutate { + add_field => { "risk_score_name" => "info" } + } + } + if [risk_score] > 0 and [risk_score] < 3 { + mutate { + add_field => { "risk_score_name" => "low" } + } + } + if [risk_score] >= 3 and [risk_score] < 6 { + mutate { + add_field => { "risk_score_name" => "medium" } + } + } + if [risk_score] >=6 and [risk_score] < 9 { + mutate { + add_field => { "risk_score_name" => "high" } + } + } + if [risk_score] >= 9 { + mutate { + add_field => { "risk_score_name" => "critical" } + } + } + + if [asset] =~ "\.yourdomain\.(com|net)$" { + mutate { + add_tag => [ "critical_asset" ] + } + } + } +} +output { + if "qualys" in [tags] { + stdout { codec => rubydebug } + elasticsearch { + hosts => [ "localhost:9200" ] + index => "logstash-vulnwhisperer-%{+YYYY.MM}" + } + } +} diff --git a/logstash/9000_output_nessus.conf b/logstash/9000_output_nessus.conf index 83bed64..3b7d27c 100755 --- a/logstash/9000_output_nessus.conf +++ b/logstash/9000_output_nessus.conf @@ -7,7 +7,7 @@ output { if "nessus" in [tags] or [type] == "nessus" { #stdout { codec => rubydebug } elasticsearch { - hosts => "localhost:19200" + hosts => "localhost:9200" index => "logstash-nessus-%{+YYYY.MM}" } } diff --git a/requirements.txt b/requirements.txt index 1023ba2..1b40850 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ pandas==0.20.3 setuptools==0.9.8 pytz==2017.2 Requests==2.18.3 -qualysapi==4.1.0 \ No newline at end of file +qualysapi==4.1.0 +lxml==4.1.1 \ No newline at end of file diff --git a/setup.py b/setup.py index fa92ce9..4874128 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import setup, find_packages setup( name='VulnWhisperer', - version='1.0.1', + version='1.2.0', packages=find_packages(), url='https://github.com/austin-taylor/vulnwhisperer', license="""MIT License diff --git a/vulnwhisp/__init__.py b/vulnwhisp/__init__.py index e69de29..4e5a397 100755 --- a/vulnwhisp/__init__.py +++ b/vulnwhisp/__init__.py @@ -0,0 +1 @@ +from utils.cli import bcolors \ No newline at end of file diff --git a/vulnwhisp/frameworks/nessus.py b/vulnwhisp/frameworks/nessus.py index 11a1cfb..59ab20e 100755 --- a/vulnwhisp/frameworks/nessus.py +++ b/vulnwhisp/frameworks/nessus.py @@ -35,7 +35,7 @@ class NessusAPI(object): 'Origin': self.base, 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'en-US,en;q=0.8', - 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36', + 'User-Agent': 'VulnWhisperer for Nessus', 'Content-Type': 'application/json', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Referer': self.base, diff --git a/vulnwhisp/frameworks/qualys.py b/vulnwhisp/frameworks/qualys.py index 7fde359..1285f33 100644 --- a/vulnwhisp/frameworks/qualys.py +++ b/vulnwhisp/frameworks/qualys.py @@ -6,6 +6,7 @@ from lxml import objectify from lxml.builder import E import xml.etree.ElementTree as ET import pandas as pd +import qualysapi import qualysapi.config as qcconf import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning @@ -17,8 +18,10 @@ import os import csv import dateutil.parser as dp -class qualysWhisper(object): - COUNT = '/count/was/webapp' + +class qualysWhisperAPI(object): + COUNT_WEBAPP = '/count/was/webapp' + COUNT_WASSCAN = '/count/was/wasscan' DELETE_REPORT = '/delete/was/report/{report_id}' GET_WEBAPP_DETAILS = '/get/was/webapp/{was_id}' QPS_REST_3 = '/qps/rest/3.0' @@ -27,6 +30,8 @@ class qualysWhisper(object): REPORT_STATUS = '/status/was/report/{report_id}' REPORT_CREATE = '/create/was/report' REPORT_DOWNLOAD = '/download/was/report/{report_id}' + SCAN_DETAILS = '/get/was/wasscan/{scan_id}' + SCAN_DOWNLOAD = '/download/was/wasscan/{scan_id}' SEARCH_REPORTS = '/search/was/report' SEARCH_WEB_APPS = '/search/was/webapp' SEARCH_WAS_SCAN = '/search/was/wasscan' @@ -36,36 +41,42 @@ class qualysWhisper(object): self.config = config try: self.qgc = qualysapi.connect(config) - print('[SUCCESS] - Connected to Qualys at %s' \ - % self.qgc.server) + print('[SUCCESS] - Connected to Qualys at %s' % self.qgc.server) except Exception as e: print('[ERROR] Could not connect to Qualys - %s' % e) - self.headers = {'content-type': 'text/xml'} + self.headers = { + "content-type": "text/xml"} self.config_parse = qcconf.QualysConnectConfig(config) try: self.template_id = self.config_parse.get_template_id() except: - print 'ERROR - Could not retrieve template ID' + print('ERROR - Could not retrieve template ID') - def request( - self, - path, - method='get', - data=None, - ): - methods = {'get': requests.get, 'post': requests.post} + def request(self, path, method='get', data=None): + methods = {'get': requests.get, + 'post': requests.post} base = 'https://' + self.qgc.server + path - req = methods[method](base, auth=self.qgc.auth, data=data, - headers=self.headers).content + req = methods[method](base, auth=self.qgc.auth, data=data, headers=self.headers).content return req def get_version(self): return self.request(self.VERSION) def get_scan_count(self, scan_name): - parameters = E.ServiceRequest(E.filters(E.Criteria(scan_name, - field='name', operator='CONTAINS'))) - xml_output = self.qgc.request(self.COUNT, parameters) + parameters = ( + E.ServiceRequest( + E.filters( + E.Criteria({'field': 'name', 'operator': 'CONTAINS'}, scan_name)))) + xml_output = self.qgc.request(self.COUNT_WEBAPP, parameters) + root = objectify.fromstring(xml_output) + return root.count.text + + def get_was_scan_count(self, status): + parameters = ( + E.ServiceRequest( + E.filters( + E.Criteria({'field': 'status', 'operator': 'EQUALS'}, status)))) + xml_output = self.qgc.request(self.COUNT_WASSCAN, parameters) root = objectify.fromstring(xml_output) return root.count.text @@ -75,14 +86,16 @@ class qualysWhisper(object): def xml_parser(self, xml, dupfield=None): all_records = [] root = ET.XML(xml) - for (i, child) in enumerate(root): + for i, child in enumerate(root): for subchild in child: record = {} + dup_tracker = 0 for p in subchild: record[p.tag] = p.text for o in p: - if o.tag == 'id': - record[dupfield] = o.text + if o.tag in record: + dup_tracker += 1 + record[o.tag + '_%s' % dup_tracker] = o.text else: record[o.tag] = o.text all_records.append(record) @@ -90,28 +103,50 @@ class qualysWhisper(object): def get_report_list(self): """Returns a dataframe of reports""" - return self.xml_parser(self.get_reports(), dupfield='user_id') def get_web_apps(self): """Returns webapps available for account""" - return self.qgc.request(self.SEARCH_WEB_APPS) def get_web_app_list(self): """Returns dataframe of webapps""" - return self.xml_parser(self.get_web_apps(), dupfield='user_id') def get_web_app_details(self, was_id): """Get webapp details - use to retrieve app ID tag""" - return self.qgc.request(self.GET_WEBAPP_DETAILS.format(was_id=was_id)) def get_scans_by_app_id(self, app_id): data = self.generate_app_id_scan_XML(app_id) return self.qgc.request(self.SEARCH_WAS_SCAN, data) + def get_scan_info(self, limit=1000, offset=1, status='FINISHED'): + """ Returns XML of ALL WAS Scans""" + data = self.generate_scan_result_XML(limit=limit, offset=offset, status=status) + return self.qgc.request(self.SEARCH_WAS_SCAN, data) + + def get_all_scans(self, limit=1000, offset=1, status='FINISHED'): + qualys_api_limit = limit + dataframes = [] + _records = [] + total = int(self.get_was_scan_count(status=status)) + print('Retrieving information for %s scans' % total) + for i in range(0, total): + if i % limit == 0: + if (total - i) < limit: + qualys_api_limit = total - i + print('Making a request with a limit of %s at offset %s' % (str(qualys_api_limit), str(i + 1))) + scan_info = self.get_scan_info(limit=qualys_api_limit, offset=i + 1, status=status) + _records.append(scan_info) + print('Converting XML to DataFrame') + dataframes = [self.xml_parser(xml) for xml in _records] + + return pd.concat(dataframes, axis=0).reset_index().drop('index', axis=1) + + def get_scan_details(self, scan_id): + return self.qgc.request(self.SCAN_DETAILS.format(scan_id=scan_id)) + def get_report_details(self, report_id): return self.qgc.request(self.REPORT_DETAILS.format(report_id=report_id)) @@ -121,43 +156,109 @@ class qualysWhisper(object): def download_report(self, report_id): return self.qgc.request(self.REPORT_DOWNLOAD.format(report_id=report_id)) + def download_scan_results(self, scan_id): + return self.qgc.request(self.SCAN_DOWNLOAD.format(scan_id=scan_id)) + + def generate_scan_result_XML(self, limit=1000, offset=1, status='FINISHED'): + report_xml = E.ServiceRequest( + E.filters( + E.Criteria({'field': 'status', 'operator': 'EQUALS'}, status + ), + ), + E.preferences( + E.startFromOffset(str(offset)), + E.limitResults(str(limit)) + ), + ) + return report_xml + + def generate_scan_report_XML(self, scan_id): + """Generates a CSV report for an asset based on template defined in .ini file""" + report_xml = E.ServiceRequest( + E.data( + E.Report( + E.name('![CDATA[API Scan Report generated by VulnWhisperer]]>'), + E.description(''), + E.format('CSV'), + E.type('WAS_SCAN_REPORT'), + E.template( + E.id(self.template_id) + ), + E.config( + E.scanReport( + E.target( + E.scans( + E.WasScan( + E.id(scan_id) + ) + ), + ), + ), + ) + ) + ) + ) + return report_xml + def generate_webapp_report_XML(self, app_id): """Generates a CSV report for an asset based on template defined in .ini file""" - - report_xml = \ - E.ServiceRequest(E.data(E.Report(E.name('![CDATA[API Web Application Report generated by VulnWhisperer]]>' - ), - E.description('' - ), E.format('CSV'), - E.template(E.id(self.template_id)), - E.config(E.webAppReport(E.target(E.webapps(E.WebApp(E.id(app_id))))))))) - + report_xml = E.ServiceRequest( + E.data( + E.Report( + E.name('![CDATA[API Web Application Report generated by VulnWhisperer]]>'), + E.description(''), + E.format('CSV'), + E.template( + E.id(self.template_id) + ), + E.config( + E.webAppReport( + E.target( + E.webapps( + E.WebApp( + E.id(app_id) + ) + ), + ), + ), + ) + ) + ) + ) return report_xml def generate_app_id_scan_XML(self, app_id): - report_xml = \ - E.ServiceRequest(E.filters(E.Criteria({'field': 'webApp.id' - , 'operator': 'EQUALS'}, app_id))) - + report_xml = E.ServiceRequest( + E.filters( + E.Criteria({'field': 'webApp.id', 'operator': 'EQUALS'}, app_id + ), + ), + ) return report_xml - def create_report(self, report_id): - data = self.generate_webapp_report_XML(report_id) - return self.qgc.request(self.REPORT_CREATE.format(report_id=report_id), - data) + def create_report(self, report_id, kind='scan'): + mapper = {'scan': self.generate_scan_report_XML, + 'webapp': self.generate_webapp_report_XML} + try: + # print lxml.etree.tostring(mapper[kind](report_id), pretty_print=True) + data = mapper[kind](report_id) + except Exception as e: + print(e) + + return self.qgc.request(self.REPORT_CREATE, data) def delete_report(self, report_id): return self.qgc.request(self.DELETE_REPORT.format(report_id=report_id)) -class qualysWebAppReport: - CATEGORIES = ['VULNERABILITY', 'SENSITIVE CONTENT', - 'INFORMATION GATHERED'] +class qualysReportFields: + CATEGORIES = ['VULNERABILITY', + 'SENSITIVECONTENT', + 'INFORMATION_GATHERED'] # URL Vulnerability Information - WEB_APP_VULN_BLOCK = [ - 'Web Application Name', + VULN_BLOCK = [ CATEGORIES[0], 'ID', 'QID', @@ -169,7 +270,6 @@ class qualysWebAppReport: 'Authentication', 'Ajax Request', 'Ajax Request ID', - 'Status', 'Ignored', 'Ignore Reason', 'Ignore Date', @@ -187,29 +287,14 @@ class qualysWebAppReport: 'Evidence #1', ] - WEB_APP_VULN_HEADER = list(WEB_APP_VULN_BLOCK) - WEB_APP_VULN_HEADER[WEB_APP_VULN_BLOCK.index(CATEGORIES[0])] = \ - 'Vulnerability Category' - - WEB_APP_SENSITIVE_HEADER = list(WEB_APP_VULN_HEADER) - WEB_APP_SENSITIVE_HEADER.insert(WEB_APP_SENSITIVE_HEADER.index('Url' - ), 'Content') - - WEB_APP_SENSITIVE_BLOCK = list(WEB_APP_SENSITIVE_HEADER) - WEB_APP_SENSITIVE_BLOCK[WEB_APP_SENSITIVE_BLOCK.index('Vulnerability Category' - )] = CATEGORIES[1] - - - WEB_APP_INFO_HEADER = [ - 'Web Application Name', + INFO_HEADER = [ 'Vulnerability Category', 'ID', 'QID', 'Response #1', 'Last Time Detected', ] - WEB_APP_INFO_BLOCK = [ - 'Web Application Name', + INFO_BLOCK = [ CATEGORIES[2], 'ID', 'QID', @@ -236,43 +321,13 @@ class qualysWebAppReport: GROUP_HEADER = ['GROUP', 'Name', 'Category'] OWASP_HEADER = ['OWASP', 'Code', 'Name'] WASC_HEADER = ['WASC', 'Code', 'Name'] + SCAN_META = ['Web Application Name', 'URL', 'Owner', 'Scope', 'Operating System'] CATEGORY_HEADER = ['Category', 'Severity', 'Level', 'Description'] - def __init__( - self, - config=None, - file_in=None, - file_stream=False, - delimiter=',', - quotechar='"', - ): - self.file_in = file_in - self.file_stream = file_stream - self.report = None - if config: - try: - self.qw = qualysWhisper(config=config) - except Exception as e: - print('Could not load config! Please check settings for %s' \ - % e) - if file_stream: - self.open_file = file_in.splitlines() - elif file_in: - - self.open_file = open(file_in, 'rb') - - self.downloaded_file = None - - def get_hostname(self, report): - host = '' - with open(report, 'rb') as csvfile: - q_report = csv.reader(csvfile, delimiter=',', quotechar='"') - for x in q_report: - - if 'Web Application Name' in x[0]: - host = q_report.next()[0] - return host +class qualysUtils: + def __init__(self): + pass def grab_section( self, @@ -303,56 +358,127 @@ class qualysWebAppReport: return dp.parse(dt).strftime('%s') def cleanser(self, _data): - repls = (('\n', '|||'), ('\r', '|||'), (',', ';'), ('\t', '|||' - )) + repls = (('\n', '|||'), ('\r', '|||'), (',', ';'), ('\t', '|||')) if _data: - _data = reduce(lambda a, kv: a.replace(*kv), repls, _data) + _data = reduce(lambda a, kv: a.replace(*kv), repls, str(_data)) return _data + +class qualysWebAppReport: + # URL Vulnerability Information + WEB_APP_VULN_BLOCK = list(qualysReportFields.VULN_BLOCK) + WEB_APP_VULN_BLOCK.insert(0, 'Web Application Name') + WEB_APP_VULN_BLOCK.insert(WEB_APP_VULN_BLOCK.index('Ignored'), 'Status') + + WEB_APP_VULN_HEADER = list(WEB_APP_VULN_BLOCK) + WEB_APP_VULN_HEADER[WEB_APP_VULN_BLOCK.index(qualysReportFields.CATEGORIES[0])] = \ + 'Vulnerability Category' + + WEB_APP_SENSITIVE_HEADER = list(WEB_APP_VULN_HEADER) + WEB_APP_SENSITIVE_HEADER.insert(WEB_APP_SENSITIVE_HEADER.index('Url' + ), 'Content') + + WEB_APP_SENSITIVE_BLOCK = list(WEB_APP_SENSITIVE_HEADER) + WEB_APP_SENSITIVE_BLOCK[WEB_APP_SENSITIVE_BLOCK.index('Vulnerability Category' + )] = qualysReportFields.CATEGORIES[1] + + WEB_APP_INFO_HEADER = list(qualysReportFields.INFO_HEADER) + WEB_APP_INFO_HEADER.insert(0, 'Web Application Name') + + WEB_APP_INFO_BLOCK = list(qualysReportFields.INFO_BLOCK) + WEB_APP_INFO_BLOCK.insert(0, 'Web Application Name') + + QID_HEADER = list(qualysReportFields.QID_HEADER) + GROUP_HEADER = list(qualysReportFields.GROUP_HEADER) + OWASP_HEADER = list(qualysReportFields.OWASP_HEADER) + WASC_HEADER = list(qualysReportFields.WASC_HEADER) + SCAN_META = list(qualysReportFields.SCAN_META) + CATEGORY_HEADER = list(qualysReportFields.CATEGORY_HEADER) + + def __init__( + self, + config=None, + file_in=None, + file_stream=False, + delimiter=',', + quotechar='"', + ): + self.file_in = file_in + self.file_stream = file_stream + self.report = None + self.utils = qualysUtils() + + if config: + try: + self.qw = qualysWhisperAPI(config=config) + except Exception as e: + print('Could not load config! Please check settings for %s' \ + % e) + + if file_stream: + self.open_file = file_in.splitlines() + elif file_in: + + self.open_file = open(file_in, 'rb') + + self.downloaded_file = None + + def get_hostname(self, report): + host = '' + with open(report, 'rb') as csvfile: + q_report = csv.reader(csvfile, delimiter=',', quotechar='"') + for x in q_report: + + if 'Web Application Name' in x[0]: + host = q_report.next()[0] + return host + + def get_scanreport_name(self, report): + scan_name = '' + with open(report, 'rb') as csvfile: + q_report = csv.reader(csvfile, delimiter=',', quotechar='"') + for x in q_report: + + if 'Scans' in x[0]: + scan_name = x[1] + return scan_name + def grab_sections(self, report): all_dataframes = [] - category_list = [] + dict_tracker = {} with open(report, 'rb') as csvfile: - q_report = csv.reader(csvfile, delimiter=',', quotechar='"') - all_dataframes.append(pd.DataFrame(self.grab_section(report, - self.WEB_APP_VULN_BLOCK, - end=[self.WEB_APP_SENSITIVE_BLOCK, - self.WEB_APP_INFO_BLOCK], - pop_last=True), - columns=self.WEB_APP_VULN_HEADER)) - all_dataframes.append(pd.DataFrame(self.grab_section(report, - self.WEB_APP_SENSITIVE_BLOCK, - end=[self.WEB_APP_INFO_BLOCK, - self.WEB_APP_SENSITIVE_BLOCK], - pop_last=True), - columns=self.WEB_APP_SENSITIVE_HEADER)) - all_dataframes.append(pd.DataFrame(self.grab_section(report, - self.WEB_APP_INFO_BLOCK, - end=[self.QID_HEADER], - pop_last=True), - columns=self.WEB_APP_INFO_HEADER)) - all_dataframes.append(pd.DataFrame(self.grab_section(report, - self.QID_HEADER, - end=[self.GROUP_HEADER], - pop_last=True), - columns=self.QID_HEADER)) - all_dataframes.append(pd.DataFrame(self.grab_section(report, - self.GROUP_HEADER, - end=[self.OWASP_HEADER], - pop_last=True), - columns=self.GROUP_HEADER)) - all_dataframes.append(pd.DataFrame(self.grab_section(report, - self.OWASP_HEADER, - end=[self.WASC_HEADER], - pop_last=True), - columns=self.OWASP_HEADER)) - all_dataframes.append(pd.DataFrame(self.grab_section(report, - self.WASC_HEADER, end=[['APPENDIX']], - pop_last=True), - columns=self.WASC_HEADER)) - all_dataframes.append(pd.DataFrame(self.grab_section(report, - self.CATEGORY_HEADER, end=''), - columns=self.CATEGORY_HEADER)) + dict_tracker['WEB_APP_VULN_BLOCK'] = pd.DataFrame(self.utils.grab_section(report, + self.WEB_APP_VULN_BLOCK, + end=[self.WEB_APP_SENSITIVE_BLOCK, + self.WEB_APP_INFO_BLOCK], + pop_last=True), columns=self.WEB_APP_VULN_HEADER) + dict_tracker['WEB_APP_SENSITIVE_BLOCK'] = pd.DataFrame(self.utils.grab_section(report, + self.WEB_APP_SENSITIVE_BLOCK, + end=[self.WEB_APP_INFO_BLOCK, + self.WEB_APP_SENSITIVE_BLOCK], + pop_last=True), columns=self.WEB_APP_SENSITIVE_HEADER) + dict_tracker['WEB_APP_INFO_BLOCK'] = pd.DataFrame(self.utils.grab_section(report, + self.WEB_APP_INFO_BLOCK, + end=[self.QID_HEADER], + pop_last=True), columns=self.WEB_APP_INFO_HEADER) + dict_tracker['QID_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.QID_HEADER, + end=[self.GROUP_HEADER], + pop_last=True), columns=self.QID_HEADER) + dict_tracker['GROUP_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.GROUP_HEADER, + end=[self.OWASP_HEADER], + pop_last=True), columns=self.GROUP_HEADER) + dict_tracker['OWASP_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.OWASP_HEADER, + end=[self.WASC_HEADER], + pop_last=True), columns=self.OWASP_HEADER) + dict_tracker['WASC_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.WASC_HEADER, end=[['APPENDIX']], + pop_last=True), columns=self.WASC_HEADER) + dict_tracker['CATEGORY_HEADER'] =pd.DataFrame(self.utils.grab_section(report, + self.CATEGORY_HEADER), columns=self.CATEGORY_HEADER) + all_dataframes.append(dict_tracker) return all_dataframes @@ -362,39 +488,34 @@ class qualysWebAppReport: :param dataframes: :return: """ + df_dict = dataframes[0] + merged_df = pd.concat([df_dict['WEB_APP_VULN_BLOCK'], df_dict['WEB_APP_SENSITIVE_BLOCK'], + df_dict['WEB_APP_INFO_BLOCK']], axis=0, + ignore_index=False) + + merged_df = pd.merge(merged_df, df_dict['QID_HEADER'], left_on='QID', + right_on='Id') merged_df = pd.concat([dataframes[0], dataframes[1], dataframes[2]], axis=0, - ignore_index=False).fillna('N/A') + ignore_index=False) merged_df = pd.merge(merged_df, dataframes[3], left_on='QID', right_on='Id') if 'Content' not in merged_df: merged_df['Content'] = '' - merged_df['Payload #1'] = merged_df['Payload #1' - ].apply(self.cleanser) - merged_df['Request Method #1'] = merged_df['Request Method #1' - ].apply(self.cleanser) - merged_df['Request URL #1'] = merged_df['Request URL #1' - ].apply(self.cleanser) - merged_df['Request Headers #1'] = merged_df['Request Headers #1' - ].apply(self.cleanser) - merged_df['Response #1'] = merged_df['Response #1' - ].apply(self.cleanser) - merged_df['Evidence #1'] = merged_df['Evidence #1' - ].apply(self.cleanser) + columns_to_cleanse = ['Payload #1', 'Request Method #1', 'Request URL #1', + 'Request Headers #1', 'Response #1', 'Evidence #1', + 'Description', 'Impact', 'Solution', 'Url', 'Content'] - merged_df['Description'] = merged_df['Description' - ].apply(self.cleanser) - merged_df['Impact'] = merged_df['Impact'].apply(self.cleanser) - merged_df['Solution'] = merged_df['Solution' - ].apply(self.cleanser) - merged_df['Url'] = merged_df['Url'].apply(self.cleanser) - merged_df['Content'] = merged_df['Content'].apply(self.cleanser) + for col in columns_to_cleanse: + merged_df[col] = merged_df[col].astype(str).apply(self.utils.cleanser) + + merged_df = pd.merge(merged_df, df_dict['CATEGORY_HEADER']) merged_df = merged_df.drop(['QID_y', 'QID_x'], axis=1) - merged_df = merged_df.rename(columns={'Id': 'QID'}) + merged_df = merged_df.replace('N/A','').fillna('') try: merged_df = \ @@ -417,28 +538,31 @@ class qualysWebAppReport: def remove_file(self, filename): os.remove(filename) - def process_data(self, file_id, cleanup=True): + def process_data(self, file_id, scan=True, cleanup=True): """Downloads a file from qualys and normalizes it""" download_file = self.download_file(file_id) print('[ACTION] - Downloading file ID: %s' % file_id) report_data = self.grab_sections(download_file) merged_data = self.data_normalizer(report_data) + if scan: + scan_name = self.get_scanreport_name(download_file) + merged_data['ScanName'] = scan_name # TODO cleanup old data (delete) return merged_data - def whisper_webapp(self, report_id, updated_date): + def whisper_reports(self, report_id, updated_date, cleanup=False): """ report_id: App ID updated_date: Last time scan was ran for app_id """ - + vuln_ready = None try: - vuln_ready = None + if 'Z' in updated_date: - updated_date = self.iso_to_epoch(updated_date) + updated_date = self.utils.iso_to_epoch(updated_date) report_name = 'qualys_web_' + str(report_id) \ + '_{last_updated}'.format(last_updated=updated_date) \ + '.csv' @@ -454,19 +578,20 @@ class qualysWebAppReport: % report_id) generated_report_id = root.data.Report.id print ('[INFO] - New Report ID: %s' \ - % generated_report_id) + % generated_report_id) vuln_ready = self.process_data(generated_report_id) - vuln_ready.to_csv(report_name, index=False) # add when timestamp occured + vuln_ready.to_csv(report_name, index=False, header=True) # add when timestamp occured print('[SUCCESS] - Report written to %s' \ % report_name) - print('[ACTION] - Removing report %s' \ - % generated_report_id) - cleaning_up = \ - self.qw.delete_report(generated_report_id) - os.remove(str(generated_report_id) + '.csv') - print('[ACTION] - Deleted report: %s' \ - % generated_report_id) + if cleanup: + print('[ACTION] - Removing report %s' \ + % generated_report_id) + cleaning_up = \ + self.qw.delete_report(generated_report_id) + self.remove_file(str(generated_report_id) + '.csv') + print('[ACTION] - Deleted report: %s' \ + % generated_report_id) else: print('Could not process report ID: %s' % status) except Exception as e: @@ -474,4 +599,239 @@ class qualysWebAppReport: return vuln_ready +class qualysScanReport: + # URL Vulnerability Information + WEB_SCAN_VULN_BLOCK = list(qualysReportFields.VULN_BLOCK) + WEB_SCAN_VULN_BLOCK.insert(WEB_SCAN_VULN_BLOCK.index('QID'), 'Detection ID') + WEB_SCAN_VULN_HEADER = list(WEB_SCAN_VULN_BLOCK) + WEB_SCAN_VULN_HEADER[WEB_SCAN_VULN_BLOCK.index(qualysReportFields.CATEGORIES[0])] = \ + 'Vulnerability Category' + + WEB_SCAN_SENSITIVE_HEADER = list(WEB_SCAN_VULN_HEADER) + WEB_SCAN_SENSITIVE_HEADER.insert(WEB_SCAN_SENSITIVE_HEADER.index('Url' + ), 'Content') + + WEB_SCAN_SENSITIVE_BLOCK = list(WEB_SCAN_SENSITIVE_HEADER) + WEB_SCAN_SENSITIVE_BLOCK.insert(WEB_SCAN_SENSITIVE_BLOCK.index('QID'), 'Detection ID') + WEB_SCAN_SENSITIVE_BLOCK[WEB_SCAN_SENSITIVE_BLOCK.index('Vulnerability Category' + )] = qualysReportFields.CATEGORIES[1] + + WEB_SCAN_INFO_HEADER = list(qualysReportFields.INFO_HEADER) + WEB_SCAN_INFO_HEADER.insert(WEB_SCAN_INFO_HEADER.index('QID'), 'Detection ID') + + WEB_SCAN_INFO_BLOCK = list(qualysReportFields.INFO_BLOCK) + WEB_SCAN_INFO_BLOCK.insert(WEB_SCAN_INFO_BLOCK.index('QID'), 'Detection ID') + + QID_HEADER = list(qualysReportFields.QID_HEADER) + GROUP_HEADER = list(qualysReportFields.GROUP_HEADER) + OWASP_HEADER = list(qualysReportFields.OWASP_HEADER) + WASC_HEADER = list(qualysReportFields.WASC_HEADER) + SCAN_META = list(qualysReportFields.SCAN_META) + CATEGORY_HEADER = list(qualysReportFields.CATEGORY_HEADER) + + def __init__( + self, + config=None, + file_in=None, + file_stream=False, + delimiter=',', + quotechar='"', + ): + self.file_in = file_in + self.file_stream = file_stream + self.report = None + self.utils = qualysUtils() + + if config: + try: + self.qw = qualysWhisperAPI(config=config) + except Exception as e: + print('Could not load config! Please check settings for %s' \ + % e) + + if file_stream: + self.open_file = file_in.splitlines() + elif file_in: + + self.open_file = open(file_in, 'rb') + + self.downloaded_file = None + + def grab_sections(self, report): + all_dataframes = [] + dict_tracker = {} + with open(report, 'rb') as csvfile: + dict_tracker['WEB_SCAN_VULN_BLOCK'] = pd.DataFrame(self.utils.grab_section(report, + self.WEB_SCAN_VULN_BLOCK, + end=[ + self.WEB_SCAN_SENSITIVE_BLOCK, + self.WEB_SCAN_INFO_BLOCK], + pop_last=True), + columns=self.WEB_SCAN_VULN_HEADER) + dict_tracker['WEB_SCAN_SENSITIVE_BLOCK'] = pd.DataFrame(self.utils.grab_section(report, + self.WEB_SCAN_SENSITIVE_BLOCK, + end=[ + self.WEB_SCAN_INFO_BLOCK, + self.WEB_SCAN_SENSITIVE_BLOCK], + pop_last=True), + columns=self.WEB_SCAN_SENSITIVE_HEADER) + dict_tracker['WEB_SCAN_INFO_BLOCK'] = pd.DataFrame(self.utils.grab_section(report, + self.WEB_SCAN_INFO_BLOCK, + end=[self.QID_HEADER], + pop_last=True), + columns=self.WEB_SCAN_INFO_HEADER) + dict_tracker['QID_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.QID_HEADER, + end=[self.GROUP_HEADER], + pop_last=True), + columns=self.QID_HEADER) + dict_tracker['GROUP_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.GROUP_HEADER, + end=[self.OWASP_HEADER], + pop_last=True), + columns=self.GROUP_HEADER) + dict_tracker['OWASP_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.OWASP_HEADER, + end=[self.WASC_HEADER], + pop_last=True), + columns=self.OWASP_HEADER) + dict_tracker['WASC_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.WASC_HEADER, end=[['APPENDIX']], + pop_last=True), + columns=self.WASC_HEADER) + + dict_tracker['SCAN_META'] = pd.DataFrame(self.utils.grab_section(report, + self.SCAN_META, + end=[self.CATEGORY_HEADER], + pop_last=True), + columns=self.SCAN_META) + + dict_tracker['CATEGORY_HEADER'] = pd.DataFrame(self.utils.grab_section(report, + self.CATEGORY_HEADER), + columns=self.CATEGORY_HEADER) + all_dataframes.append(dict_tracker) + + return all_dataframes + + def data_normalizer(self, dataframes): + """ + Merge and clean data + :param dataframes: + :return: + """ + df_dict = dataframes[0] + merged_df = pd.concat([df_dict['WEB_SCAN_VULN_BLOCK'], df_dict['WEB_SCAN_SENSITIVE_BLOCK'], + df_dict['WEB_SCAN_INFO_BLOCK']], axis=0, + ignore_index=False) + merged_df = pd.merge(merged_df, df_dict['QID_HEADER'], left_on='QID', + right_on='Id') + + if 'Content' not in merged_df: + merged_df['Content'] = '' + + columns_to_cleanse = ['Payload #1', 'Request Method #1', 'Request URL #1', + 'Request Headers #1', 'Response #1', 'Evidence #1', + 'Description', 'Impact', 'Solution', 'Url', 'Content'] + + for col in columns_to_cleanse: + merged_df[col] = merged_df[col].apply(self.utils.cleanser) + + merged_df = merged_df.drop(['QID_y', 'QID_x'], axis=1) + merged_df = merged_df.rename(columns={'Id': 'QID'}) + merged_df = merged_df.assign(**df_dict['SCAN_META'].to_dict(orient='records')[0]) + + merged_df = pd.merge(merged_df, df_dict['CATEGORY_HEADER'], how='left', left_on=['Category', 'Severity Level'], + right_on=['Category', 'Severity'], suffixes=('Severity', 'CatSev')) + + merged_df = merged_df.replace('N/A', '').fillna('') + + try: + merged_df = \ + merged_df[~merged_df.Title.str.contains('Links Crawled|External Links Discovered' + )] + except Exception as e: + print(e) + return merged_df + + def download_file(self, path='', file_id=None): + report = self.qw.download_report(file_id) + filename = path + str(file_id) + '.csv' + file_out = open(filename, 'w') + for line in report.splitlines(): + file_out.write(line + '\n') + file_out.close() + print('[ACTION] - File written to %s' % filename) + return filename + + def remove_file(self, filename): + os.remove(filename) + + def process_data(self, path='', file_id=None, cleanup=True): + """Downloads a file from qualys and normalizes it""" + + download_file = self.download_file(path=path, file_id=file_id) + print('[ACTION] - Downloading file ID: %s' % file_id) + report_data = self.grab_sections(download_file) + merged_data = self.data_normalizer(report_data) + merged_data.sort_index(axis=1, inplace=True) + # TODO cleanup old data (delete) + + return merged_data + + def whisper_reports(self, report_id, updated_date, cleanup=False): + """ + report_id: App ID + updated_date: Last time scan was ran for app_id + """ + vuln_ready = None + try: + + if 'Z' in updated_date: + updated_date = self.utils.iso_to_epoch(updated_date) + report_name = 'qualys_web_' + str(report_id) \ + + '_{last_updated}'.format(last_updated=updated_date) \ + + '.csv' + if os.path.isfile(report_name): + print('[ACTION] - File already exist! Skipping...') + pass + else: + print('[ACTION] - Generating report for %s' % report_id) + status = self.qw.create_report(report_id) + root = objectify.fromstring(status) + if root.responseCode == 'SUCCESS': + print('[INFO] - Successfully generated report for webapp: %s' \ + % report_id) + generated_report_id = root.data.Report.id + print ('[INFO] - New Report ID: %s' \ + % generated_report_id) + vuln_ready = self.process_data(generated_report_id) + + vuln_ready.to_csv(report_name, index=False, header=True) # add when timestamp occured + print('[SUCCESS] - Report written to %s' \ + % report_name) + if cleanup: + print('[ACTION] - Removing report %s from disk' \ + % generated_report_id) + cleaning_up = \ + self.qw.delete_report(generated_report_id) + self.remove_file(str(generated_report_id) + '.csv') + print('[ACTION] - Deleted report from Qualys Database: %s' \ + % generated_report_id) + else: + print('Could not process report ID: %s' % status) + except Exception as e: + print('[ERROR] - Could not process %s - %s' % (report_id, e)) + return vuln_ready + + +maxInt = sys.maxsize +decrement = True + +while decrement: + decrement = False + try: + csv.field_size_limit(maxInt) + except OverflowError: + maxInt = int(maxInt/10) + decrement = True \ No newline at end of file diff --git a/vulnwhisp/utils/cli.py b/vulnwhisp/utils/cli.py index c71abcf..046fbfa 100644 --- a/vulnwhisp/utils/cli.py +++ b/vulnwhisp/utils/cli.py @@ -12,5 +12,6 @@ class bcolors: UNDERLINE = '\033[4m' INFO = '{info}[INFO]{endc}'.format(info=OKBLUE, endc=ENDC) + ACTION = '{info}[ACTION]{endc}'.format(info=OKBLUE, endc=ENDC) SUCCESS = '{green}[SUCCESS]{endc}'.format(green=OKGREEN, endc=ENDC) FAIL = '{red}[FAIL]{endc}'.format(red=FAIL, endc=ENDC) diff --git a/vulnwhisp/vulnwhisp.py b/vulnwhisp/vulnwhisp.py index accd153..5cccf74 100755 --- a/vulnwhisp/vulnwhisp.py +++ b/vulnwhisp/vulnwhisp.py @@ -1,8 +1,13 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +__author__ = 'Austin Taylor' from base.config import vwConfig from frameworks.nessus import NessusAPI +from frameworks.qualys import qualysScanReport from utils.cli import bcolors import pandas as pd +from lxml import objectify import sys import os import io @@ -10,114 +15,104 @@ import time import sqlite3 # TODO Create logging option which stores data about scan + import logging +class vulnWhispererBase(object): -class vulnWhisperer(object): + CONFIG_SECTION = None - def __init__(self, config=None, db_name='report_tracker.db', purge=False, verbose=None, debug=False, username=None, password=None): + def __init__( + self, + config=None, + db_name='report_tracker.db', + purge=False, + verbose=None, + debug=False, + username=None, + password=None, + section=None, + develop=False, + ): - self.verbose = verbose - self.nessus_connect = False - self.develop = True + + if self.CONFIG_SECTION is None: + raise Exception('Implementing class must define CONFIG_SECTION') + + self.db_name = db_name self.purge = purge - + self.develop = develop if config is not None: - try: - self.config = vwConfig(config_in=config) - self.nessus_enabled = self.config.getbool('nessus', 'enabled') + self.config = vwConfig(config_in=config) + self.enabled = self.config.get(self.CONFIG_SECTION, 'enabled') + self.hostname = self.config.get(self.CONFIG_SECTION, 'hostname') + self.username = self.config.get(self.CONFIG_SECTION, 'username') + self.password = self.config.get(self.CONFIG_SECTION, 'password') + self.write_path = self.config.get(self.CONFIG_SECTION, 'write_path') + self.db_path = self.config.get(self.CONFIG_SECTION, 'db_path') + self.verbose = self.config.getbool(self.CONFIG_SECTION, 'verbose') - if self.nessus_enabled: - self.nessus_hostname = self.config.get('nessus', 'hostname') - self.nessus_port = self.config.get('nessus', 'port') - if password: - self.nessus_password = password - else: - self.nessus_password = self.config.get('nessus', 'password') - - if username: - self.nessus_username = username - else: - self.nessus_username = self.config.get('nessus', 'username') - - self.nessus_writepath = self.config.get('nessus', 'write_path') - self.nessus_dbpath = self.config.get('nessus', 'db_path') - self.nessus_trash = self.config.getbool('nessus', 'trash') - self.verbose = self.config.getbool('nessus', 'verbose') - - try: - self.vprint( - '{info} Attempting to connect to nessus...'.format(info=bcolors.INFO)) - self.nessus = NessusAPI(hostname=self.nessus_hostname, - port=self.nessus_port, - username=self.nessus_username, - password=self.nessus_password) - self.nessus_connect = True - self.vprint( - '{success} Connected to nessus on {host}:{port}'.format(success=bcolors.SUCCESS, - host=self.nessus_hostname, - port=str(self.nessus_port))) - except Exception as e: - self.vprint(e) - raise Exception( - "{fail} Could not connect to nessus -- Please verify your settings in {config} are correct and try again.\nReason: {e}".format(config=self.config, - fail=bcolors.FAIL, - e=e)) - - except Exception as e: - - self.vprint('{fail} Could not properly load your config!\nReason: {e}'.format(fail=bcolors.FAIL, e=e)) - sys.exit(0) - - if db_name is not None: - if self.nessus_dbpath: - self.database = os.path.join(self.nessus_dbpath, db_name) + if self.db_name is not None: + if self.db_path: + self.database = os.path.join(self.db_path, + db_name) else: - self.database = os.path.abspath(os.path.join(os.path.dirname( __file__ ), 'database', db_name)) + self.database = \ + os.path.abspath(os.path.join(os.path.dirname(__file__), + 'database', db_name)) try: self.conn = sqlite3.connect(self.database) self.cur = self.conn.cursor() - self.vprint("{info} Connected to database at {loc}".format(info=bcolors.INFO, loc=self.database)) + self.vprint('{info} Connected to database at {loc}'.format(info=bcolors.INFO, + loc=self.database)) except Exception as e: - self.vprint("{fail} Could not connect to database at {loc}\nReason: {e} - Please ensure the path exist".format(e=e, fail=bcolors.FAIL, loc=self.database)) - + self.vprint( + '{fail} Could not connect to database at {loc}\nReason: {e} - Please ensure the path exist'.format( + e=e, + fail=bcolors.FAIL, loc=self.database)) else: + self.vprint('{fail} Please specify a database to connect to!'.format(fail=bcolors.FAIL)) exit(0) - self.table_columns = ['scan_name', - 'scan_id', - 'last_modified', - 'filename', - 'download_time', - 'record_count', - 'source', - 'uuid', - 'processed'] + self.table_columns = [ + 'scan_name', + 'scan_id', + 'last_modified', + 'filename', + 'download_time', + 'record_count', + 'source', + 'uuid', + 'processed', + ] + self.init() self.uuids = self.retrieve_uuids() self.processed = 0 self.skipped = 0 self.scan_list = [] - - def vprint(self, msg): if self.verbose: print(msg) - def create_table(self): - self.cur.execute("create table if not exists scan_history (id integer primary key, scan_name text, scan_id integer, last_modified date, filename text, download_time date, record_count integer, source text, uuid text, processed integer)") + self.cur.execute( + 'CREATE TABLE IF NOT EXISTS scan_history (id INTEGER PRIMARY KEY,' + ' scan_name TEXT, scan_id INTEGER, last_modified DATE, filename TEXT,' + ' download_time DATE, record_count INTEGER, source TEXT,' + ' uuid TEXT, processed INTEGER)' + ) self.conn.commit() def delete_table(self): - self.cur.execute('drop table if exists scan_history') + self.cur.execute('DROP TABLE IF EXISTS scan_history') self.conn.commit() def init(self): @@ -126,15 +121,90 @@ class vulnWhisperer(object): self.create_table() def cleanser(self, _data): - repls = ('\n', '|||'), ('\r', '|||'), (',',';') + repls = (('\n', '|||'), ('\r', '|||'), (',', ';')) data = reduce(lambda a, kv: a.replace(*kv), repls, _data) return data def path_check(self, _data): - if self.nessus_writepath: - data = self.nessus_writepath + '/' + _data + if self.write_path: + if '/' or '\\' in _data[-1]: + data = self.write_path + _data + else: + data = self.write_path + '/' + _data return data + def record_insert(self, record): + self.cur.execute('insert into scan_history({table_columns}) values (?,?,?,?,?,?,?,?,?)'.format( + table_columns=', '.join(self.table_columns)), + record) + self.conn.commit() + + def retrieve_uuids(self): + """ + Retrieves UUIDs from database and checks list to determine which files need to be processed. + :return: + """ + try: + self.conn.text_factory = str + self.cur.execute('SELECT uuid FROM scan_history where source = "{config_section}"'.format(config_section=self.CONFIG_SECTION)) + results = frozenset([r[0] for r in self.cur.fetchall()]) + except: + results = [] + return results + +class vulnWhispererNessus(vulnWhispererBase): + + CONFIG_SECTION = 'nessus' + + def __init__( + self, + config=None, + db_name='report_tracker.db', + purge=False, + verbose=None, + debug=False, + username=None, + password=None, + ): + super(vulnWhispererNessus, self).__init__(config=config) + + self.port = int(self.config.get(self.CONFIG_SECTION, 'port')) + + self.develop = True + self.purge = purge + + if config is not None: + try: + self.nessus_port = self.config.get(self.CONFIG_SECTION, 'port') + + self.nessus_trash = self.config.getbool(self.CONFIG_SECTION, + 'trash') + + try: + self.vprint('{info} Attempting to connect to nessus...'.format(info=bcolors.INFO)) + self.nessus = \ + NessusAPI(hostname=self.hostname, + port=self.nessus_port, + username=self.username, + password=self.password) + self.nessus_connect = True + self.vprint('{success} Connected to nessus on {host}:{port}'.format(success=bcolors.SUCCESS, + host=self.hostname, + port=str(self.nessus_port))) + except Exception as e: + self.vprint(e) + raise Exception( + '{fail} Could not connect to nessus -- Please verify your settings in {config} are correct and try again.\nReason: {e}'.format( + config=self.config, + fail=bcolors.FAIL, e=e)) + except Exception as e: + + self.vprint('{fail} Could not properly load your config!\nReason: {e}'.format(fail=bcolors.FAIL, + e=e)) + sys.exit(0) + + + def scan_count(self, scans, completed=False): """ @@ -142,6 +212,7 @@ class vulnWhisperer(object): :param completed: Only return completed scans :return: """ + self.vprint('{info} Gathering all scan data... this may take a while...'.format(info=bcolors.INFO)) scan_records = [] for s in scans: @@ -159,14 +230,18 @@ class vulnWhisperer(object): record['uuid'] = h.get('uuid', '') record['status'] = h.get('status', '') record['history_id'] = h.get('history_id', '') - record['last_modification_date'] = h.get('last_modification_date', '') - record['norm_time'] = self.nessus.get_utc_from_local(int(record['last_modification_date']), - local_tz=self.nessus.tz_conv(record['timezone'])) + record['last_modification_date'] = \ + h.get('last_modification_date', '') + record['norm_time'] = \ + self.nessus.get_utc_from_local(int(record['last_modification_date' + ]), + local_tz=self.nessus.tz_conv(record['timezone' + ])) scan_records.append(record.copy()) - - except Exception as e: - #print(e) + # Generates error each time nonetype is encountered. + # print(e) + pass if completed: @@ -174,22 +249,6 @@ class vulnWhisperer(object): return scan_records - def record_insert(self, record): - self.cur.execute("insert into scan_history({table_columns}) values (?,?,?,?,?,?,?,?,?)".format( - table_columns=', '.join(self.table_columns)), record) - self.conn.commit() - - def retrieve_uuids(self): - """ - Retrieves UUIDs from database and checks list to determine which files need to be processed. - :return: - """ - self.conn.text_factory = str - self.cur.execute('select uuid from scan_history') - results = frozenset([r[0] for r in self.cur.fetchall()]) - return results - - def whisper_nessus(self): if self.nessus_connect: scan_data = self.nessus.get_scans() @@ -197,16 +256,20 @@ class vulnWhisperer(object): scans = scan_data['scans'] all_scans = self.scan_count(scans) if self.uuids: - scan_list = [scan for scan in all_scans if (scan['uuid'] not in self.uuids and scan['status']=='completed')] + scan_list = [scan for scan in all_scans if scan['uuid'] + not in self.uuids and scan['status'] + == 'completed'] else: scan_list = all_scans - self.vprint("{info} Identified {new} scans to be processed".format(info=bcolors.INFO, new=len(scan_list))) + self.vprint('{info} Identified {new} scans to be processed'.format(info=bcolors.INFO, + new=len(scan_list))) if not scan_list: - self.vprint("{info} No new scans to process. Exiting...".format(info=bcolors.INFO)) + self.vprint('{info} No new scans to process. Exiting...'.format(info=bcolors.INFO)) exit(0) # Create scan subfolders + for f in folders: if not os.path.exists(self.path_check(f['name'])): if f['name'] == 'Trash' and self.nessus_trash: @@ -216,25 +279,43 @@ class vulnWhisperer(object): else: os.path.exists(self.path_check(f['name'])) self.vprint('{info} Directory already exist for {scan} - Skipping creation'.format( - scan=self.path_check(f['name']), info=bcolors.INFO)) + scan=self.path_check(f['name' + ]), info=bcolors.INFO)) # try download and save scans into each folder the belong to + scan_count = 0 + # TODO Rewrite this part to go through the scans that have aleady been processed + for s in scan_list: scan_count += 1 - scan_name, scan_id, history_id,\ - norm_time, status, uuid = s['scan_name'], s['scan_id'], s['history_id'],\ - s['norm_time'], s['status'], s['uuid'] + ( + scan_name, + scan_id, + history_id, + norm_time, + status, + uuid, + ) = ( + s['scan_name'], + s['scan_id'], + s['history_id'], + s['norm_time'], + s['status'], + s['uuid'], + ) # TODO Create directory sync function which scans the directory for files that exist already and populates the database folder_id = s['folder_id'] scan_history = self.nessus.get_scan_history(scan_id) - folder_name = next(f['name'] for f in folders if f['id'] == folder_id) + folder_name = next(f['name'] for f in folders if f['id' + ] == folder_id) if status == 'completed': - file_name = '%s_%s_%s_%s.%s' % (scan_name, scan_id, history_id, norm_time, 'csv') - repls = ('\\', '_'), ('/', '_'), ('/', '_'), (' ', '_') + file_name = '%s_%s_%s_%s.%s' % (scan_name, scan_id, + history_id, norm_time, 'csv') + repls = (('\\', '_'), ('/', '_'), ('/', '_'), (' ', '_')) file_name = reduce(lambda a, kv: a.replace(*kv), repls, file_name) relative_path_name = self.path_check(folder_name + '/' + file_name) @@ -242,37 +323,311 @@ class vulnWhisperer(object): if self.develop: csv_in = pd.read_csv(relative_path_name) record_meta = ( - scan_name, scan_id, norm_time, file_name, time.time(), csv_in.shape[0], 'nessus', uuid, 1) + scan_name, + scan_id, + norm_time, + file_name, + time.time(), + csv_in.shape[0], + self.CONFIG_SECTION, + uuid, + 1, + ) self.record_insert(record_meta) self.vprint( - "{info} File {filename} already exist! Updating database".format(info=bcolors.INFO, filename=relative_path_name)) + '{info} File {filename} already exist! Updating database'.format(info=bcolors.INFO, + filename=relative_path_name)) else: - file_req = self.nessus.download_scan(scan_id=scan_id, history=history_id, export_format='csv') - clean_csv = pd.read_csv(io.StringIO(file_req.decode('utf-8'))) + file_req = \ + self.nessus.download_scan(scan_id=scan_id, + history=history_id, export_format='csv') + clean_csv = \ + pd.read_csv(io.StringIO(file_req.decode('utf-8' + ))) if len(clean_csv) > 2: - self.vprint("Processing %s/%s for scan: %s" % (scan_count, len(scan_history), scan_name)) - clean_csv['CVSS'] = clean_csv['CVSS'].astype(str).apply(self.cleanser) - clean_csv['CVE'] = clean_csv['CVE'].astype(str).apply(self.cleanser) - clean_csv['Description'] = clean_csv['Description'].astype(str).apply(self.cleanser) - clean_csv['Synopsis'] = clean_csv['Description'].astype(str).apply(self.cleanser) - clean_csv['Solution'] = clean_csv['Solution'].astype(str).apply(self.cleanser) - clean_csv['See Also'] = clean_csv['See Also'].astype(str).apply(self.cleanser) - clean_csv['Plugin Output'] = clean_csv['Plugin Output'].astype(str).apply(self.cleanser) - clean_csv.to_csv(relative_path_name, index=False) + self.vprint('Processing %s/%s for scan: %s' + % (scan_count, len(scan_list), + scan_name)) + columns_to_cleanse = ['CVSS','CVE','Description','Synopsis','Solution','See Also','Plugin Output'] + + for col in columns_to_cleanse: + clean_csv[col] = clean_csv[col].astype(str).apply(self.cleanser) + + clean_csv['Synopsis'] = \ + clean_csv['Description' + ].astype(str).apply(self.cleanser) + clean_csv.to_csv(relative_path_name, + index=False) record_meta = ( - scan_name, scan_id, norm_time, file_name, time.time(), clean_csv.shape[0], 'nessus', uuid, - 1) + scan_name, + scan_id, + norm_time, + file_name, + time.time(), + clean_csv.shape[0], + self.CONFIG_SECTION, + uuid, + 1, + ) self.record_insert(record_meta) - self.vprint("{info} {filename} records written to {path} ".format(info=bcolors.INFO, filename=clean_csv.shape[0], path=file_name)) + self.vprint('{info} {filename} records written to {path} '.format(info=bcolors.INFO, + filename=clean_csv.shape[ + 0], + path=file_name)) else: record_meta = ( - scan_name, scan_id, norm_time, file_name, time.time(), clean_csv.shape[0], 'nessus', uuid, - 1) + scan_name, + scan_id, + norm_time, + file_name, + time.time(), + clean_csv.shape[0], + self.CONFIG_SECTION, + uuid, + 1, + ) self.record_insert(record_meta) - self.vprint(file_name + ' has no host available... Updating database and skipping!') + self.vprint(file_name + + ' has no host available... Updating database and skipping!' + ) self.conn.close() - "{success} Scan aggregation complete! Connection to database closed.".format(success=bcolors.SUCCESS) - - + '{success} Scan aggregation complete! Connection to database closed.'.format(success=bcolors.SUCCESS) else: - self.vprint('{fail} Failed to use scanner at {host}'.format(fail=bcolors.FAIL, host=self.nessus_hostname+':'+self.nessus_port)) \ No newline at end of file + + self.vprint('{fail} Failed to use scanner at {host}'.format(fail=bcolors.FAIL, + host=self.hostname + ':' + + self.nessus_port)) + + +class vulnWhispererQualys(vulnWhispererBase): + + CONFIG_SECTION = 'qualys' + COLUMN_MAPPING = {'Access Path': 'access_path', + 'Ajax Request': 'ajax_request', + 'Ajax Request ID': 'ajax_request_id', + 'Authentication': 'authentication', + 'CVSS Base': 'cvss', + 'CVSS Temporal': 'cvss_temporal', + 'CWE': 'cwe', + 'Category': 'category', + 'Content': 'content', + 'DescriptionSeverity': 'severity_description', + 'DescriptionCatSev': 'category_description', + 'Detection ID': 'detection_id', + 'Evidence #1': 'evidence_1', + 'First Time Detected': 'first_time_detected', + 'Form Entry Point': 'form_entry_point', + 'Function': 'function', + 'Groups': 'groups', + 'ID': 'id', + 'Ignore Comments': 'ignore_comments', + 'Ignore Date': 'ignore_date', + 'Ignore Reason': 'ignore_reason', + 'Ignore User': 'ignore_user', + 'Ignored': 'ignored', + 'Impact': 'impact', + 'Last Time Detected': 'last_time_detected', + 'Last Time Tested': 'last_time_tested', + 'Level': 'level', + 'OWASP': 'owasp', + 'Operating System': 'operating_system', + 'Owner': 'owner', + 'Param': 'param', + 'Payload #1': 'payload_1', + 'QID': 'plugin_id', + 'Request Headers #1': 'request_headers_1', + 'Request Method #1': 'request_method_1', + 'Request URL #1': 'request_url_1', + 'Response #1': 'response_1', + 'Scope': 'scope', + 'Severity': 'risk', + 'Severity Level': 'security_level', + 'Solution': 'solution', + 'Times Detected': 'times_detected', + 'Title': 'plugin_name', + 'URL': 'url', + 'Url': 'uri', + 'Vulnerability Category': 'vulnerability_category', + 'WASC': 'wasc', + 'Web Application Name': 'web_application_name'} + def __init__( + self, + config=None, + db_name='report_tracker.db', + purge=False, + verbose=None, + debug=False, + username=None, + password=None, + ): + + super(vulnWhispererQualys, self).__init__(config=config, ) + + self.qualys_scan = qualysScanReport(config=config) + self.latest_scans = self.qualys_scan.qw.get_all_scans() + self.directory_check() + self.scans_to_process = None + + + def directory_check(self): + if not os.path.exists(self.write_path): + os.makedirs(self.write_path) + self.vprint('{info} Directory created at {scan} - Skipping creation'.format( + scan=self.write_path, info=bcolors.INFO)) + else: + os.path.exists(self.write_path) + self.vprint('{info} Directory already exist for {scan} - Skipping creation'.format( + scan=self.write_path, info=bcolors.INFO)) + + def whisper_reports(self, + report_id=None, + launched_date=None, + scan_name=None, + scan_reference=None, + output_format='json', + cleanup=True): + """ + report_id: App ID + updated_date: Last time scan was ran for app_id + """ + vuln_ready = None + + try: + if 'Z' in launched_date: + launched_date = self.qualys_scan.utils.iso_to_epoch(launched_date) + report_name = 'qualys_web_' + str(report_id) \ + + '_{last_updated}'.format(last_updated=launched_date) \ + + '.{extension}'.format(extension=output_format) + + relative_path_name = self.path_check(report_name) + + if os.path.isfile(relative_path_name): + #TODO Possibly make this optional to sync directories + file_length = len(open(relative_path_name).readlines()) + record_meta = ( + scan_name, + scan_reference, + launched_date, + report_name, + time.time(), + file_length, + self.CONFIG_SECTION, + report_id, + 1, + ) + self.record_insert(record_meta) + self.vprint('{info} File {filename} already exist! Updating database'.format(info=bcolors.INFO, filename=relative_path_name)) + + else: + print('{action} - Generating report for %s'.format(action=bcolors.ACTION) % report_id) + status = self.qualys_scan.qw.create_report(report_id) + root = objectify.fromstring(status) + if root.responseCode == 'SUCCESS': + print('{info} - Successfully generated report! ID: %s'.format(info=bcolors.INFO) \ + % report_id) + generated_report_id = root.data.Report.id + print('{info} - New Report ID: %s'.format(info=bcolors.INFO) \ + % generated_report_id) + + vuln_ready = self.qualys_scan.process_data(path=self.write_path, file_id=str(generated_report_id)) + + vuln_ready.to_csv(relative_path_name, index=False, header=True) # add when timestamp occured + vuln_ready.rename(columns=self.COLUMN_MAPPING, inplace=True) + + record_meta = ( + scan_name, + scan_reference, + launched_date, + report_name, + time.time(), + vuln_ready.shape[0], + self.CONFIG_SECTION, + report_id, + 1, + ) + self.record_insert(record_meta) + + if output_format == 'json': + with open(relative_path_name, 'w') as f: + f.write(vuln_ready.to_json(orient='records', lines=True)) + + elif output_format == 'csv': + vuln_ready.to_csv(relative_path_name, index=False, header=True) # add when timestamp occured + + print('{success} - Report written to %s'.format(success=bcolors.SUCCESS) \ + % report_name) + + if cleanup: + print('{action} - Removing report %s from Qualys Database'.format(action=bcolors.ACTION) \ + % generated_report_id) + cleaning_up = \ + self.qualys_scan.qw.delete_report(generated_report_id) + os.remove(self.path_check(str(generated_report_id) + '.csv')) + print('{action} - Deleted report from local disk: %s'.format(action=bcolors.ACTION) \ + % self.path_check(str(generated_report_id))) + else: + print('{error} Could not process report ID: %s'.format(error=bcolors.FAIL) % status) + + except Exception as e: + print('{error} - Could not process %s - %s'.format(error=bcolors.FAIL) % (report_id, e)) + return vuln_ready + + + def identify_scans_to_process(self): + if self.uuids: + self.scans_to_process = self.latest_scans[~self.latest_scans['id'].isin(self.uuids)] + else: + self.scans_to_process = self.latest_scans + self.vprint('{info} Identified {new} scans to be processed'.format(info=bcolors.INFO, + new=len(self.scans_to_process))) + + + def process_web_assets(self): + counter = 0 + self.identify_scans_to_process() + if self.scans_to_process.shape[0]: + for app in self.scans_to_process.iterrows(): + counter += 1 + r = app[1] + print('Processing %s/%s' % (counter, len(self.scans_to_process))) + self.whisper_reports(report_id=r['id'], + launched_date=r['launchedDate'], + scan_name=r['name'], + scan_reference=r['reference']) + else: + self.vprint('{info} No new scans to process. Exiting...'.format(info=bcolors.INFO)) + self.conn.close() + exit(0) + + + + + +class vulnWhisperer(object): + + def __init__(self, + profile=None, + verbose=None, + username=None, + password=None, + config=None): + + self.profile = profile + self.config = config + self.username = username + self.password = password + self.verbose = verbose + + + def whisper_vulnerabilities(self): + + if self.profile == 'nessus': + vw = vulnWhispererNessus(config=self.config, + username=self.username, + password=self.password, + verbose=self.verbose) + vw.whisper_nessus() + + elif self.profile == 'qualys': + vw = vulnWhispererQualys(config=self.config) + vw.process_web_assets() \ No newline at end of file