Skip to content

Commit

Permalink
Removed excess descriptions from template, changed export behavior to…
Browse files Browse the repository at this point in the history
… only create requested file
  • Loading branch information
tleef42 committed Jun 5, 2023
1 parent 4e6b757 commit 43dc34f
Show file tree
Hide file tree
Showing 11 changed files with 42 additions and 64 deletions.
77 changes: 33 additions & 44 deletions src/cti_publishing_tool/cti_publishing_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import json
from pathlib import Path
import base64
import tempfile

from liquid import Template
from htmldocx import HtmlToDocx
Expand Down Expand Up @@ -529,13 +530,15 @@ def _data_input_path():


def process_template(data_input_filepath, report_type, exclude_sections=None):
"""Load the `report_type` template from memory while excluding sections from `exclude_sections`"""
"""Load the `report_type` template from memory while excluding sections from `exclude_sections`.
Returns a tuple of the template as a string and the filename.
"""

def _load_data(data_input_filepath):
"""Expects a str of the JSON to convert. Simply loads it into Python and returns it"""
with open(data_input_filepath, 'r') as _file_obj:
data_json = json.load(_file_obj)
return data_json
return data_json

def _modular_template(exclude_sections, report_type, data):
"""Create a template dynamically by adding sections as needed, without the criteria from `exclude_sections`."""
Expand Down Expand Up @@ -578,7 +581,6 @@ def _embed_file(data):
with open("./output/" + filename + ".json", "w") as file:
json.dump(json.loads(bytes), file, indent=4)


_report_map = {
1: 'campaign',
2: 'executive',
Expand All @@ -589,37 +591,36 @@ def _embed_file(data):
report_type = _report_map[int(report_type)]

rendered_template = _modular_template(exclude_sections, report_type, data)
filename = os.path.splitext(os.path.split(data_input_filepath)[-1])[0] + '.html'

# Save rendered template as an HTML file
# Rendered HTML can be converted to DOCX or PDF files or converted by the user.
filename = os.path.splitext(os.path.split(data_input_filepath)[-1])[0]
return (rendered_template, filename)


def export_report(rendered_template, filename, doc_type='docx'):
try:
os.mkdir("./output/")
except FileExistsError:
pass

with open("./output/" + filename, 'w') as file:
file.write(rendered_template)


def export_report(filepath_to_html, doc_type='docx'):
filename = os.path.splitext(filepath_to_html)[0]
if doc_type == 'docx':
new_parser = HtmlToDocx()
new_parser.table_style = 'Light List Accent 1'
new_parser.parse_html_file(filepath_to_html, filename)
elif doc_type == 'pdf':
# Temporary workaround - with out current PDF creation, we require a DOCX.
new_parser = HtmlToDocx()
new_parser.table_style = 'Light List Accent 1'
new_parser.parse_html_file(filepath_to_html, filename)
# Remove all the above when we find a better transformer

input_f = Path(filename + '.docx')
output_f = Path(filename + '.pdf')
convert(input_f, output_f)

with tempfile.TemporaryDirectory() as temporary_files:
if doc_type == 'docx':
new_parser = HtmlToDocx()
new_parser.table_style = 'Light List Accent 1'
docx = new_parser.parse_html_string(rendered_template)
temp_path = os.path.join("./output/", (filename + '.docx'))
docx.save(temp_path)
elif doc_type == 'pdf':
temp_path = os.path.join(temporary_files, (filename + '.docx'))
# Temporary workaround - with our current PDF conversion library, we require a DOCX.
new_parser = HtmlToDocx()
new_parser.table_style = 'Light List Accent 1'
docx = new_parser.parse_html_string(rendered_template)
docx.save(temp_path)
# Remove lines between comments when using a different transformer
input_f = temp_path
output_f = os.path.join("./output/", (filename + '.pdf'))
convert(input_f, output_f)
print("Document created")


if __name__ == "__main__":
parser = argparse.ArgumentParser()
Expand All @@ -640,7 +641,7 @@ def export_report(filepath_to_html, doc_type='docx'):
args.report_type, args.document_type, args.exclude_section, args.data_input_filepath = cli()
args.data_input_filepath = Path(args.data_input_filepath)

if not args.exclude_section:
if args.only_section:
# only_section was inputted
if args.report_type == '1':
campaign = {"executive_summary", "key_points", "assessment", "intelligence_gaps", "mitre_attack_table", "timeline", "iocs", "signatures", "intelligence_requirements", "data_sources", "metadata"}
Expand All @@ -655,17 +656,5 @@ def export_report(filepath_to_html, doc_type='docx'):
ta = {"executive_summary", "key_points", "assessment", "threat_actor", "timeline", "intelligence_gaps", "mitre_attack_table", "victims", "iocs", "signatures", "intelligence_requirements", "data_sources", "metadata"}
args.exclude_section = list(ta-set(args.only_section))

process_template(args.data_input_filepath, args.report_type, args.exclude_section)
filename = os.path.splitext(os.path.split(args.data_input_filepath)[-1])[0] + '.html'
export_report("./output/" + filename, args.document_type)


def todo():
"""A running list of remaining TODO's
# TODO: Go back and modify `TORENAMELATER.html` to be operational. The file contains feedback and is meant for attaching Attack Flow & heatmap files
* Ending tasks:
-. Clean up comments
-. Write docstrings
NOTE: Using a set in CLI_exclude will print elements in different orders.
"""
template = process_template(args.data_input_filepath, args.report_type, args.exclude_section)
export_report(template[0], template[1], args.document_type)
Binary file modified src/cti_publishing_tool/requirements.txt
Binary file not shown.
1 change: 0 additions & 1 deletion src/cti_publishing_tool/templates/sections/TORENAME.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<h2>Attached Attack Flow and/or Navigator Heat Maps, if applicable</h2>
<h2>Probability Matrix</h2>
<p>We recommend that analysts properly express and explain uncertainties associated with major analytic judgments.</p>
<table>
<thead>
<tr>
Expand Down
2 changes: 1 addition & 1 deletion src/cti_publishing_tool/templates/sections/feedback.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<h2>Feedback</h2>
<p>Provide a point of contact (e.g., an email address) for customer feedback on the published CTI report, such as whether the report addressed the customers&quot; Intelligence Requirements, how the report could be more actionable, additional Intelligence Requirement questions to answer, etc. </p>
<p>{{ feedback }}</p>
<hr>
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<h2>Intelligence Requirements</h2>
<p>Brief citation of CTI requirements(s) addressed by this report.</p>
<ul>
{%- for requirement in intelligence_requirements -%}
<li>{{ requirement.intelligence_requirement }}</li>
Expand Down
4 changes: 0 additions & 4 deletions src/cti_publishing_tool/templates/sections/iocs.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<p class="page-break"></p>
<h2>Indicators of Compromise (IOC)</h2>
<p>This section consists of three IOC tables [Malware, Network, and System Artifacts] associated with the Campaign.</p>
<h2>Malware</h2>
<table>
<thead>
Expand Down Expand Up @@ -33,7 +32,6 @@ <h2>Malware</h2>
</tbody>
</table>
<h2>Network</h2>
<p>This table should detail the network indicators associated with the campaign, e.g., domains and IP addresses. The &OpenCurlyDoubleQuote;Intrusion Phase&CloseCurlyDoubleQuote; column includes Initial Access, Command and Control, and Exfiltration. The first and last reported fields are intended to memorialize the longevity of a particular network artifact, providing additional insight into trends in malicious behavior.</p>
<table>
<thead>
<tr>
Expand All @@ -59,7 +57,6 @@ <h2>Network</h2>
</tbody>
</table>
<h2>System Artifacts</h2>
<p>This table should detail any unique artifacts associated with the campaign that could be observed on a host, e.g., processes, DLLs, registry keys. The first and last reported fields are intended to memorialize the longevity of a particular system artifact, providing additional insight into trends in malicious behavior.</p>
<table>
<thead>
<tr>
Expand Down Expand Up @@ -87,7 +84,6 @@ <h2>System Artifacts</h2>
</tbody>
</table>
<h2>Common Vulnerabilities and Exposures (CVEs)</h2>
<p>CVEs associated with the campaign. The date reported field is designed to capture the date when the CVE became public knowledge. To adequately fill out this table, it may require information from other internal teams.</p>
<table>
<thead>
<tr>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<h2>Metadata</h2>
<p>The metadata info below is for automation purposes and provides discrete fields for tool extraction. If you are not using the tool, we recommend removing the info.</p>
<h3>Threat Actor:</h3>
<ul>
{%- for threat_actor in metadata.threat_actors -%}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<h2>Metadata</h2>
<p>The metadata info below is for automation purposes and provides discrete fields for tool extraction. If you are not using the tool, we recommend removing the info.</p>
<h3>Threat Actor:</h3>
<ul>
{%- for threat_actor in metadata.threat_actors -%}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<h2>MITRE ATT&amp;CK Table (based on v12)</h2>
<p>Table of the MITRE ATT&amp;CK tactics and techniques/sub-techniques from the campaign. The procedure column details a particular instance of how a technique/sub-technique has been used. The D3FEND column includes the corresponding MITRE D3FEND countermeasure technique, if available. If using the tool, the Tactics and Techniques can be automatically generated from an Attack Flow document using the plug-in.</p>
<table>
<h2>MITRE ATT&amp;CK Table (based on v12)</h2><table>
<thead>
<tr>
<th>Attribution</th>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<h2>MITRE ATT&amp;CK Table (based on v12): TTPs Likely to Be in the Network</h2>
<p>This table should show the MITRE tactics and techniques/Sub-techniques not yet observed but likely to be in the network. The procedure column details a particular instance of how a technique/sub-technique has been used. The D3FEND column includes the corresponding MITRE D3FEND countermeasure technique, if available. If using the tool, the tactics and techniques can be automatically generated from an Attack Flow document using the plug-in.</p>
<table>
<thead>
<tr>
Expand Down Expand Up @@ -27,7 +26,6 @@ <h2>MITRE ATT&amp;CK Table (based on v12): TTPs Likely to Be in the Network</h2>
</tbody>
</table>
<h2>MITRE ATT&amp;CK Table (based on v12): TTPs Observed in the Intrusion</h2>
<p>This table should show the MITRE tactics, techniques/sub-techniques, and procedures observed during the intrusion based on data provided by the SOC or IR team. Analysts can include the corresponding MITRE DEFEND countermeasure technique, if available. If using the tool, the tactics and techniques can be automatically generated from an Attack Flow document using the plug-in.</p>
<table>
<thead>
<tr>
Expand Down
13 changes: 7 additions & 6 deletions src/cti_publishing_tool/templates/sections/signatures.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<h2>Signatures</h2>
<p>This section should include detections (e.g., Yara signature) that correspond to the malware or malicious activity associated with the campaign.</p>
<ol>
{%- for sig in iocs.signatures -%}
<ul>
{%- for sig in signatures -%}
<li>{{ sig.attribution }}</li>
<li>{{ sig.ioc_malware_name }}</li>
<li>{{ sig.signature_description }}</li>
<ul>
<li>{{ sig.ioc_malware_name }}</li>
<li>{{ sig.signature_description }}</li>
</ul>
{%- endfor -%}
</ol>
</ul>

0 comments on commit 43dc34f

Please sign in to comment.