Skip to content

Commit

Permalink
Update report logic and add images
Browse files Browse the repository at this point in the history
  • Loading branch information
nickviola committed Jul 7, 2023
1 parent 15de0a0 commit 154f948
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 45 deletions.
Binary file added src/assets/Picture1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/Picture2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/TitlePage.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
265 changes: 220 additions & 45 deletions src/reportlab_generator.py
@@ -1,11 +1,12 @@
"""Generate a TPT report using a passed data dictionary."""

# Standard Python Libraries
from hashlib import sha256
import os
import pandas as pd

# Third-Party Libraries
# import numpy as np
import numpy as np
from reportlab.lib import utils
from reportlab.lib.colors import HexColor
from reportlab.lib.pagesizes import letter
Expand Down Expand Up @@ -34,6 +35,14 @@

BASE_DIR = os.path.abspath(os.path.dirname(__file__))

EXAMPLE_TABLE1 = {
"id": [12],
"Finding": ["Spear Phishing Weakness"],
"Severity": ["High"],
"Service": ["Phishing Assessment (Infrastructure Only)"],
"Location": ["Phishing"]
}

# Set fonts that you will use in the pdf.
pdfmetrics.registerFont(
TTFont("Franklin_Gothic_Book", BASE_DIR + "/fonts/FranklinGothicBook.ttf")
Expand Down Expand Up @@ -156,52 +165,65 @@ def format_table(
def report_gen(data_dict):
"""Generate a TPT report with data passed in the data dictionry."""
"""Build the 'templates' for the static pages."""
def doHeading(text, sty):
"""Add a bookmark to heading element to allow linking from the table of contents."""
# this will add a bookmark to a header allowing it to be linked from the table of contents
# create bookmarkname
bn = sha256((text + sty.name).encode("utf8")).hexdigest()
# modify paragraph text to include an anchor point with name bn
h = Paragraph(text + '<a name="%s"/>' % bn, sty)
# store the bookmark name on the flowable so afterFlowable can see this
h._bookmarkName = bn
return h

def titlePage(canvas, doc):
"""Build static elements of the cover page."""
canvas.saveState()
# Add the background image to the top
# canvas.drawImage(BASE_DIR + "/assets/Cover.png", 0, 0, width=None, h eight=None)
canvas.drawInlineImage(
BASE_DIR + "/assets/cisa.png", 45, 705, width=65, height=65
)
# set the font
# canvas.drawImage(BASE_DIR + "/assets/TitlePage.png", 0, 0, width=None, height=None)
# canvas.drawInlineImage(
# BASE_DIR + "/assets/cisa.png", 45, 705, width=65, height=65
# )

# Story.append(get_image(BASE_DIR + "/assets/TitlePage.png", width=6 * inch))
# # set the font
canvas.setFont("Franklin_Gothic_Medium_Regular", 32)
# Write the title to page and add some dynamic content to complete the tile page later
canvas.drawString(50, 660, "TPT Report")
canvas.restoreState()
# # Write the title to page and add some dynamic content to complete the tile page later
# canvas.drawString(50, 660, "TPT Report")
# canvas.restoreState()

def summaryPage(canvas, doc):
"""Build static elements of the summary page."""
canvas.saveState()
# Set the font
canvas.setFont("Franklin_Gothic_Book", 13)
# add a background image
# canvas.drawImage(
# BASE_DIR + "/assets/summary-background.png",
# 0,
# 0,
# width=PAGE_WIDTH,
# height=PAGE_HEIGHT,
# canvas.saveState()
# # Set the font
# canvas.setFont("Franklin_Gothic_Book", 13)
# # add a background image
# # canvas.drawImage(
# # BASE_DIR + "/assets/summary-background.png",
# # 0,
# # 0,
# # width=PAGE_WIDTH,
# # height=PAGE_HEIGHT,
# # )
# # Change the color that will be used in the rectangle we add
# canvas.setFillColor(HexColor("#1d5288"))
# canvas.setStrokeColor("#1d5288")
# canvas.rect(inch, 210, 3.5 * inch, 5.7 * inch, fill=1)
# canvas.restoreState()
# # Add header/footer
# canvas.setStrokeColor("#a7a7a6")
# canvas.setFillColor("#a7a7a6")
# canvas.drawInlineImage(
# BASE_DIR + "/assets/cisa.png", 45, 705, width=65, height=65
# )
# Change the color that will be used in the rectangle we add
canvas.setFillColor(HexColor("#1d5288"))
canvas.setStrokeColor("#1d5288")
canvas.rect(inch, 210, 3.5 * inch, 5.7 * inch, fill=1)
canvas.restoreState()
# Add header/footer
canvas.setStrokeColor("#a7a7a6")
canvas.setFillColor("#a7a7a6")
canvas.drawInlineImage(
BASE_DIR + "/assets/cisa.png", 45, 705, width=65, height=65
)
canvas.drawString(130, 745, "TPT Report")
canvas.drawString(130, 725, "Reporting Period: " + data_dict["dateRange"])
canvas.line(130, 710, PAGE_WIDTH - inch, 710)
canvas.drawRightString(
PAGE_WIDTH - inch, 0.75 * inch, "P&E Report | Page %d" % (doc.page)
)
canvas.drawString(inch, 0.75 * inch, data_dict["endDate"])
canvas.setFont("Franklin_Gothic_Medium_Regular", 12)
# canvas.drawString(130, 745, "TPT Report")
# canvas.drawString(130, 725, "Reporting Period: " + data_dict["dateRange"])
# canvas.line(130, 710, PAGE_WIDTH - inch, 710)
# canvas.drawRightString(
# PAGE_WIDTH - inch, 0.75 * inch, "P&E Report | Page %d" % (doc.page)
# )
# canvas.drawString(inch, 0.75 * inch, data_dict["endDate"])
# canvas.setFont("Franklin_Gothic_Medium_Regular", 12)

# ***Document Structures***#
"""Build frames for different page structures."""
Expand Down Expand Up @@ -329,7 +351,14 @@ def summaryPage(canvas, doc):
#The default template will be the first in the list we create above i.e. TitlePage
#These will start at the beginning of the frame we added to that template page
# Story.append(point12_spacer)
Story.append(Spacer(1, 55))

# Story.append(point12_spacer)
Story.append(get_image(BASE_DIR + "/assets/TitlePage.png", width=7.3 * inch))
Story.append(point12_spacer)
Story.append(point12_spacer)
Story.append(doHeading("TPT Report", h1))
Story.append(PageBreak())
# Story.append(Spacer(1, 55))
Story.append(
format_table(
data_dict["intro_table"],
Expand All @@ -347,18 +376,115 @@ def summaryPage(canvas, doc):
[body, None],
)
)
Story.append(Spacer(1, 40))
Story.append(Paragraph("Phishing Results", h1))
Story.append(Spacer(1, 10))
# Story.append(Spacer(1, 40))
# Story.append(Paragraph("Phishing Results", h1))
# Story.append(Spacer(1, 10))
# Story.append(
# Paragraph("""The phishing test evaluated the performance of security controls at the border and host. During a phishing attack (Figure 5), an attacker sends an email that must successfully pass through any protections presented by both the network border and the host system that receives the email.""", body)
# )
Story.append(PageBreak())

Story.append(horizontal_line)
Story.append(point12_spacer)
Story.append(doHeading("Phishing Results", h2))
Story.append(
Paragraph(
"""The phishing test evaluated the performance of security controls
at the border and host. During a phishing attack (Figure 5), an
attacker sends an email that must successfully pass through any
protections presented by both the network border and the host system
that receives the email.""",
body,
)
)
Story.append(point12_spacer)
Story.append(get_image(BASE_DIR + "/assets/Picture1.png", width=4 * inch))
Story.append(point12_spacer)
Story.append(get_image(BASE_DIR + "/assets/Picture2.png", width=4 * inch))
Story.append(point12_spacer)
Story.append(
Paragraph(
"""A simulated phishing attack scenario was performed with the Example Organization (EXPL) complicit user, Alisia Romo, during which, the CISA team attempted to execute a variety of simulated malicious payloads on the POC’s workstation. This simulated attack scenario was meant to test EXPL’s security controls in their ability to identify, alert, and prevent such attack vectors. """,
body,
)
)
Story.append(point12_spacer)
Story.append(
Paragraph("""The phishing test evaluated the performance of security controls at the border and host. During a phishing attack (Figure 5), an attacker sends an email that must successfully pass through any protections presented by both the network border and the host system that receives the email.""", body)
Paragraph(
"""The initial email containing a link to the malicious payloads was able to circumvent border protections and reach the complicit user’s inbox (in spam). Of the twenty-five (25) different payloads tested, zero (0) payloads successfully executed and connected to the CISA team’s command-and-control (C2) server. From the attached payload test, one (1) of the eight (8) emails containing malicious attachments was able to circumvent through border protections and reach the POC’s inbox. This payload was unable to successfully execute.""",
body,
)
)
# Story.append(point12_spacer)
# Story.append(point12_spacer)

Story.append(PageBreak())

doc.multiBuild(Story)
# Preloaded templates to use on the next page
Story.append(horizontal_line)
Story.append(point12_spacer)
Story.append(doHeading("Noted System Strengths", h2))

Story.append(
Paragraph(
"""The internal and email infrastructure incorporated several security features that reduced the effectiveness of phishing payloads. The environment’s firewall (Fortinet) prohibited users from accessing the testing team’s malicious web during the phishing assessment. This reduces the likelihood of users obtaining malicious software from known malicious sites and domains. The environment utilized an effective antivirus solution (Trend Micro), which prevented the execution of most malicious payloads during the phishing assessment.""",
body,
)
)
Story.append(point12_spacer)
Story.append(
Paragraph(
"""The environment utilized Albert real-time monitoring, which alerted security staff upon the detection of malicious code within the environment. The alert notifications were received within minutes of initiating the phishing assessment.""",
body,
)
)

Story.append(point12_spacer)
Story.append(
format_table(
pd.DataFrame.from_dict(EXAMPLE_TABLE1),
table_header,
[.5 * inch, 1.5 * inch, inch, 2.5 * inch, inch],
[None, body, None, body, None],
)
)

Story.append(point12_spacer)
Story.append(point12_spacer)
Story.append(doHeading("Affected Systems", h2))

Story.append(
Paragraph(
"""@example.org workstations""",
body,
)
)

Story.append(point12_spacer)
Story.append(point12_spacer)
Story.append(doHeading("Description", h2))

Story.append(
Paragraph(
"""Successful spear phishing requires an attacker’s email to pass through the network border and execute on the local host with the aid of a user performing some action. Most common phishing attacks can be rebuffed by good border and host-level automated protections. Inadequate protections allow the execution of malicious payloads. """,
body,
)
)

Story.append(point12_spacer)
Story.append(point12_spacer)
Story.append(doHeading("Recommended Mitigation", h2))

Story.append(
Paragraph(
"""Regularly analyze border and host-level protections, including spam-filtering capabilities, to ensure their continued effectiveness in blocking the delivery and execution of malware. """,
body,
)
)

Story.append(PageBreak())
Story.append(horizontal_line)
Story.append(point12_spacer)
Story.append(doHeading("Payload Testing Results", h2))
Story.append(
Paragraph(
"""
Expand All @@ -377,8 +503,57 @@ def summaryPage(canvas, doc):
)
)
Story.append(point12_spacer)

Story.append(PageBreak())

Story.append(horizontal_line)
Story.append(point12_spacer)
Story.append(doHeading("Payload Testing Results", h2))

Story.append(
Paragraph(
"""The initial email containing a link to the malicious payloads was able to circumvent border protections and reach the complicit user’s inbox (in spam). Of the twenty-five (25) different payloads tested, no payloads successfully executed and connected to the CISA team’s C2 server. From the attached payload test, one (1) of the eight (8) emails containing malicious attachments were able to circumvent through border protections and reach the POC’s inbox. This payload was unable to successfully execute. """,
body,
)
)

Story.append(point12_spacer)
Story.append(point12_spacer)
Story.append(doHeading("Conclusions/Recommendations", h2))

Story.append(
Paragraph(
"""Regularly analyze border and host-level protections, including spam-filtering capabilities, to ensure their continued effectiveness in blocking the delivery and execution of malware. """,
body,
)
)


# Story.append(horizontal_line)
# Story.append(point12_spacer)
# Preloaded templates to use on the next page
# Story.append(point12_spacer)
# Story.append(point12_spacer)
# Story.append(
# Paragraph(
# """
# Payload Testing Results
# """,
# table,
# )
# )
# # Generate a table using ad atabframe passed to my format_table function
# Story.append(
# format_table(
# data_dict["breach_table"],
# table_header,
# [2.5 * inch, inch, inch, inch, inch],
# [body, None, None, None, None],
# )
# )
# Story.append(point12_spacer)
# Story.append(PageBreak())

doc.multiBuild(Story)
return 1

Expand Down

0 comments on commit 154f948

Please sign in to comment.