Skip to content

Commit

Permalink
Added support for trustwave pentest results
Browse files Browse the repository at this point in the history
  • Loading branch information
kuffers committed Feb 24, 2021
1 parent b4ea8f6 commit f9a9f81
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 0 deletions.
9 changes: 9 additions & 0 deletions trustwave/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Script to pull the vulnerability report from a Trustwave automated pentest output, convert to Nucleus CSV, then post to Nucleus
*** Populate the following variables in the script prior to using ***
NUCLEUS_ROOT_URL
NUCLEUS_API_KEY

Required command line arguments:
-i for input file path
-o for output file in Nucleus format
-# for project id
2 changes: 2 additions & 0 deletions trustwave/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
requests
xmltodict
208 changes: 208 additions & 0 deletions trustwave/trustwave_pentest_xml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#!/usr/bin/python3.7
__author__ = "Nucleus Security"
__license__ = "MIT License"
__version__ = "0.1"

#Used for writing to csv
import csv
# Used for arguments
import argparse
# Used to post the file to Nucleus
import requests
import xmltodict
import json


# Enter in the root URL of your Nucleus instance.
# Example https://example.nucleussec.com
NUCLEUS_ROOT_URL = "{Enter root URL of your Nucleus Instance here}"

# Generate an API key through the Nucleus UI
API_KEY = "{Enter your API key from Nucleus here}"


def convert_to_json(inputPath):

with open (inputPath) as xml_file:

data_dict = xmltodict.parse(xml_file.read())

xml_file.close()

json_data = json.dumps(data_dict)

#print(json_data)

return json_data



def customParser(json_data, outputPath):

# Create the csv file for writing
with open(outputPath, 'w', newline='') as csvfile:

csvwriter = csv.writer(csvfile, delimiter=',')

csvwriter.writerow(['nucleus_import_version', 'host_name', 'ip_address', 'scan_type', 'scan_tool', 'finding_type', 'finding_cve', 'finding_number', 'finding_name', 'finding_severity', 'finding_description', 'finding_recommendation', 'finding_output', 'finding_result', 'finding_references'])

# Try to parse the data.
try:

json_data = json.loads(json_data)

#print(json_data)

export = json_data['export']

findings = export['finding']

#print(findings)

for finding in findings:

csv_line = []

severity = finding['severity']

finding_name = finding['title']

asset_name = finding['assetName']

asset_ip = finding['ip']

finding_number = finding['title']

description = finding['description']

scan_date = finding['createdOn']

# Loop and fix references
references = finding['references']

# Skipping references for now for speed
#TODO: Parse the references into Nucleus format
'''
try:
#reference_info = references.replace(",", ";")
reference_info = references.replace(":", "-")
reference_info = reference_info.replace(" ", "_")
#Replace https://
reference_info = reference_info.replace("ps-", "ps:")
except:
pass
#print(reference_info)
'''


solution = finding['remediation']

# Loop and fix finding output
finding_output = finding['evidences']['evidence']

#print(finding_output)

finding_output_data = ''

try:

for output in finding_output:

title = output['title']
value = output['value']
output_type = output['type']

finding_output_data = output_type + ': ' + title + ' - ' + value

#print(finding_output_data)

except Exception as e:

pass

csv_line.extend(['1', asset_name, asset_ip, 'Host', 'Trustwave Pentest', 'Vuln', '', finding_number, finding_name, severity, description, solution, finding_output_data, 'Failed'])

#print(csv_line)

csvwriter.writerow(csv_line)



except Exception as e:

print("Error:", e)


def get_args():
parser = argparse.ArgumentParser(description="For parsing whitesource files to be uploaded into Nucleus. If project ID is specified, will post the Nucleus supported file to Nucleus project.")

# List arguments. Should only include input file and output file
parser.add_argument('-i', '--inputfile', dest='inputFile', help="Path to trustwave xml file", required=True)
parser.add_argument('-o', '--outputfile', dest='outputFile', help="Path to csv file output", required=True)
parser.add_argument('-#', '--project_id', dest="project_id", help="This is the project ID of the Nucleus project to which you want to post. If not specified, this script will only parse the whitesource file for manual upload.")

# Define the arguments globally for ease of use
global args

args = parser.parse_args()

return args

# Send the file to Nucleus
def post_to_nucleus(outputfile):

# Enter the ID of the project which you wish to post to here
PROJECT_ID = args.project_id

# open the file to send
with open(outputfile.name, 'rb') as f:

# Get the final Nucleus URL to post to
nucleus_url = str(NUCLEUS_ROOT_URL+'/nucleus/api/projects/'+PROJECT_ID+'/scans')

print("Posted to URL:", nucleus_url)

# Send file with proper header. Keep note of the project ID you need to send
file_upload = requests.post(nucleus_url, files={outputfile.name: f}, headers={'x-apikey': API_KEY})

# Print the response from the server
print(file_upload.content)



if __name__ == "__main__":

# Get the arguments
arguments = get_args()

# Get the input file to parse
inputPath = arguments.inputFile

# Get the output file to save to
outputPath = arguments.outputFile

json_data = convert_to_json(inputPath)

# Start the parsing and csv writing
outputfile = customParser(json_data, outputPath)

#print(outputfile.name)

# If a project ID was specified, send the file to Nucleus
if arguments.project_id:

# Send the newly created csv file to Nucleus if project id was specified
post_to_nucleus(outputfile)

# If no project ID was specified, just parse file to Nucleus format for manual file upload
else:

pass

0 comments on commit f9a9f81

Please sign in to comment.