Created
March 7, 2021 03:08
-
-
Save SafeEval/31cae3d6916dbd00b0b2ba9fa2692799 to your computer and use it in GitHub Desktop.
PoC: Automatic commenting from Burp Turbo Intruder scripts
This file contains 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
""" | |
poc-turbo-intruder-messageinfo-comment.py | |
Jack Sullivan <jack@divergent.codes> | |
This is a Burp Turbo Intruder PoC that shows how to automatically set the comment | |
field from a Turbo Intruder script. Each comment will be persisted across other | |
Burp plugins, like Logger++. | |
The approach is to register a IHttpListener class that captures and exposes | |
each IHttpRequestResponse object in a way that can be called from other | |
portions of a Turbo Intruder script, like `queueRequests` and `handleResponse`. | |
Yes, it might be over-engineered, but it works! ;) | |
""" | |
############################################################################# | |
# HTTP listener class and functions for Turbo Intruder messageInfo modification | |
############################################################################# | |
class TurboIntruderMessageInfoHttpListener(burp.IHttpListener): | |
name = 'TurboIntruderMessageInfoHttpListener' | |
_callbacks = None | |
_call_count = 0 | |
request_messages = [] | |
response_messages = [] | |
comment = 'Default Comment' | |
def set_callbacks_reference(self, callbacks_ref): | |
self._callbacks = callbacks_ref | |
def console_log(self, message): | |
if not self._callbacks: | |
return | |
self._callbacks.printOutput('[%s] %s' % (self.name, message)) | |
def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): | |
self._call_count += 1 | |
if not self._callbacks: | |
return | |
tool_name = self._callbacks.getToolName(toolFlag) | |
if tool_name != 'Extender': | |
return | |
#### Requests #### | |
# Setting comments on requests can be done from here. | |
if messageIsRequest: | |
self.request_messages.append(messageInfo) | |
messageInfo.setComment(self.comment) | |
#### Responses #### | |
# Setting a response comment from here results in something like "$LPP:47:f20286db-2b3a-4a6d-8ae5-6d15e406f5b7$" | |
# Let the handleResponse() handler use it via HTTP_LISTENER.response_messages[] | |
if not messageIsRequest: | |
self.response_messages.append(messageInfo) | |
def get_matching_http_listeners(): | |
# Collect existing listeners registered by this extension. | |
http_listeners = callbacks.getHttpListeners() | |
# Find matching listeners. | |
matches = [] | |
for hl in http_listeners: | |
if TurboIntruderMessageInfoHttpListener.name in str(type(hl)): | |
matches.append(hl) | |
return matches | |
def clear_http_listeners(): | |
matches = get_matching_http_listeners() | |
callbacks.printOutput('Removing %s existing HTTP listener(s)' % len(matches)) | |
[callbacks.removeHttpListener(hl) for hl in matches] | |
def create_http_listener(): | |
callbacks.printOutput('Creating HTTP listener') | |
http_listener = TurboIntruderMessageInfoHttpListener() | |
http_listener.set_callbacks_reference(callbacks) | |
callbacks.registerHttpListener(http_listener) | |
return http_listener | |
def initialize_http_listener(): | |
matches = get_matching_http_listeners() | |
if not matches: | |
return create_http_listener() | |
return matches[-1] | |
############################################################################# | |
# Standard Turbo Intruder code | |
############################################################################# | |
#clear_http_listeners() | |
HTTP_LISTENER = initialize_http_listener() | |
def queueRequests(target, wordlists): | |
engine = RequestEngine( | |
endpoint=target.endpoint, | |
concurrentConnections=1, # Single concurrent connection to force sequential order. | |
engine=Engine.BURP, # Use Burp's network stack, so state is persisted across tools. | |
) | |
for i in range(0, 3): | |
# Can set persisted label per request here, and use it to | |
# set the comment on the response in handleResponse. | |
label = '#%s' % i | |
engine.queue(target.req, i, learn=1, label=label) | |
# Only a single comment value can be applied in queueRequests(). | |
# The comment set here will be applied to all queued requests in the Turbo Intruder run. | |
# Setting the response comment in handleResponse() will override it. | |
#HTTP_LISTENER.comment = 'queueRequests Comment' | |
def handleResponse(req, interesting): | |
# Commenting on the most recent request has no effect. Default comment will be used. | |
#last_request = HTTP_LISTENER.request_messages[-1] | |
#last_request.setComment('[Request] %s' % req.label) | |
# Commenting on the most recent response will be set. | |
last_response = HTTP_LISTENER.response_messages[-1] | |
last_response.setComment('[Response] %s' % req.label) | |
table.add(req) |
Author
SafeEval
commented
Mar 7, 2021
I was looking for this for a long time, thank you very much
Sure thing. Glad you found it useful.
I use this gist but the output panel show requestsPerConnection has been forced to 1 and pipelining has been disabled due to Burp engine limitations
, is this gist can't be used now?
I might have some time over the weekend to see if this needs any tweaks.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment