Skip to content

Commit

Permalink
Extract more useful info from tags instead of description
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGroundZero committed Sep 20, 2018
1 parent 129e3e1 commit c81a02e
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 41 deletions.
Binary file added dist/OpenVAS Reporting-1.3.0.tar.gz
Binary file not shown.
Binary file added dist/OpenVAS_Reporting-1.3.0-py3-none-any.whl
Binary file not shown.
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Changelog
=========

1.3.0 - Fix retrieval of description and other useful info by parsing <tags> instead of <description>

1.2.3 - Implement https://github.com/cr0hn/openvas_to_report/pull/12

1.2.2 - Fix bug where port info was not correctly extracted.
Expand Down
60 changes: 38 additions & 22 deletions openvasreporting/libs/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def exporters():
'docx': export_to_word
}


def export_to_excel(vuln_info, output_file="openvas_report"):
"""
Export vulnerabilities info in an Excel file.
Expand Down Expand Up @@ -220,47 +221,58 @@ def export_to_excel(vuln_info, output_file="openvas_report"):
string="<< TOC")
# / Add to Table of Contents

ws_vuln.set_column("B:B", 14, format_align_center)
ws_vuln.set_column("A:A", 7, format_align_center)
ws_vuln.set_column("B:B", 20, format_align_center)
ws_vuln.set_column("C:C", 14, format_align_center)
ws_vuln.set_column("D:D", 30, format_align_center)
ws_vuln.set_column("E:E", 12, format_align_center)
ws_vuln.set_column("F:F", 13, format_align_center)
ws_vuln.set_column("G:G", 20, format_align_center)
ws_vuln.set_column("H:H", 7, format_align_center)

ws_vuln.write('B2', "Title", format_table_titles)
ws_vuln.merge_range("C2:G2", vuln.name, format_sheet_title_content)

ws_vuln.write('B3', "Description", format_table_titles)
ws_vuln.merge_range("C3:G3", vuln.description, format_description)

ws_vuln.write('B4', "CVEs", format_table_titles)
ws_vuln.write('B4', "Impact", format_table_titles)
ws_vuln.merge_range("C4:G4", vuln.impact, format_description)

ws_vuln.write('B5', "Recommendation", format_table_titles)
ws_vuln.merge_range("C5:G5", vuln.solution, format_description)

ws_vuln.write('B6', "Details", format_table_titles)
ws_vuln.merge_range("C6:G6", vuln.insight, format_description)

ws_vuln.write('B7', "CVEs", format_table_titles)
cves = ", ".join(vuln.cves)
cves = cves.upper() if cves != "" else "No CVE"
ws_vuln.merge_range("C4:G4", cves, format_table_cells)
ws_vuln.merge_range("C7:G7", cves, format_table_cells)

ws_vuln.write('B5', "CVSS", format_table_titles)
ws_vuln.write('B8', "CVSS", format_table_titles)
cvss = vuln.cvss if vuln.cvss != -1.0 else "No CVSS"
ws_vuln.merge_range("C5:G5", cvss, format_table_cells)
ws_vuln.merge_range("C8:G8", cvss, format_table_cells)

ws_vuln.write('B6', "Level", format_table_titles)
ws_vuln.merge_range("C6:G6", vuln.level.capitalize(), format_table_cells)
ws_vuln.write('B9', "Level", format_table_titles)
ws_vuln.merge_range("C9:G9", vuln.level.capitalize(), format_table_cells)

ws_vuln.write('B7', "Family", format_table_titles)
ws_vuln.merge_range("C7:G7", vuln.family, format_table_cells)
ws_vuln.write('B10', "Family", format_table_titles)
ws_vuln.merge_range("C10:G10", vuln.family, format_table_cells)

if len(vuln.description) < 200:
description_height = 20
else:
description_height = 80
ws_vuln.set_row(2, description_height, None)

ws_vuln.write('C9', "IP", format_table_titles)
ws_vuln.write('D9', "Host name", format_table_titles)
ws_vuln.write('E9', "Port number", format_table_titles)
ws_vuln.write('F9', "Port protocol", format_table_titles)
ws_vuln.write('C12', "IP", format_table_titles)
ws_vuln.write('D12', "Host name", format_table_titles)
ws_vuln.write('E12', "Port number", format_table_titles)
ws_vuln.write('F12', "Port protocol", format_table_titles)

# Affected hosts
for j, (host, port) in enumerate(vuln.hosts, 10):
for j, (host, port) in enumerate(vuln.hosts, 13):

ws_vuln.write("C{}".format(j), host.ip)
ws_vuln.write("D{}".format(j), host.host_name if host.host_name else "-")
Expand Down Expand Up @@ -444,12 +456,12 @@ def add_style(new_style_name, base_style_name, font_size, font_color, font_bold,
title = "[{}] {}".format(level.upper(), vuln.name)
document.add_paragraph(title, style='Report Heading 2')

table_vuln = document.add_table(rows=4, cols=3)
table_vuln = document.add_table(rows=6, cols=3)
table_vuln.autofit = False

# Color
col_cells = table_vuln.columns[0].cells
col_cells[0].merge(col_cells[3])
col_cells[0].merge(col_cells[5])
color_fill = parse_xml(r'<w:shd {} w:fill="{}"/>'.format(nsdecls('w'), Config.colors()[vuln.level][1:]))
col_cells[0]._tc.get_or_add_tcPr().append(color_fill)

Expand All @@ -459,9 +471,11 @@ def add_style(new_style_name, base_style_name, font_size, font_color, font_bold,
# Headers
hdr_cells = table_vuln.columns[1].cells
hdr_cells[0].paragraphs[0].add_run('Description').bold = True
hdr_cells[1].paragraphs[0].add_run('CVEs').bold = True
hdr_cells[2].paragraphs[0].add_run('CVSS').bold = True
hdr_cells[3].paragraphs[0].add_run('Family').bold = True
hdr_cells[1].paragraphs[0].add_run('Impact').bold = True
hdr_cells[2].paragraphs[0].add_run('Recommendation').bold = True
hdr_cells[3].paragraphs[0].add_run('Details').bold = True
hdr_cells[4].paragraphs[0].add_run('CVSS').bold = True
hdr_cells[5].paragraphs[0].add_run('CVEs').bold = True

for hdr_cell in hdr_cells:
hdr_cell.width = Cm(3.58)
Expand All @@ -474,9 +488,11 @@ def add_style(new_style_name, base_style_name, font_size, font_color, font_bold,

txt_cells = table_vuln.columns[2].cells
txt_cells[0].text = vuln.description
txt_cells[1].text = cves
txt_cells[2].text = cvss
txt_cells[3].text = vuln.family
txt_cells[1].text = vuln.impact
txt_cells[2].text = vuln.solution
txt_cells[3].text = vuln.insight
txt_cells[4].text = cvss
txt_cells[5].text = cves

for txt_cell in txt_cells:
txt_cell.width = Cm(12.51)
Expand Down
25 changes: 12 additions & 13 deletions openvasreporting/libs/parsed_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ def __init__(self, vuln_id, name, threat, **kwargs):
:param level: Threat level according to CVSS: None, Low, Medium, High, Critical
:type level: str
:param description: vulnerability description
:type description: basestring
:param tags: vulnerability tags
:type tags: dict
:param references: list of references
:type references: list(str)
Expand All @@ -162,7 +162,7 @@ def __init__(self, vuln_id, name, threat, **kwargs):
cves = kwargs.get("cves", list()) or list()
cvss = kwargs.get("cvss", -1.0) or -1.0
level = kwargs.get("level", "None") or "None"
description = kwargs.get("description", "") or ""
tags = kwargs.get("tags", dict()) or dict()
references = kwargs.get("references", list()) or list()
family = kwargs.get("family", "Unknown") or "Unknown"

Expand All @@ -185,28 +185,27 @@ def __init__(self, vuln_id, name, threat, **kwargs):
raise TypeError("Expected float, got '{}' instead".format(type(cvss)))
if not isinstance(level, str):
raise TypeError("Expected basestring, got '{}' instead".format(type(level)))
if description is not None:
if not isinstance(description, str):
raise TypeError("Expected basestring, got '{}' instead".format(type(description)))
else:
description = name

if not isinstance(tags, dict):
raise TypeError("Expected dict, got '{}' instead".format(type(tags)))
if not isinstance(references, list):
raise TypeError("Expected list, got '{}' instead".format(type(references)))
else:
for x in references:
if not isinstance(x, str):
raise TypeError("Expected basestring, got '{}' instead".format(type(x)))

description = re.sub("([\n\r]*[\s]*[Ss]ummary[:]*[\n\r\s]*)", "", description)
description = re.sub("[\w][\r\n][\w]", "", description)

self.vuln_id = vuln_id
self.name = name
self.cves = cves
self.cvss = float(cvss)
self.level = level
self.description = description
self.description = tags.get('summary', '')
self.detect = tags.get('vuldetect', '')
self.insight = tags.get('insight', '')
self.impact = tags.get('impact', '')
self.affected = tags.get('affected', '')
self.solution = tags.get('solution', '')
self.solution_type = tags.get('solution_type', '')
self.references = references
self.threat = threat
self.family = family
Expand Down
18 changes: 13 additions & 5 deletions openvasreporting/libs/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# Project name: OpenVAS Reporting: A tool to convert OpenVAS XML reports into Excel files.
# Project URL: https://github.com/TheGroundZero/openvas_to_report

import re
import sys
import logging

Expand Down Expand Up @@ -65,6 +65,8 @@ def openvas_parser(input_files, min_level=Config.levels()["n"]):

nvt_tmp = vuln.find("./nvt")

# --------------------
#
# VULN_NAME
vuln_name = nvt_tmp.find("./name").text

Expand Down Expand Up @@ -114,9 +116,15 @@ def openvas_parser(input_files, min_level=Config.levels()["n"]):

# --------------------
#
# VULN_DESCRIPTION
vuln_description = vuln.find("./description").text
logging.debug("* vuln_desc:\t{}".format(vuln_description)) # DEBUG
# VULN_TAGS
# Replace double newlines by a single newline
vuln_tags_text = re.sub(r"(\r\n)+", "\r\n", nvt_tmp.find("./tags").text)
vuln_tags_text = re.sub(r"\n+", "\n", vuln_tags_text)
# Remove useless whitespace but not newlines
vuln_tags_text = re.sub(r"[^\S\r\n]+", " ", vuln_tags_text)
vuln_tags_temp = vuln_tags_text.split('|')
vuln_tags = dict(tag.split('=', 1) for tag in vuln_tags_temp)
logging.debug("* vuln_tags:\t{}".format(vuln_tags)) # DEBUG

# --------------------
#
Expand Down Expand Up @@ -178,7 +186,7 @@ def openvas_parser(input_files, min_level=Config.levels()["n"]):
vuln_store = Vulnerability(vuln_id,
name=vuln_name,
threat=vuln_threat,
description=vuln_description,
tags=vuln_tags,
cvss=vuln_cvss,
cves=vuln_cves,
references=vuln_references,
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
setup(
name='OpenVAS Reporting',
description='A tool to convert OpenVAS XML into reports.',
version='1.2.3',
version='1.3.0',
long_description=long_description,
long_description_content_type='text/markdown',
author='TheGroundZero (@DezeStijn)',
Expand Down

0 comments on commit c81a02e

Please sign in to comment.