Projects STRLCPY flan Commits 827aa432
🤬
  • vulnerability descriptions with urls and markdown report generator

  • Loading...
  • shadow committed 4 years ago
    827aa432
    1 parent 520e7bb3
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■
    contrib/descriptions/__init__.py
    1  -from .description_provider import VulnDescriptionProvider
     1 +from .description_provider import VulnDescription, VulnDescriptionProvider
    2 2  from .cveproject import CveProjectProvider
    3 3   
  • ■ ■ ■ ■ ■ ■
    contrib/descriptions/cveproject.py
    1 1  from requests import Session, HTTPError
    2 2   
    3  -from contrib.descriptions import VulnDescriptionProvider
    4  - 
     3 +from contrib.descriptions import VulnDescriptionProvider, VulnDescription
    5 4   
    6 5  __all__ = ['CveProjectProvider']
    7 6   
    skipped 8 lines
    16 15   self.sess = session
    17 16   self.cache = {}
    18 17   
    19  - def get_description(self, vuln: str, vuln_type: str) -> str:
     18 + def get_description(self, vuln: str, vuln_type: str) -> VulnDescription:
    20 19   if vuln in self.cache:
    21 20   return self.cache[vuln]
    22 21   
    skipped 7 lines
    30 29   cve_json = response.json()
    31 30   description = cve_json['description']['description_data'][0]['value']
    32 31   self.cache[vuln] = description
    33  - return description
     32 + return VulnDescription(description, url)
    34 33   except HTTPError as he:
    35  - return 'Description fetching error: ' + str(he)
     34 + return VulnDescription('', 'Description fetching error: ' + str(he))
    36 35   
    37  - return ''
     36 + return VulnDescription('', '')
    38 37   
  • ■ ■ ■ ■ ■
    contrib/descriptions/description_provider.py
    1 1  import abc
     2 +from typing import Optional
    2 3   
    3  -__all__ = ['VulnDescriptionProvider']
     4 +__all__ = ['VulnDescriptionProvider', 'VulnDescription']
     5 + 
     6 + 
     7 +class VulnDescription:
     8 + def __init__(self, text: str, url: Optional[str] = None):
     9 + self.text = text
     10 + self.url = url
    4 11   
    5 12   
    6 13  class VulnDescriptionProvider(metaclass=abc.ABCMeta):
    skipped 1 lines
    8 15   Provides extended vulnerability description by vulnerablity identifier and type
    9 16   """
    10 17   @abc.abstractmethod
    11  - def get_description(self, vuln: str, vuln_type: str) -> str:
     18 + def get_description(self, vuln: str, vuln_type: str) -> VulnDescription:
    12 19   pass
    13 20   
  • ■ ■ ■ ■ ■ ■
    contrib/internal_types/flan_types.py
    1 1  from collections import defaultdict
    2  - 
     2 +from typing import List, Dict
    3 3   
    4 4  __all__ = ['SeverityLevels', 'Vuln', 'ScanResult']
    5 5   
    skipped 40 lines
    46 46   Scan result representation
    47 47   """
    48 48   def __init__(self):
    49  - self.locations = defaultdict(list)
    50  - self.vulns = []
     49 + self.locations = defaultdict(list) # type: Dict[str, List[str]]
     50 + self.vulns = [] # type: List[Vuln]
    51 51   
  • ■ ■ ■ ■ ■
    contrib/report_builders/__init__.py
    1 1  from .report_builder import ReportBuilder
    2 2  from .latex_report_builder import LatexReportBuilder
     3 +from .markdown_report_builder import MarkdownReportBuilder
    3 4   
  • ■ ■ ■ ■ ■ ■
    contrib/report_builders/latex_report_builder.py
    skipped 41 lines
    42 42   locations = report.locations
    43 43   num_vulns = len(vulns)
    44 44   
    45  - for i, v in enumerate(vulns):
     45 + for v in vulns:
     46 + description = self.description_provider.get_description(v.name, v.vuln_type)
    46 47   severity_name = v.severity_str
    47 48   self._append('\\begin{figure}[h!]\n')
    48 49   self._append('\\begin{tabular}{|p{16cm}|}\\rowcolor[HTML]{'
    skipped 1 lines
    50 51   + '} \\begin{tabular}{@{}p{15cm}>{\\raggedleft\\arraybackslash} p{0.5cm}@{}}\\textbf{'
    51 52   + v.name + ' ' + severity_name + ' ('
    52 53   + str(v.severity)
    53  - + ')} & \href{https://nvd.nist.gov/vuln/detail/'
    54  - + v.name + '}{\large \\faicon{link}}'
     54 + + ')} & \href{' + description.url
     55 + + '}{\large \\faicon{link}}'
    55 56   + '\end{tabular}\\\\\n Summary:'
    56  - + self.description_provider.get_description(v.name, v.vuln_type)
     57 + + description.text
    57 58   + '\\\\ \hline \end{tabular} ')
    58 59   self._append('\end{figure}\n')
    59 60   
    skipped 67 lines
  • ■ ■ ■ ■ ■ ■
    contrib/report_builders/markdown_report_builder.py
     1 +from datetime import datetime
     2 +from typing import Any, Dict, List
     3 + 
     4 +from contrib.descriptions import VulnDescriptionProvider
     5 +from contrib.internal_types import ScanResult
     6 +from contrib.report_builders import ReportBuilder
     7 + 
     8 +__all__ = ['MarkdownReportBuilder']
     9 + 
     10 + 
     11 +class MarkdownReportBuilder(ReportBuilder):
     12 + def __init__(self, description_provider: VulnDescriptionProvider):
     13 + self.description_provider = description_provider
     14 + self._buffer = ''
     15 + 
     16 + def init_report(self, start_date: str, nmap_command: str):
     17 + self._append_line(self.header)
     18 + self._append_line('## {date:%B %d, %Y}'.format(date=datetime.utcnow()))
     19 + self._append_line('### **Summary**')
     20 + self._append_line('Flan Scan ran a network vulnerability scan with the following Nmap command on {date}'
     21 + .format(date=start_date))
     22 + self._append_line('`{command}`'.format(command=nmap_command))
     23 + 
     24 + def build(self) -> Any:
     25 + return self._buffer
     26 + 
     27 + def add_vulnerable_section(self):
     28 + self._append_line('### Services with vulnerabilities')
     29 + 
     30 + def add_non_vulnerable_section(self):
     31 + self._append_line('### Services with no *known* vulnerabilities')
     32 + 
     33 + def add_vulnerable_services(self, scan_results: Dict[str, ScanResult]):
     34 + for i, pair in enumerate(scan_results.items(), start=1):
     35 + app_name, report = pair # type: str, ScanResult
     36 + self._append_service(i, app_name)
     37 + num_vulns = len(report.vulns)
     38 + 
     39 + for v in report.vulns:
     40 + description = self.description_provider.get_description(v.name, v.vuln_type)
     41 + self._append_line('- [**{name}** {severity} ({severity_num})]({link} "{title}")'
     42 + .format(name=v.name, severity=v.severity_str, severity_num=v.severity,
     43 + link=description.url, title=v.name), spaces=4)
     44 + self._append_line('```text', separators=1, spaces=6)
     45 + self._append_line(description.text, separators=1, spaces=6)
     46 + self._append_line('```', spaces=6)
     47 + 
     48 + self._append_line('The above {num} vulnerabilities apply to these network locations'.format(num=num_vulns),
     49 + spaces=4)
     50 + self._append_line('```text', separators=1, spaces=4)
     51 + for addr, ports in report.locations.items():
     52 + self._append_location(addr, ports, spaces=4)
     53 + self._append_line('```', spaces=4)
     54 + 
     55 + def add_non_vulnerable_services(self, scan_results: Dict[str, ScanResult]):
     56 + for i, pair in enumerate(scan_results.items(), start=1):
     57 + app_name, report = pair # type: str, ScanResult
     58 + self._append_service(i, app_name)
     59 + 
     60 + for addr, ports in report.locations.items():
     61 + self._append_location(addr, ports, spaces=4)
     62 + self._append('\n')
     63 + 
     64 + def initialize_section(self):
     65 + pass
     66 + 
     67 + def add_ips_section(self):
     68 + self._append_line('### List of IPs Scanned')
     69 + 
     70 + def add_ip_address(self, ip: str):
     71 + self._append_line('- {ip}'.format(ip=ip), separators=1)
     72 + 
     73 + def finalize(self):
     74 + pass
     75 + 
     76 + @property
     77 + def header(self) -> Any:
     78 + return '# Flan scan report'
     79 + 
     80 + def _append(self, text: str, spaces: int = 0):
     81 + if spaces:
     82 + self._buffer += ' ' * spaces
     83 + self._buffer += text
     84 + 
     85 + def _append_line(self, text: str, separators: int = 2, spaces: int = 0):
     86 + self._append(text, spaces)
     87 + self._append('\n' * separators)
     88 + 
     89 + def _append_service(self, index: int, name: str, spaces: int = 0):
     90 + self._append_line('{index}. **{service}**'.format(index=index, service=name.strip()), spaces=spaces,
     91 + separators=1)
     92 + 
     93 + def _append_location(self, address: str, ports: List[str], spaces: int):
     94 + self._append_line('- {address} Ports: {ports}'.format(address=address, ports=', '.join(ports)), spaces=spaces,
     95 + separators=1)
     96 + 
  • ■ ■ ■ ■ ■ ■
    output_report.py
    skipped 5 lines
    6 6   
    7 7  from contrib.descriptions import CveProjectProvider
    8 8  from contrib.parsers import FlanXmlParser
    9  -from contrib.report_builders import ReportBuilder, LatexReportBuilder
     9 +from contrib.report_builders import ReportBuilder, LatexReportBuilder, MarkdownReportBuilder
    10 10   
    11 11   
    12 12  def create_report(parser: FlanXmlParser, builder: ReportBuilder, nmap_command: str, start_date: str, output_writer: IO,
    skipped 25 lines
    38 38   return ' '.join(nmap_split)
    39 39   
    40 40   
     41 +def create_default_provider():
     42 + return CveProjectProvider(Session())
     43 + 
     44 + 
    41 45  def create_report_builder(report_type: str) -> ReportBuilder:
    42 46   if report_type == 'latex':
    43  - session = Session()
    44  - description_provider = CveProjectProvider(session)
    45  - report_bilder = LatexReportBuilder(description_provider)
    46  - return report_bilder
     47 + return LatexReportBuilder(create_default_provider())
     48 + if report_type == 'md':
     49 + return MarkdownReportBuilder(create_default_provider())
    47 50   raise NotImplementedError(report_type)
    48 51   
    49 52   
    skipped 21 lines
Please wait...
Page is in error, reload to recover