Skip to content

Instantly share code, notes, and snippets.

@jonaslejon
Last active October 24, 2024 13:53
Show Gist options
  • Save jonaslejon/7007f001edbdbaabc38b2b47d5a8d39c to your computer and use it in GitHub Desktop.
Save jonaslejon/7007f001edbdbaabc38b2b47d5a8d39c to your computer and use it in GitHub Desktop.
Burp Suite CSV Log Parser
#!/usr/bin/env python3
"""
Burp Suite CSV Log Parser
This script parses a Burp Suite CSV log file, decodes base64-encoded HTTP requests and responses,
and prints them in a human-readable format with colored output for better readability.
Usage:
python burp_log_parser.py <input_file> --status_code <status_code> --filter_response <filter_response> --negative_filter_response <negative_filter_response> --response_only --json_output
Dependencies:
- termcolor: Install using `pip install termcolor`
"""
import csv
import base64
import argparse
import re
import json
import sys
from termcolor import colored
import csv
# Increase CSV field size limit to avoid field limit error
csv.field_size_limit(sys.maxsize)
def decode_burp_log(file_path, filter_status_code, filter_response, negative_filter_response, response_only, json_output):
log_entries = []
# Open the CSV file for reading
with open(file_path, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
# Filter based on status code if provided
if filter_status_code and row['Status code'] != filter_status_code:
continue
# Decode the base64-encoded HTTP response if it exists
if 'Response' in row and row['Response']:
response = base64.b64decode(row['Response']).decode('utf-8')
# Filter based on response content if provided (supports both text and regex)
if filter_response:
filter_patterns = filter_response.split(',')
if not any(re.search(pattern.strip(), response) for pattern in filter_patterns):
continue
# Filter out responses that match the negative filter (supports both text and regex)
if negative_filter_response:
negative_patterns = negative_filter_response.split(',')
if any(re.search(pattern.strip(), response) for pattern in negative_patterns):
continue
# If response_only flag is set, only print the response
if response_only:
if 'Response' in row and row['Response']:
print(colored(response, "yellow"))
print("\n")
continue
# Decode the base64-encoded HTTP request
request = row['Request']
decoded_request = base64.b64decode(request).decode('utf-8')
# Collect data for JSON output
log_entry = {
"ID": row['ID'],
"Time": row['Time'],
"Tool": row['Tool'],
"Method": row['Method'],
"Protocol": row['Protocol'],
"Host": row['Host'],
"Port": row['Port'],
"URL": row['URL'],
"Status Code": row['Status code'],
"Length": row['Length'],
"MIME Type": row['MIME type'],
"Comment": row['Comment'],
"Decoded HTTP Request": decoded_request,
"Decoded HTTP Response": response if 'Response' in row and row['Response'] else None
}
log_entries.append(log_entry)
# Skip printing if JSON output is selected
if json_output:
continue
# Print general information about the HTTP request/response
print(f"ID: {row['ID']}")
print(f"Time: {row['Time']}")
print(f"Tool: {row['Tool']}")
print(f"Method: {row['Method']}")
print(f"Protocol: {row['Protocol']}")
print(f"Host: {row['Host']}")
print(f"Port: {row['Port']}")
print(f"URL: {row['URL']}")
print(f"Status Code: {row['Status code']}")
print(f"Length: {row['Length']}")
print(f"MIME Type: {row['MIME type']}")
print(f"Comment: {row['Comment']}")
print("\n")
print(colored("Decoded HTTP Request:", "cyan"))
# Print the decoded HTTP request in green color
print(colored(decoded_request, "green"))
# Print the decoded HTTP response if it exists
if 'Response' in row and row['Response']:
print("\n")
print(colored("Decoded HTTP Response:", "cyan"))
# Print the decoded HTTP response in yellow color
print(colored(response, "yellow"))
print("\n")
# Print the output as JSON if the json_output flag is set
if json_output:
print(json.dumps(log_entries, indent=4))
def main():
# Set up argument parser to take input file, status code, and response filter from command line
parser = argparse.ArgumentParser(description='Parse and decode Burp Suite CSV log file.')
parser.add_argument('input_file', type=str, help='Path to the Burp Suite CSV log file')
parser.add_argument('--status_code', type=str, help='Filter results by HTTP status code', default=None)
parser.add_argument('--filter_response', type=str, help='Filter results by HTTP response content (supports text and regex, multiple patterns separated by commas)', default=None)
parser.add_argument('--negative_filter_response', type=str, help='Exclude results by HTTP response content (supports text and regex, multiple patterns separated by commas)', default=None)
parser.add_argument('--response_only', action='store_true', help='Only print the HTTP response data')
parser.add_argument('--json_output', action='store_true', help='Print the output as JSON')
args = parser.parse_args()
# Call the function to decode the Burp log with optional filters
decode_burp_log(args.input_file, args.status_code, args.filter_response, args.negative_filter_response, args.response_only, args.json_output)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment