In the web application penetration testing industry, Burp Suite is considered a must-have tool – it includes an intercepting proxy, both active and passive web vulnerability scanners, crawler, session ID analysis tools and various other useful features, all under a single application. One of Burp's best features is the Intruder, a tool which allows the tester to provide a list of values which should be sent to the application as parameter values. By providing values which trigger SQL errors or inject Javascript into the resulting page, one can easily determine if and how the application is doing filtering on the parameters, and whether it is vulnerable to a given issue.
Burp's Intruder works perfectly when the application responds to those requests as if they came from the user. The screenshot above shows the submission of the following HTML form:
<form action="/CSRFGuardTestAppVulnerable/HelloWorld" method="POST" name="first"> <input type="text" value="SpiderLabs" name="name"> <input type="submit" value="submit" name="submit"> </form>
However, modern application frameworks are adding support for Anti-CSRF (Cross-Site Request Forgery) techniques, which protect the application from forged requests such as those Burp uses. The most commonly implemented prevention measure is the Synchronizer Token Pattern, which adds a parameter with a random value to all forms generated by the application for a given user session, and validates this token when the form is submitted. For example:
<form action="/CSRFGuardTestApp/HelloWorld" method="POST" name="first"> <input type="text" value="SpiderLabs" name="name"> <input type="submit" value="submit" name="submit"> <input type="hidden" value="Z0XN-1FRF-975E-GB9F-GGQM-L2RC-04H1-GKHQ" name="OWASP_CSRFTOKEN"> </form>
Because the OWASP_CSRFTOKEN parameter will change between every submission, the Intruder will not work, as it expects the application to respond to the request as if they came from the user. The solution is rather simple: instead of simply feeding a set of values to the parameters being tested, we need to have the Intruder populate the Anti-CSRF token parameter from the form page.
This changes the default behavior of the Intruder tool quite a bit. First, it must know which parameter represents the Anti-CSRF token in the request. While many frameworks will use parameter names that include the "csrf" string, this can be configured per application, and thus we cannot rely on automatic detection. Second, it means the Intruder must make twice the number of requests it would normally perform: one to fetch the form page, which contains the Anti-CSRF token embedded in it, and a second one to actually submit the form with the parameter values provided by the tester. We will address both issues by developing a Burp extension called CSRF Intruder.
Burp offers an extensibility API, called Burp Extender, which allows us to hook into various points in the application, including the UI and the request interception engine. The first thing we need to do is create a Java class which will host our extension.
package burp; import spiderlabs.burp.intruder.CSRFIntruder; public class BurpExtender { private IBurpExtenderCallbacks callbacks; private CSRFIntruder csrfIntruder; public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { this.callbacks = callbacks; this.csrfIntruder = new CSRFIntruder(this.callbacks); this.callbacks.registerMenuItem("CSRF Intruder", this.csrfIntruder); this.callbacks.issueAlert(String.format("Starting up CSRF Intruder extension [%s]", this.getClass().getCanonicalName())); } public void processHttpMessage(java.lang.String toolName, boolean messageIsRequest, IHttpRequestResponse messageInfo) { /* Intercept Intruder requests and check if they came from CSRF Intruder */ if (toolName.equals("intruder") && messageIsRequest) this.callbacks.issueAlert("TODO: Intercept CSRF Intruder requests"); } }
The registerExtenderCallbacks() method acts as the extension constructor, and is the first method called by Burp when the extension is loaded. It provides us with a IBurpExtenderCallbacks instance, which we use to create a new context menu entry for our CSRF Intruder handler. We also implement a processHttpMessage() method, which we will use to intercept Intruder requests and modify the Anti-CSRF token velues before they are sent to the remote application.
How does Burp use this class? It must obey a series of restrictions before Burp can find and use it:
- It must be in package burp;
- It must be named BurpExtender;
- It must implement at least one of the methods in interface IBurpExtender;
- Burp must be executed with the JVM classpath pointing to our BurpExtender class:
java -classpath burp.jar;BurpProxyExtender.jar burp.StartBurp
If these criteria are met, then when Burp starts up our CSRF Intruder extension message should show up in the Alerts tab.
We can now right-click everywhere where a "Send to [...]" menu entry is displayed and click on "CSRF Intruder".
Clicking on the CSRF Intruder menu entry will trigger the handler in our CSRFIntruder class, shown below:
package spiderlabs.burp.intruder; import javax.swing.JOptionPane; import spiderlabs.burp.intruder.gui.CSRFConfigurationDialog; import burp.IBurpExtenderCallbacks; import burp.IHttpRequestResponse; import burp.IMenuItemHandler; public class CSRFIntruder implements IMenuItemHandler { private IBurpExtenderCallbacks callbacks; public CSRFIntruder(IBurpExtenderCallbacks callbacks) { this.callbacks = callbacks; } @Override public void menuItemClicked(String caption, IHttpRequestResponse[] messageInfo) { try { IHttpRequestResponse message = messageInfo[0]; String refererUrl = new String(); for (String header: this.callbacks.getHeaders(message.getRequest())) { System.out.println(header); if (header.startsWith("Referer:")) refererUrl = header.split(":\\s")[1]; } String parameters[][] = this.callbacks.getParameters(message.getRequest()); CSRFIntruderConfiguration configuration = CSRFConfigurationDialog.getConfigurationFromDialog(refererUrl, parameters); this.callbacks.issueAlert(configuration.toString()); } catch (Exception exception) { this.callbacks.issueAlert(String.format("Error while obtaining request URL: %s", exception.toString())); } } }
The menuItemClicked() handler does two things: first, it fetches the value of the Referer header (if present) from the request the user right-clicked on and uses it as the suggested source form URL, that is, the place where we can find the Anti-CSRF token values; next, it obtain a list of all parameters in that request. It then sends those to a CSRFConfigurationDialog, which displays the URL and parameters, and waits for the user to configure the Anti-CSRF parameters.
When the user provides the URL and the token parameter to be used, we already have all the information necessary to start up Intruder and manipulate its requests. This will come on a second post.

Blubbfiction & Trevor: You are right, I was not aware that Burp's macros could do this when I started working on this extension. The main advantage to the approach I'm taking is ease of use and less setup work -- you will not need to keep rules, you just select one or more anti-CSRF parameters from a source URL, and their values will be properly populated when used together with Intruder.
If Burp Extender offered a way to interface with the macro functionality, then I would probably turn this into an easier interface for the current implementation. At least we will have a nice description on how to extend Burp using the Extender, or so I hope. :)
Posted by: Urma | 01 October 2012 at 15:50
Blubbfiction is right, this can all be done with session handling rules and macros. What added benefit does your tool provide?
Posted by: Trevor Stevado | 01 October 2012 at 15:35
What is the advantage to burps session handling rules?
Posted by: Blubbfiction | 30 September 2012 at 15:01
Go way, use "recursive grep".
Posted by: Heyder Andrade | 28 September 2012 at 09:17
Fantastish. I love it, well done guys. keep it up
Posted by: N0x00 | 28 September 2012 at 07:36
damn grt.. keep it up.. :)
Posted by: Security | 28 September 2012 at 06:16
Good stuff, burp should integrate antixsrf on intruder by default.
Posted by: P1erz | 28 September 2012 at 00:39