The document discusses customizing Burp Suite by creating extensions using the Burp Extender API. It provides examples of building passive and active scanners, handling insertion points for active scanning, modifying requests through an HTTP listener, and debugging extensions. The goal is to customize Burp Suite functionality by adding new features through extensions.
3. 3
Burp Suite
• Burp Suite is a powerful tool for performing
security assessments
• Burp Plugin API allows new features to be
added
www.portswigger.net/burp/extender
4. 4
What Can I Do With Plugins?
• Passive Scanning
• Active Scanning
• Alter/append requests
• Define Insertion Points for Scanner/Intruder
• Create new payload types
• Automate Authentication
• Much, Much More
5. 5
Prerequisites
• Burp Suite Pro v 1.5.x+
• Java 1.6.x+
• NetBeans
• Other programming languages
– Jython
– JRuby
6. 6
Creating An Extension
• Download the Extender API from Portswigger:
portswigger.net/burp/extender/api/
burp_extender_api.zip
• Or export the API from within Burp
7. 7
Creating an Extension
• Create a new project with existing sources:
8. 8
Creating an Extension
• Create the BurpExtender class
– In package ‘burp’
– Implement IBurpExtender
12. 12
Building a Passive Scanner
Passive Scanning
• Search responses for problematic values
• Built-in passive scans
– Credit card numbers
– Known passwords
– Missing headers
13. 13
Building a Passive Scanner
Passive Scanning – Room for Improvement
• Error Messages
• Software Version Numbers
14. 14
Building a Passive Scanner
Building a Passive Scanner
• Implement the IScannerCheck interface:
• Register the extension as a scanner:
15. 15
Building a Passive Scanner
IScannerCheck.doPassiveScan()
16. 16
Building a Passive Scanner
IScannerCheck.doPassiveScan()
17. 17
Building a Passive Scanner
IScannerCheck.consolidateDuplicateIssues()
• Ensure an issue is only posted to scanner once
18. 18
Building a Passive Scanner
IScannerCheck.doActiveScan()
• Only needed for active scans
19. 19
Building an Active Scanner
Active Scanning
• Issue requests containing attacks
• Look for indication of success in response
• Built-In Active Scans
– XSS
– SQL Injection
– Path Traversal
– etc
20. 20
Building an Active Scanner
IScannerCheck.doActiveScan()
21. 21
Building an Active Scanner
Insertion Points
• Locations of parameters in request
• Contain data the server will act upon
24. 24
Building an Active Scanner
Defining Insertion Points
• Implement IScannerInsertionPointProvider
– getInsertionPoints()
• Register as an insertion point provider
25. 25
Building an Active Scanner
BurpExtender.getInsertionPoints()
27. 27
Building an Active Scanner
Viewing Insertion Points
• Add menu option to send request to Intruder
• Implement IContextMenuFactory
– createMenuItems()
• Register as a menu factory
28. 28
Building an Active Scanner
BurpExtender.createMenuItems()
I recently got done publishing a book, so I get to put ‘Author” on this slide.
What does Senior Application Security Consultant mean? It means a large portion of my job is pen tests. And I’m always looking for ways to make them easier and more fun.
Burp Suite
Burp Suite is the leading web application vulnerability testing tool. It is available from http://portswigger.net for $299/year –a fraction of the cost of some other commercially available web application testing tools.
Burp supports a plugin architecture which allows additional functionality to be developed and integrated with the tool. Anyone can download it and start adding new features to the tool.
I’ve spoken to some of you who are using plugins to do some truly incredible stuff like turning Burp into a full automated testing suite.
In the short time we have here today we won’t be able to get into cool stuff like that, but I want to give you the basic tools to get started writing your own extensions.
Development Requirements
You need Burp Suite Pro in order to use extensions.
If you have a Pro license, you automatically have access to the latest Burp versions, so no problem there.
Java 1.6.x is the minimum requirement to run Burp, but much newer versions are available.
I like NetBeans for its ease of use, but you can use any IDE, or even a simple text editor
You can also write Burp extensions in Python using Jython, OR Ruby using Jruby, but Java is the native language of Burp Suite (and me) so that will be the focus of this talk today.
You must download the Burp Extender API from Portswigger in order to create an extension. The Extender API contains interfaces you will implement to develop different kinds of plugin functionality.
You can also export the API from within Burp Suite itself by going to Extender -> APIs and clicking Save interface files.
This shows NetBeans but you can use your own IDE, or even a text editor.
The key part is to create your project using the existing API files that you downloaded.
The BurpExtender class is the guts of any extension. It must be named BurpExtender and be in the burp package.
Implementing IBurpExtender tells Burp Suite that this is an extension that can be loaded and provide additional functionality to the program.
You will now have a project structure like this. For some reason Burp Suite requires each extension to have their own copy of all of the Extender interfaces, even though they are included in the Burp Suite jar itself.
The registerExtenderCallbacks method is called when Burp loads the extension. This is where you can perform any initialization tasks your extension needs.
It is passed an instance of IBurpExtenderCallbacks. This class allows your plugin to get access to internal Burp methods and this is the only time you will be able to get the callbacks object, so it is important to store it in the extension now.
IBurpExtenderHelpers is another useful class that allows you to do things like issuing and parsing HTTP requests, encoding/decoding, etc. You will probably use it a lot, so just store a reference to it in your extension.
Finally, we can set the name for the extension. This is what will be displayed in Burp’s list of loaded extensions.
To load the extension:
Go to Burp’s Extender tab and click Add
Select the compiled jar file, then click Next
You should see an output screen saying “the extension loaded successfully”
Finally, you will see the new extension in the list of extensions
Passive Scanning
Passive scanning allows you to monitor responses for certain values and flag them as issues in the Burp Scanner tab.
Burp includes built in passive scanning for things like credit card numbers, previously used passwords, missing headers like X-Frame-Options, etc.
Error messages can reveal valuable details about the inner workings of an application
Software version numbers can inform you as to the overall health of an organization’s operations: When they are patched, how up to date, etc.
These things are often only revealed in error pages - things that might be responses to Scanner or Intruder requests, but not necessarily seen by a tester.
Burp has no facility to detect them on its own. Enter the Plugins!
To build a passive scanner you must implement the IScannerCheck interface and register it as a scanner check with the Extender Callbacks.
IScannerCheck requires you to implement 3 methods.
Registering the extension as a scanner check is a simple method call to the callbacks object and can be done when the extension initializes.
Passive scanners must implement the doPassiveScan method. This is where the meat of your extension’s work will be done.
In this case we get the body of the response, then iterate over a list of regular expressions (contained in the MatchRule objects) attempting to match them to the body.
When we find a match, we save it in a ScannerMatch object (just a simple Java bean defined as an inner class) which we will add to Burp’s Scanner results.
Once we have found matches of our regex, we want to add them to the Burp Scanner interface.
1. First, we need to sort the matches. This is important because in order for code highlighting to work, Burp wants all matches to be in order.
2. Next create the description that will appear in the Scanner Advisory panel.
3. Iterate through the scanner matches and turn them into a List of stop and start positions for the code highlighting
4. Finally return a CustomScanIssue (an POJO object that extends IScanIssue) to be added to the Scanner
If no issues are found, simply return null
consolidateDuplicateIssues is called by Burp to ensure that the same issue only shows up once on Burp’s Scanner list.
It essentially works like any other Java Comparable:
Return -1 to keep the old issue and discard the new one
Return 0 to report both issues
Return 1 to report the new issue and discard the old one
doActiveScan is part of the IScannerCheck interface, but it is only used when doing an active scan. Nevertheless, we still have to implement it in order to build a valid class.
In the case of our passive scan, we can simply return null.
This brings us to our next topic, Active Scanning.
Active scanning is excellent for finding injection type vulnerabilities, like SQLi, XSS and others. Active scanning is more complicated because it requires you to issue requests and look for success in the responses.
Here we will be building an example active scanner to test for server-side injection on a JavaScript-based website, for example using node.js.
When building an active scan, we do the opposite of what we did with a passive scanner: Implement doActiveScan and have doPassiveScan return null.
doActiveScan is called for each insertion point of each request that the Burp Scanner makes. Here we iterate through our injection tests, and for each:
Compile a test request
Issue the request
Look for matches in the response, and if any are found, report an issue
In all other respects, doActiveScan and doPassiveScan both perform the same way.
Insertion Points define the locations within a request that contain data that the server will act upon.
Insertion points are used by the Active Scanner or Burp Intruder to target attack payloads.
You can see the insertion points that Burp identifies by right-clicking a request and selecting Send to Intruder.
Burp does a pretty good job defining insertion points on its own for regular HTTP requests.
But what if your request looks like this? This is a Google Web Toolkit request, and Burp’s built-in request parser doesn’t do such a good job.
Somewhere inside that huge block of condensed text, we know that there is data that the server is going to act upon. Sure, in Intruder we can actively select each one, but that is time consuming and… boring.
So how can we teach Burp to automatically know where they are?
To have your extension define insertion points, you must implement IScannerInsertionPointProvider. This consists of one method: getInsertionPoints()
You also need to register as an insertion point provider. This can be done in the registerExtenderCallbacks method when your extension initializes.
Implementing getInsertionPoints is easy. The method is passed the HTTP request. We parse that request to determine the offsets of the insertion points we want to use. In this case, I did some research and found existing parsers, but they all missed something, so I wound up writing my own. How it works is unimportant, just know that it returns a set of offsets: The start/stop index of the insertion point within the raw request.
Once we know the offsets, we create a List of IScannerInsertionPoint objects using the helpers object we got form the callbacks.
getInsertionPoints() is called automatically when you send an item to the active scanner. If you send a request to the scanner, you can see that it now has 5 insertion points, rather than the 2 that Burp originally identified.
If you want to see the actual insertion points that your extension defines you have to send the request to Intruder. Burp’s own Send to Intruder option will use the built-in insertion points, so you need to add your own option to the right-click menu.
To do that you will need to implement the IContextMenuFactory interface and add the createMenuItems() method.
You also need to register as a context menu factory. This can be done in the registerExtenderCallbacks method when your extension initializes.
The createMenuItems method is passed an Invocation object by Burp. This object contains the request or requests that were selected when the mouse was right clicked.
We want to create a new standard Swing JMenuItem and attach an ActionListener that will fire when the menu item is clicked.
This method actually wants you to return a Collection of menu items. That way your extension can define more than one menu item.
The MenuItemListener is an inner class that implements ActionListener just like any other Swing component.
It has an actionPerformed method that takes an array of request-response objects and passes them to a method that parses them and sends them to Intruder.
The method called by the MenuItemListener parses each request in turn to see if it can locate GWT insertion points.
If insertion points are found, that indicates that the request is a GWT request. Then it invokes the sendToIntruder method of the callbacks, passing the request with the new insertion points to Intruder.
Now you can right-click on a request in any of Burp’s Tools and there will be a new option in the context menu to send a GWT request to Intruder.
In Intruder you can now see the 5 new insertion points that our extension defined.
Some web services require you to send a custom header or signature with your requests. Or maybe you need to add a constantly rotating anti-CSRF token to each request.
In that case you will need to do request modification.
To setup your extension to modify requests you need to implement IHttpListener. This has one method: processHttpMessage()
You also need to register the class as HTTP listener. Again, this is done in registerExtenderCallbacks
The processHttpMessage method is called by Burp for each HTTP request before it is sent to the server, and for each response, before it is returned to the browser.
The fist thing we need to do then is determine if this is a request or response. Fortunately Burp passes a boolean to this method to tell you.
Next we need to determine whether this is a request for a URL we actually want to sign. This makes use of a handy method in the Burp callbacks called isInScope()
Finally we check if the request is coming from a tool that we want to do signing for. For example, if you have a request in the repeater, you might not want to automatically sign it if you are trying to tamper with the signature itself. This is done by checking whether the toolFlag passed in to the method matches the tool values defined in the API.
If all of those things are true, you actually proceed to signing the request.
To sign the request you must first retrieve the request form the request-response object passed by Burp.
The Burp Extender API provides some excellent tools for parsing and modifying HTTP messages. You can easily add, modify and delete parameters, but unfortunately it does not provide the same facility for headers. It also cannot guarantee that parameters and headers will follow a certain order. So I had to create my own request parser, the HttpMessage class.
The signature class does the actual signing of the request. It sorts and canonicalizes the parameters and headers, and computes an HMAC of the request using your AWS secret key. I’m not going to get into that here, you can check the AWS docs if you want to know how that works.
The important part is that the signature returns the raw bytes of the signed request. These are then set back into the request-response object so that Burp can send the modified request to the server.
The Burp Extender API now offers methods to print Strings to the Extension’s output and error logs. This was actually a suggestion I submitted on the Burp Suite Forums.
If you want to see stack traces you can use e.printStackTrace() and the stack trace will show up in the terminal where you launched Burp.
Calling printOutput causes the message to be written to the Output tab on the Extensions panel, directly within the Burp GUI
You can still also select to output to the terminal where you launched Burp, or save it to a file, which could be useful if you want to do further analysis.
You can call printStackTrace and write a stack trace to the terminal where you opened Burp.
To show a stack trace in Burp’s own interface, you need to get the actual OutputStream from the callbacks.
Then, create a method to print an exception stack trace directly to that OutputStream.
Now stack traces will show up directly within the Burp GUI
We’ve talked about getting setup to develop, We’ve built extensions for passive scanning, active scanning, and handling custom requests.
If it looked easy, that’s because it is easy! So get out there and customize Burp for your hacking needs!
All of the extensions we talked about today are on my website. The source code is available on Google Code.
Feel free to download and use them. I would love to hear your feedback!
There is a link right on my site to contact me if you want to get involved, or if you have any questions about your extensions.