diff --git a/.gitignore b/.gitignore index 1e788cb1852089d59aae33e59d76809676604c59..ffd7e372182e1205917b047c9d84b42201bab7be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ **.swp wiser-wcs-reports/.idea/* wiser-wcs-reports/env/* -wiser-wcs-reports/example_nmap_output/* wiser-wcs-reports/__pycache__/* +wiser-wcs-reports/example_output/* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fc4459fbe61fb96282ef61d3048a7df4303fdf34..695f9519a793b785785addfa5b9fbf152b35ec0d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,15 +18,18 @@ test: script: - docker network create test-genscan - docker run --rm -d --network=test-genscan --name dvwa vulnerables/web-dvwa - - cp "${CI_PROJECT_DIR}/config-example.json" /tmp - - docker run --rm --network=test-genscan -e TARGET="http://dvwa/" -v /tmp/:/root/out registry-gitlab.xlab.si/cyberwiser/$SERVICE:$VERSION - - cat /tmp/cscan-log.txt - - grep -q "W3af" /tmp/genscan-out.json - - grep -q "OWASP ZAP" /tmp/genscan-out.json + - cp "${CI_PROJECT_DIR}/config-example.json" /tmp/ + - mkdir /tmp/out + - docker run --rm --network=test-genscan -v /tmp/config-example.json:/root/config.json -v /tmp/out:/root/out registry-gitlab.xlab.si/cyberwiser/$SERVICE:$VERSION + - cat /tmp/out/cscan-log.txt + - grep -q "W3af" /tmp/out/genscan-out.json + - grep -q "OWASP ZAP" /tmp/out/genscan-out.json + - grep -q "nmap" /tmp/out/genscan-out.json after_script: - docker kill dvwa || docker network rm test-genscan - docker network rm test-genscan - - rm /tmp/genscan-out.json + - rm /tmp/genscan-out.json || true + - rm -rf /tmp/out push: stage: push diff --git a/Dockerfile b/Dockerfile index 080376663d83e571b3d3f57a00e1b233b5480ffe..fd0dd04ab99e435e8ffbc1d2de3fb7432d401c05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,8 @@ COPY wiser-wcs-reports /service/wiser-wcs-reports/ COPY install/wiser-wcs.sh /tmp/install/ RUN chmod +x /tmp/install/wiser-wcs.sh && /tmp/install/wiser-wcs.sh +RUN apt install -y nmap + COPY install/cleanup.sh /tmp/install/ RUN chmod +x /tmp/install/cleanup.sh && /tmp/install/cleanup.sh diff --git a/MANIFEST b/MANIFEST index cd8acda39449e1dd0a4b9a1469ee978986311fa6..f5fd3aad31471eba9c53d0472377ec6e8c4fdc2d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,3 +1,3 @@ -VERSION=v1.3.4 +VERSION=v1.4.0 SERVICE=vat-genscan diff --git a/Makefile b/Makefile index d170f2f3b32a1f06dc7ba370a6f1070a0e5164f4..c221fc92a4870766e3934ab05a28ba73ced5bd73 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ test: docker network rm test-genscan grep -q "W3af" $(TEST_DIR)genscan-out.json grep -q "OWASP ZAP" $(TEST_DIR)genscan-out.json + grep -q "nmap" $(TEST_DIR)genscan-out.json start: ifdef OUTPUT_DIR diff --git a/README.md b/README.md index 0e3b424cc8bb3a98571441e6f1ae0a2f2aaba8e0..4cbaf2ac78164cbf30c6138618fcb646ed05f2c7 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ Supported scanners and their profiles: * `fast_scan`: no parameters * `zap` * `basic`: no parameters +* `nmap` + * `basic_discovery`: no parameters Example JSON config file: @@ -35,6 +37,9 @@ Example JSON config file: }, "zap": { "profile": "basic" + }, + "nmap": { + "profile": "basic_discovery" } } } @@ -42,8 +47,6 @@ Example JSON config file: ### TODOs and FIXMEs: -* use latest w3af and zap (now fetching static, old commits) -* use cscan from Faraday repo (newer?) * include some configuration options (at least authenticated scans for w3af) diff --git a/config-example.json b/config-example.json index fed87a25babb48bb8698576dfd73fc876048c969..9f61d529fc69cc8a872189bcded19a615fb65382 100644 --- a/config-example.json +++ b/config-example.json @@ -1,6 +1,7 @@ { "target": { - "url": "http://dvwa/" + "url": "http://dvwa/", + "ip": "dvwa" }, "config": { "w3af": { @@ -8,6 +9,9 @@ }, "zap": { "profile": "basic" + }, + "nmap": { + "profile": "basic_discovery" } } } diff --git a/configure.py b/configure.py index 800fb44b4d1d92575388702ff872c86605d5fc8b..6e27c9875b1bc5c45041526789709789d28ebe17 100644 --- a/configure.py +++ b/configure.py @@ -6,6 +6,7 @@ import configparser Supported scanners: - w3af - zap + - nmap ''' @@ -49,6 +50,13 @@ def configure(): if profile != "basic": raise UnsupportedProfileException() cs_scripts.append("zap.sh") + elif scanner == "nmap": + cscan_config["NMAP"] = {"CS_NMAP": "nmap"} + if profile == "basic_discovery": + cscan_config["NMAP"]["CS_NMAP_ARGS"] = "-sV" + else: + raise UnsupportedProfileException() + cs_scripts.append("nmap.sh") else: raise UnsupportedScannerException() diff --git a/wiser-wcs-reports/main.py b/wiser-wcs-reports/main.py index e446e39dec42a63455de78fe0715c6426d6920ab..60e3d00f9463eb67778bd2cc69a0bce35ed6e7ad 100644 --- a/wiser-wcs-reports/main.py +++ b/wiser-wcs-reports/main.py @@ -6,6 +6,7 @@ import configparser import json import w3af import zap +import nmap class Options(object): @@ -55,6 +56,8 @@ def list_vulnerabilities(reports): vulnerabilities.extend(zap.WiserZapReport(report_dict['OWASPZAPReport']).get_report()) if "w3af-run" in report_dict: vulnerabilities.extend(w3af.WiserW3afReport(report_dict['w3af-run']).get_report()) + if "nmaprun" in report_dict: + vulnerabilities.extend(nmap.WiserNmapReport(report_dict['nmaprun']).get_report()) return vulnerabilities if __name__ == "__main__": diff --git a/wiser-wcs-reports/nmap.py b/wiser-wcs-reports/nmap.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..690c3bbf8ac7865a6ff0cdda0334ce9fcb4d6a3b 100644 --- a/wiser-wcs-reports/nmap.py +++ b/wiser-wcs-reports/nmap.py @@ -0,0 +1,75 @@ +from wiser import WiserReport, WiserVulnerability +from collections import OrderedDict +import re + + +def _safe_get(ordered_dict, key): + try: + return ordered_dict[key] + except KeyError: + return "" + + +class WiserNmapVulnerability(WiserVulnerability): + + def __init__(self): + super().__init__() + self.risk_level = "Information" + self.source_pentest = "nmap" + self.w_risk_level = 1 + + @staticmethod + def from_port_report(report_port, address): + vuln = WiserNmapVulnerability() + vuln.short_desc = "Port %d on host %s is %s." % (report_port['@portid'], + address, + report_port['state']['@state']) + vuln.desc = '' + if 'service' in report_port: + vuln.desc = "Host %s is likely running the following service on port %d %s: " \ + "%s %s %s (%s) (%s) " \ + % (address, report_port['@portid'], report_port['@protocol'], + _safe_get(report_port['service'], '@name'), _safe_get(report_port['service'], '@product'), + _safe_get(report_port['service'], '@version'), _safe_get(report_port['service'], '@extrainfo'), + _safe_get(report_port['service'], '@ostype')) + vuln.desc = re.sub('\\(\\)', '', vuln.desc).strip() + return vuln + + @staticmethod + def from_host(address, state): + vuln = WiserNmapVulnerability() + vuln.short_desc = "Host %s appears to be %s." % (address, state) + return vuln + + +class WiserNmapReport(WiserReport): + + def __init__(self, report): + super().__init__() + self.parse_report(report) + + def parse_report(self, report_dict): + if isinstance(report_dict['host'], OrderedDict): + self.parse_host(report_dict['host']) + else: + for i in report_dict['host']: + self.parse_host(i) + + def parse_host(self, report_host): + address = '' + if isinstance(report_host['address'], OrderedDict): + address = report_host['address']['@addr'] + else: + for i in report_host['address']: + if i['@addrtype'] == 'ipv4': + address = i['@addr'] + break + + if 'port' in report_host['ports']: + if isinstance(report_host['ports']['port'], OrderedDict): + self.report.append(WiserNmapVulnerability.from_port_report(report_host['ports']['port'], address)) + else: + for i in report_host['ports']['port']: + self.report.append(WiserNmapVulnerability.from_port_report(i, address)) + else: + self.report.append(WiserNmapVulnerability.from_host(address, report_host['status']['@state'])) diff --git a/wiser-wcs-reports/wiser.py b/wiser-wcs-reports/wiser.py index 597ef1978fb8302ec2498b13897cc650c3a0587f..02ae0249b8f9238df1de656c04895cf196a78028 100644 --- a/wiser-wcs-reports/wiser.py +++ b/wiser-wcs-reports/wiser.py @@ -32,12 +32,6 @@ class WiserVulnerability(IterMixin): def __init__(self): pass - def parse_from_alert(self, alert_dict, type): - pass - - def parse_report(self, report_dict): - pass - """ Sets WISER risk level to the Vulnerability. """