Web applications often implement some form of Cross-site Request Forgery (CSRF) protection, such as a viewstate parameter that is passed through requests, or a per-session nonce (if they don’t, well, that’s a finding worth documenting!) These parameters are used to verify that the request received was sent from the intended user, and was not an attacker-forged request.
These parameters, which are intended to stop attackers from being able to coerce users into making forged requests, tend to be annoying to application security consultants during assessments. Typically scanners and other automated tools fail at correctly handling these parameters, and as such, are not effective.
This post will highlight a method for handling these CSRF prevention tokens using Burp Intruder’s Recursive Grep payload.
To work through the example, we will be using an example app that we have developed. This application is a very basic search form with a CSRF prevention token.
Our goal is to test the application for a cross-site scripting vulnerability within the search functionality.
When we first load the page, we view the page source to see that there’s a hidden field named csrf_token. This token changes every time the page is reloaded.
In order to automatically test this functionality, we need some method of submitting a correct csrf_token with each request. Submitting anything that does not match the expected value may cause errors or show up in server logs.
Burp intruder offers a payload type called Recursive Grep that “lets you extract each payload from the response to the previous request in the attack” . We can use this functionality to extract the CSRF token from the HTML source, and replay in the next request, allowing us to launch automated fuzzing attempts.
We can use Burp’s Recursive Grep payload to extract the csrf_token value, in tandem with the xssValidator payloads to automate detection of XSS in applications with CSRF prevention mechanisms.
Let us demonstrate
Begin by sending a request to intruder, as you would normally. Define the insertion points that you want to fuzz. After you have defined all the insertion points you need to find the location of the CSRF token within the HTTP request and define this as a payload, too. Be sure to take a note of which number position this payload is, because that will be important for the next step.
After defining the payload positions we need to set the attack type. For this example we’ll be using the Pitchfork attack type.
We want to start by configuring the payload for the csrf_token parameter within the cookie header. In this case, it’s position one. Define the payload type as Recursive grep as seen in the screenshot below.
Next, we need to define the location of the payload to be extracted within the HTTP response body. To do so, navigate to the Options tab and browse down to the Grep – Extract panel.
Click the add button and a panel will popup allowing you to define the extract grep item. There are a few options: we can define a start and end, or use a regex to pick out the term. In this example we’ll be defining a start and end position.
To define the locations, simply highlight the specific area of interest within the HTTP response. The information can be within the header or the body.
After highlighting the desired region, you will see that the start and end positions are defined automatically. Click OK and you should now see an entry in the Grep – Extract panel.
Note: by default Burp limits the capture length to 100 characters. In many instances this will be too small, so don’t forget to adjust!
The Recursive Grep payload requires that the intruder attack consist of only one thread. This is necessary to ensure that the payload values are replayed as intended. Navigate to the Request Engine panel, and set the number of threads to one.
At this point, we need to finish configuring the payload. Browse back to the payloads tab, and navigate to the recursive grep payload set. Under payload options you should now see an option to select the extract grep item from the list. Ensure that it’s selected. [Payload options Recursive grep] You will see that for this example we have provided an initial payload value. Quite often when testing CSRF protected applications you will need to obtain a valid token for the first request. This will ensure that we’re not triggering any anti-csrf functionality by not sending a legitimate token.
At this point we are done defining the recursive grep payload and can continue defining our other payloads.
In the example application we have two more: Search and csrf_token. The search parameter is the parameter we’re trying to inject. The csrf_token parameter is another position that is expecting the CSRF token.
We’re looking to test the application for XSS, and as such, we leverage the xssValidator extender to test payload position number 2. This extender leverages an external phantomJS server to accurately detect XSS vulnerabilities through Burp intruder. For more information, check out our blog post: Accurate XSS Detection with BurpSuite and PhantomJS
Now, in position 3 we need to provide the csrf_token again. Since we’re already retrieving the token in position 1, using Burp’s recursive grep payload, we can now use Burp’s copy other payload payload to copy the value of a previously defined payload. In our example we want payload positions 1 and 3 to have the same value.
Launching the attack
Now that we’ve defined all the payloads, we’re ready to launch the attack. Go ahead and launch the attack. As it’s executing you will see that Burp is automatically parsing the csrf_token from the previous request, and using it as the payload value for the next request. You will also notice in our example that Payload1 and Payload3 both have the same value. This is due to the fact that we’re leveraging Burp’s copy other payload feature to pass the csrf_token in multiple locations.
In this case, you will see a column labeled fy7sdu… This column is used within the xssValidator extender, and when checked, signifies a positive XSS finding.
As we have demonstrated, just because an application has CSRF prevention tokens, viewstate objects, or anything similar, doesn’t mean we still can’t automate the testing. Burp’s recursive grep payload is a great function for anyone that’s testing web apps.
If you’re testing a page that follows a redirect, the define extract grep item panel does not currently provide the option to follow the redirect, despite setting the redirect option to always. If you define the value manually, intruder will follow the redirect when processing the payload, as expected. PortSwigger is aware of the issue and will be rolling out a fix.
Last but not least, if you’re interested in using the example application you can access the source code on github: https://github.com/mccabe615/sinny. If you’re not interested in code, but just want something to test, feel free to use the version which we’ve deployed: http://sleepy-tor-8086.herokuapp.com/