Using Groovy in BurpSuite with BurpKit
In August of 2015, I released a tool at DEFCON 23 called BurpKit. BurpKit is a plugin for the de-facto web penetration testing tool, BurpSuite. It incorporates WebKit, the software rendering engine used by Safari and others, and provides a bi-directional bridge between BurpSuite and the document object model (DOM); or in less geeky terms, gives you the ability to write cool web penetration testing plugins using JavaScript! If you're interested in learning more, take a look at my presentation on the DEFCON media servers.
As an added bonus I added a Jython tab which allowed plugin developers to write quick and dirty BurpSuite plugins in Python. The tab includes a rudimentary IDE and a live Jython interpreter so that you can quickly test your plugin without having to compile and package anything in an IDE.
The Problem
I was tinkering around one day with a pretty complex web application for a client. One of the controllers I was fuzzing accepted file uploads and I was trying various ways to get a JSP file uploaded. I found myself constantly flipping back and forth, copying and pasting text, from my IDE into the repeater tab.
After a while I got frustrated and figured that there must be a better way to do this. I finally caved in and started writing a Jython plugin using the Jython tab in BurpKit. Why did I use Jython instead of JavaScript to write this plugin? The reason was simple: I needed to use the full feature-set of the JAVA programming language and BurpKit's JavaScript bridge only provides access to the BurpSuite Extender API.
The Solution
A while ago I got introduced to Grails. Grails is a JAVA-based web application development framework which uses Groovy (http://www.groovy-lang.org/) as its primary programming language. One of the things I enjoyed most about Groovy/Grails was its powerful string templating features like the ability to execute a snippet of code within a string like so:
distance = 400
speed = 100
s = "The average time it takes to get to Toronto is ${distance/speed} hours" // -> Evaluates to "The average time it takes to get to Toronto is 4 hours"
So I decided to take advantage of this feature and leverage the power of Groovy and BurpKit to process "request templates" in BurpSuite.
The Approach
I wanted to implement two new plugins using Jython:
- An extra text editor tab which allowed a user to embed a Groovy string template variable in the body of an HTTP request. The user could flip back to the
Raw
tab in BurpSuite to see the rendering results. - A context menu item that could be used to render a Groovy string template variable within the body of an HTTP request in the
Raw
tab.
In other words, be able to type something like this in your Groovy Templater
tab:
POST /fileupload HTTP/1.1
Host: foo.com
...
${new File('/path/to/myshellfile.txt').text}
And have it show up as:
POST /fileupload HTTP/1.1
Host: foo.com
...
<Contents of myshellfile.txt here>
in my Raw
editor tab. I first took a look at how Grails implemented string templating but it became clear early on that there would be significant overhead associated with this approach. Instead I opted to use the Groovy StreamingTemplatingEngine
out of the many Groovy-based string template engines, instead. It came bundled with Groovy's all-in-one jars (groovy-all-x.x.x.jar
) and it could do everything I was looking for.
Here's an example of how you can use the StreamingTemplateEngine
from Jython:
engine = StreamingTemplateEngine()
template = engine.createTemplate('The average time it takes to get to Toronto is ${distance/speed} hours')
print template.make({'distance': 400, 'speed': 100}).toString()
# -> The average time it takes to get to Toronto is 4 hours
Finally, to make the code as easy as possible to run with no modifications, I decided that the plugin should programmatically download and import the Groovy all-in-one jar from Maven Central at runtime. The plugin would save the jar in the user's home directory under a .burpkit
directory.
Powered with my new found knowledge and vision, I set out to write my Groovy Templater
plugin.
The Implementation
The following sections highlight the interesting parts of the code. If you just want the end result, then you can find it here.
Downloading and Importing Dependencies Dynamically
Before we can import StreamingTemplateEngine
we need to download the groovy-all.jar
file and add it to our class path at runtime. This can be done using two simple modules: urllib
and sys
.
We can use urllib
's URLopener
class to download and save our file in one line:
from urllib import URLopener
URLopener().retrieve(url, '/tmp/groovy-all.jar')
Once we've got our JAR file downloaded, we can then append it to our JAVA class path using sys.path.append()
:
sys.path.append('/tmp/groovy-all.jar')
If successful, we should now be able to import StreamingTemplateEngine
and use it in our plugin:
from groovy.text import StreamingTemplateEngine
At this point, if you haven't encountered an Exception, it means you've successfully downloaded and imported the StreamingTemplateEngine
class.
The next steps involve implementing the IMessageEditorTab
, IMessageEditorTabFactory
, and IContextMenuFactory
classes to create our custom Groovy Templater
tabs and context menus:
from burp import IMessageEditorTab, IMessageEditorTabFactory, IContextMenuFactory
class TemplateTab(IMessageEditorTab):
def __init__(self, controller, editable):
self._engine = StreamingTemplateEngine()
# ...
def getMessage(self):
# ...
return self._message
# etc.
class TemplateTabFactory(IMessageEditorTabFactory):
def createNewInstance(self, controller, editable):
return TemplateTab(controller, editable)
# etc.
Once you've created your factory and implementation classes, the next step is to register them with Burp's extender API. Since you're already operating within BurpKit's context, you do not need to create an IBurpExtender
class. You can register the factories by using the burp
variable in the Jython global namespace (globals()
), like so:
factory = TemplateTabFactory()
burp.registerMessageEditorTabFactory(factory)
Easy peasy, right? The full implementation can be found here: BurpKit GroovyTemplater Example. To load the example, make sure you have BurpKit installed. Navigate to the Jython
tab and click Load Script
, select groovyTemplater.py
, and click Run Script
. Alternatively, you could just copy-and-paste the groovyTemplater.py
code right into the top pane and click Run Script
. If successful you should see the following output in the Jython console:
registering new context menu factory
registering new message editor tab factory
>>>
Here's a screenshot of the plugin in action:
Pretty groovy, right?
Conclusion
Writing Burp plugins can be easy when using BurpKit and it's full set of features. We've demonstrated that you don't necessarily need to open an IDE to mock up a quick-and-dirty BurpSuite plugin and that building plugins can be interactive and fun!
Thanks for reading this blog post and I hope it helped! As usual if you have any questions or require any clarifications feel free to drop me a line!