From 8ba0a59ebb78e420869424263a061211f868f255 Mon Sep 17 00:00:00 2001 From: sw <shadow.bfs@gmail.com> Date: Sun, 8 Mar 2020 04:23:26 +0300 Subject: [PATCH] new report formats and arguments to use them --- Makefile | 11 +++++++- README.md | 9 ++++++- contrib/internal_types/flan_types.py | 8 ++++++ contrib/report_builders/__init__.py | 2 ++ contrib/report_builders/report_builder.py | 18 ------------- kubernetes_templates/cron_job.yaml | 2 ++ kubernetes_templates/deployment.yaml | 2 ++ output_report.py | 31 +++++++++++++++-------- requirements.txt | 1 + run.sh | 20 +++++++++++---- 10 files changed, 68 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index d073f5b..0ed0bd0 100644 --- a/Makefile +++ b/Makefile @@ -3,4 +3,13 @@ build : container_name = flan_$(shell date +'%s') start : - docker run --name $(container_name) -v "$(pwd)/shared:/shared:Z" flan_scan + docker run --name $(container_name) -v "$(shell pwd)/shared:/shared:Z" flan_scan + +md : + docker run --name $(container_name) -v "$(shell pwd)/shared:/shared:Z" -e format=md flan_scan + +html : + docker run --name $(container_name) -v "$(shell pwd)/shared:/shared:Z" -e format=html flan_scan + +json : + docker run --name $(container_name) -v "$(shell pwd)/shared:/shared:Z" -e format=json flan_scan diff --git a/README.md b/README.md index 260c26f..d144fb3 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,12 @@ $ make build $ make start ``` +6. To use another output format: +``` +$ make html +``` +Additional supported formats are *md* (markdown), *html* and *json*. + When the scan finishes you will find a Latex report of the summarizing the scan in `shared/reports`. You can also see the raw XML output from Nmap in `shared/xml_files`. <div> @@ -42,7 +48,7 @@ $ nmap -sV -oX /shared/xml_files -oN - -v1 $@ --script=vulners/vulners.nse <ip-a ``` The `-oX` flag adds an XML version of the scan results to the `/shared/xml_files` directory and the `-oN -` flag outputs "normal" Nmap results to the console. The `-v1` flag increases the verbosity to 1 and the `-sV` flag runs a service detection scan (aside from Nmap's default port and SYN scans). The `--script=vulners/vulners.nse` is the script that matches the services detected with relevant CVEs. -Nmap also allows you to run UDP scans and to scan IPv6 addresses. To add these and other flags to Scan Flan's Nmap command after running `make build` run the container and pass in you Nmap flags like so: +Nmap also allows you to run UDP scans and to scan IPv6 addresses. To add these and other flags to Scan Flan's Nmap command after running `make build` run the container and pass in your Nmap flags like so: ```bash $ docker run -v $(pwd)/shared:/shared flan_scan <Nmap-flags> @@ -57,6 +63,7 @@ $ docker run --name <container-name> \ -v $(pwd)/shared:/shared \ -e upload=<gcp or aws> \ -e bucket=<bucket-name> \ + -e format=<optional, one of: md, html or json> \ flan_scan ``` diff --git a/contrib/internal_types/flan_types.py b/contrib/internal_types/flan_types.py index f1c0da4..fb63476 100644 --- a/contrib/internal_types/flan_types.py +++ b/contrib/internal_types/flan_types.py @@ -22,6 +22,14 @@ class Vuln: self.vuln_type = vuln_type self.severity = severity + def to_dict(self): + return { + 'name': self.name, + 'type': self.vuln_type, + 'severity': self.severity, + 'severity_str': self.severity_str + } + @staticmethod def convert_severity(severity: float) -> str: """ diff --git a/contrib/report_builders/__init__.py b/contrib/report_builders/__init__.py index 5db2353..ca8cb01 100644 --- a/contrib/report_builders/__init__.py +++ b/contrib/report_builders/__init__.py @@ -1,3 +1,5 @@ from .report_builder import ReportBuilder from .latex_report_builder import LatexReportBuilder from .markdown_report_builder import MarkdownReportBuilder +from .json_report_builder import JsonReportBuilder +from .html_report_builder import JinjaHtmlReportBuilder diff --git a/contrib/report_builders/report_builder.py b/contrib/report_builders/report_builder.py index 006b361..ed452cb 100644 --- a/contrib/report_builders/report_builder.py +++ b/contrib/report_builders/report_builder.py @@ -8,80 +8,62 @@ __all__ = ['ReportBuilder'] class ReportBuilder(metaclass=abc.ABCMeta): - @abc.abstractmethod def init_report(self, start_date: str, nmap_command: str): """ Creates document section with report overview """ pass - @abc.abstractmethod def build(self) -> Any: """ :return: Ready report in specific format """ pass - @abc.abstractmethod def add_vulnerable_section(self): """ Adds header for section with vulnerable services """ pass - @abc.abstractmethod def add_non_vulnerable_section(self): """ Adds header for section with services without detected vulnerabilities """ pass - @abc.abstractmethod def add_vulnerable_services(self, scan_results: Dict[str, ScanResult]): """ Adds descriptions of vulnerable services """ pass - @abc.abstractmethod def add_non_vulnerable_services(self, scan_results: Dict[str, ScanResult]): """ Adds descriptions of services without detected vulnerabilities """ pass - @abc.abstractmethod def initialize_section(self): """ Adds begin of report section """ pass - @abc.abstractmethod def add_ips_section(self): """ Adds section with list of scanned ip addresses """ pass - @abc.abstractmethod def add_ip_address(self, ip: str): """ Adds IP-address to scanned addresses section """ pass - @abc.abstractmethod def finalize(self): """ Adds report footer """ pass - - @property - @abc.abstractmethod - def header(self) -> Any: - """ - :return: Common document header for format type (e.g. for latex report) - """ - pass diff --git a/kubernetes_templates/cron_job.yaml b/kubernetes_templates/cron_job.yaml index 36f41f9..b920dda 100644 --- a/kubernetes_templates/cron_job.yaml +++ b/kubernetes_templates/cron_job.yaml @@ -33,3 +33,5 @@ spec: value: <GCP_OR_AWS> - name: bucket value: <BUCKET_NAME> + - name: format + value: <REPORT_FORMAT> diff --git a/kubernetes_templates/deployment.yaml b/kubernetes_templates/deployment.yaml index e1fa560..d593f24 100644 --- a/kubernetes_templates/deployment.yaml +++ b/kubernetes_templates/deployment.yaml @@ -35,3 +35,5 @@ spec: value: <GCP_OR_AWS> - name: bucket value: <BUCKET_NAME> + - name: format + value: <REPORT_FORMAT> diff --git a/output_report.py b/output_report.py index 2f5b45e..42ecc54 100644 --- a/output_report.py +++ b/output_report.py @@ -4,9 +4,10 @@ from typing import IO from requests import Session -from contrib.descriptions import CveProjectProvider +from contrib.descriptions import CveProjectProvider, VulnDescriptionProvider from contrib.parsers import FlanXmlParser -from contrib.report_builders import ReportBuilder, LatexReportBuilder, MarkdownReportBuilder +from contrib.report_builders import ReportBuilder, LatexReportBuilder, MarkdownReportBuilder, JinjaHtmlReportBuilder, \ + JsonReportBuilder def create_report(parser: FlanXmlParser, builder: ReportBuilder, nmap_command: str, start_date: str, output_writer: IO, @@ -26,7 +27,7 @@ def create_report(parser: FlanXmlParser, builder: ReportBuilder, nmap_command: s builder.add_ips_section() for ip in ip_reader: - builder.add_ip_address(ip) + builder.add_ip_address(ip.strip()) builder.finalize() output_writer.write(builder.build()) @@ -38,19 +39,26 @@ def parse_nmap_command(raw_command: str) -> str: return ' '.join(nmap_split) -def create_default_provider(): +def create_default_provider() -> VulnDescriptionProvider: return CveProjectProvider(Session()) def create_report_builder(report_type: str) -> ReportBuilder: - if report_type == 'latex': - return LatexReportBuilder(create_default_provider()) - if report_type == 'md': - return MarkdownReportBuilder(create_default_provider()) - raise NotImplementedError(report_type) + builder_map = { + 'tex': lambda p: LatexReportBuilder(p), + 'md': lambda p: MarkdownReportBuilder(p), + 'html': lambda p: JinjaHtmlReportBuilder(p), + 'json': lambda p: JsonReportBuilder(p) + } + if report_type not in builder_map: + raise NotImplementedError(report_type) -def main(dirname: str, output_file: str, ip_file: str, report_type: str = 'latex'): + provider = create_default_provider() + return builder_map[report_type](provider) + + +def main(dirname: str, output_file: str, ip_file: str, report_type: str = 'tex'): nmap_command = '' start_date = '' builder = create_report_builder(report_type) @@ -69,4 +77,5 @@ def main(dirname: str, output_file: str, ip_file: str, report_type: str = 'latex if __name__ == '__main__': - main(*sys.argv[1:4], report_type='latex') + report_format = os.getenv('format', 'tex') + main(*sys.argv[1:4], report_type=report_format) diff --git a/requirements.txt b/requirements.txt index 82928b9..aced391 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ xmltodict==0.12.0 google-cloud-storage==1.23.0 boto3==1.12.15 +Jinja2==2.10.3 \ No newline at end of file diff --git a/run.sh b/run.sh index 77ec6d0..dcbcdf2 100755 --- a/run.sh +++ b/run.sh @@ -10,8 +10,15 @@ else mkdir /reports fi +report_extension="tex" + +if [[ ! -z $format ]] +then + report_extension=$format +fi + xml_dir=xml_files/$current_time -report_file=reports/report_$current_time.tex +report_file=reports/report_$current_time.$report_extension function upload { if [[ -z $upload ]] @@ -40,8 +47,11 @@ do done < /shared/ips.txt python /output_report.py $root_dir$xml_dir $root_dir$report_file /shared/ips.txt -sed -i 's/_/\\_/g' $root_dir$report_file -sed -i 's/\$/\\\$/g' $root_dir$report_file -sed -i 's/#/\\#/g' $root_dir$report_file -sed -i 's/%/\\%/g' $root_dir$report_file +if [[ $report_extension = "tex" ]] +then + sed -i 's/_/\\_/g' $root_dir$report_file + sed -i 's/\$/\\\$/g' $root_dir$report_file + sed -i 's/#/\\#/g' $root_dir$report_file + sed -i 's/%/\\%/g' $root_dir$report_file +fi upload $report_file -- GitLab