Created
January 7, 2022 00:11
-
-
Save thypon/21bd25a36149256115905e5c330ed14d to your computer and use it in GitHub Desktop.
Create a CSV containing all the cookies encountered during a BURP scan
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Author: Andrea Brancaleoni | |
# Version: 1.0 | |
# License: MIT License | |
from burp import IBurpExtender | |
from burp import IHttpListener | |
from burp import IProxyListener | |
from burp import IContextMenuFactory | |
from javax.swing import JMenuItem, JFileChooser | |
from java.awt.event import ActionListener | |
from java.lang import System | |
from java.io import File | |
from java.io import PrintWriter | |
import re | |
import csv | |
import json | |
class BurpExtender(IBurpExtender,IContextMenuFactory,ActionListener): | |
def registerExtenderCallbacks( self, callbacks): | |
# Keep a reference to our callbacks and helper object | |
self.callbacks = callbacks | |
self.helpers = callbacks.getHelpers() | |
self.stdout = PrintWriter(callbacks.getStdout(), True) | |
self.callbacks.setExtensionName("GDPR Reporter") | |
self.stdout.println("GDPR Reporter is loaded") | |
self.enable_cookiejar() | |
#IExtensionHelpers helpers = callbacks.getHelpers() | |
callbacks.registerContextMenuFactory(self) | |
return | |
def enable_cookiejar(self): | |
try: | |
j = json.loads(self.callbacks.saveConfigAsJson()) | |
j['project_options']['sessions']['cookie_jar']['monitor_extender'] = True | |
j['project_options']['sessions']['cookie_jar']['monitor_intruder'] = True | |
j['project_options']['sessions']['cookie_jar']['monitor_proxy'] = True | |
j['project_options']['sessions']['cookie_jar']['monitor_repeater'] = True | |
j['project_options']['sessions']['cookie_jar']['monitor_scanner'] = True | |
j['project_options']['sessions']['cookie_jar']['monitor_sequencer'] = True | |
self.callbacks.loadConfigFromJson(json.dumps(j)) | |
except Exception as ex: | |
print("Cannot enable * Cookie Jar! %s" % ex) | |
finally: | |
sys.stdout.flush() | |
sys.stderr.flush() | |
def prepare_cookies(self): | |
self.cookies = {} | |
self.attributes_keys = set() | |
for r in self.callbacks.getProxyHistory(): | |
reqinfo = self.helpers.analyzeRequest(r) | |
url = reqinfo.getUrl() | |
self._process_request(url, reqinfo, r.getRequest()) | |
self._process_reponse(url, self.helpers.analyzeResponse(r.getResponse()), r.getResponse()) | |
for icookie in self.callbacks.getCookieJarContents(): | |
self.add_cookie(icookie.getName(), {"Value": icookie.getValue(), "Domain": icookie.getDomain(), "Path": icookie.getPath(), "Expiration": icookie.getExpiration()}, override=True) | |
def merge_two_dicts(self, x, y): | |
z = x.copy() # start with keys and values of x | |
z.update(y) # modifies z with keys and values of y | |
return z | |
def add_cookie(self, cookie, attributes, override=False): | |
for k in attributes.keys(): | |
self.attributes_keys.add(k) | |
if not cookie in self.cookies: | |
self.cookies[cookie] = {} | |
if override is False: | |
self.cookies[cookie] = self.merge_two_dicts(attributes, self.cookies[cookie]) | |
else: | |
self.cookies[cookie] = self.merge_two_dicts(self.cookies[cookie], attributes) | |
def _process_request(self, url, reqinfo, reqbody): | |
""" | |
Process request and extract key values | |
:param domain: | |
:param reqinfo: | |
:param reqbody: | |
:return: | |
""" | |
for h in reqinfo.getHeaders(): | |
if h.lower().startswith("cookie:"): | |
cookies = h[7:].strip() | |
for c in cookies.split(';'): | |
ckey, cvalue = c.strip().split('=') | |
self.add_cookie(ckey, {'Value': cvalue, 'Domain': url.getHost()}) | |
def _process_reponse(self, url, respinfo, respbody): | |
""" | |
Process response and extract key values | |
:param domain: | |
:param reqinfo: | |
:param reqbody: | |
:return: | |
""" | |
for h in respinfo.getHeaders(): | |
if h.lower().startswith("set-cookie:"): | |
set_cookies = h[11:].strip() | |
ckey, cvalue = set_cookies.split(';', 1)[0].strip().split("=") | |
attributes = {'Value': cvalue, 'Domain': url.getHost()} | |
for s in set_cookies.split(';', 1)[1].strip().split(';'): | |
if '=' in s: | |
attrkey, attrvalue = s.strip().split("=") | |
else: | |
attrkey = s.strip() | |
attrvalue = True | |
attributes[attrkey] = attrvalue | |
self.add_cookie(ckey, attributes, override=True) | |
def createMenuItems(self, invocation): | |
if invocation.getInvocationContext() == invocation.CONTEXT_PROXY_HISTORY: | |
mymenu = [] | |
item = JMenuItem("Generate GDRP report") | |
item.addActionListener(self) | |
mymenu.append(item) | |
return mymenu | |
else: | |
return None | |
def _directory_picker(self): | |
""" | |
Run the filepicker and return if approved | |
:return: boolean, true if approved | |
""" | |
fileChooser = JFileChooser() | |
fileChooser.setCurrentDirectory(File(System.getProperty("user.home"))) | |
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) | |
result = fileChooser.showOpenDialog(None) | |
isApproveOption = result == JFileChooser.APPROVE_OPTION | |
if isApproveOption: | |
selectedFile = fileChooser.getSelectedFile() | |
self.write_file(selectedFile.getAbsolutePath()) | |
return isApproveOption | |
def write_file(self, dname): | |
attributes = list(self.attributes_keys) | |
header = ['Cookie Name'] + attributes | |
with open(dname+"/gdpr.csv", 'w') as f: | |
writer = csv.writer(f) | |
# write the header | |
writer.writerow(header) | |
for k in self.cookies.keys(): | |
v = self.cookies[k] | |
row = [k] | |
for a in attributes: | |
if a in v: | |
row += [v[a]] | |
else: | |
row += [None] | |
writer.writerow(row) | |
def actionPerformed(self, actionEvent): | |
self.prepare_cookies() | |
selectedFile = self._directory_picker() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment