Using Recursive Grep to Test Per-Request CSRF-Token Protected Pages

Cross-Site Request Forgery (CSRF or XSRF) is an attack which is used to execute a transaction on behalf of a victim user against a vulnerable web application. To be vulnerable to CSRF, an attacker must be able to determine and submit all of the values necessary to execute the target transaction in advance. If this is possible, an attacker will use social engineering, craft a malicious URL, or post a malicious form on a third party site that will accept unfiltered HTML input. When the targeted user executes the attacker’s content, the transaction is executed on the target web application.

As a defense against CSRF attacks, web applications employ Anti-CSRF tokens in sensitive forms. The token is a random value that is generated when the target form is loaded, and verified when the form is submitted. Since an attacker cannot know the value in advance and must have the value to successfully submit the form, this technique, when implemented properly, will thwart CSRF attacks.

Some anti-CSRF implementations change the token value with each submission of the form. A side-effect of this behavior is that automated testing becomes nearly impossible without taking the token value into consideration. In this post I will demonstrate how Burp Intruder’s Recursive Grep payload can be used to solve this problem. Once the Recursive Grep payload is understood it can be used to solve nearly any dependency on a previous server response.

I recently encountered a WebSphere portal that exhibited the behavior described above. When any form was submitted to the server, multiple values would change in the ensuing response which prevented automated tools like Burp Repeater and Burp Intruder from working properly on the site. The server would simply respond by reloading the blank form with newly updated token values.

To demonstrate this problem, I have created a single ASP.NET web form with two fields.  For simplicity, the current token value is displayed on the form. If this form is submitted without the correct token value, the string “Invalid Token Value” is displayed. However, when the correct token value is submitted, the submitted values are reflected on the page along with an indication of success.

Basic Form with Token Value Displayed

Token Validation Error

Successful Form Submission

If no compensation is made for the token value, when Burp Intruder is run trying to tamper the form fields we see the following results. This is because the token is changing with each request and being validated when the form is submitted. Since the values don’t match, none of the requests is successful.

Unsuccessful Intruder Attack Due to Invalid Token Value

To accommodate for the token value present in the response, we can use the Burp Intruder Recursive Grep payload. This payload will formulate and insert a parameter into your request based on the previous server response. The derived parameter can originate from any arbitrary location in the response and you can include as many recursive grep payloads as you need. While testing the WebSphere portal mentioned above, there were three distinct values that changed with each response from the server.

In order to use the Recursive Grep payload, we must make some adjustments to our standard Intruder Attack setup. In the instance above, I simply selected the txtFName parameter, specified a sniper attack using the simple list payload and selected the default Burp username list.

Using Recursive Grep requires us to select either the Pitchfork or Cluster Bomb attack type. Since we are tampering only one parameter, the Pitchfork attack makes sense. This attack will stop when the shortest list is exhausted. With multiple significant parameters, this attack treats the values in each list as a tuple.  In contrast, the Cluster Bomb attack tests each of the possible permutations generated by each list. Our setup can be seen below. The target field (txtFName) and token (checkToken) are identified as payload positions and the Attack Type is Pitchfork.

Intruder Attack Setup with Parameter and Token Payload Positions

Since the target field appears first in the request we select simple list as the payload type and specify the Burp username list as described earlier.

Simple List Payload Configuration

The second field is our checkToken value. In this case we desire a Recursive Grep payload but first we must set up the Grep location. To do so we have to navigate to the options tab and scroll down to the “Grep Extract” location in the form.

Burp Intruder Grep Extract

Once there, click the add button to add an extract location. On the ensuing form, scroll down in the HTTP response body and highlight the CSRF token value.  This identifies the location in the previous response that Burp will use for the Burp Recursive Grep payload.

Grep Extract Location Selection

One final adjustment on the Options tab is required to ensure that the recursive grep works properly. Since there is a direct relationship between the previous response and the current request, the number of threads must be set to 1.

Burp Intruder Attack Request Engine Options

With intercept enabled on the proxy, submit the form to capture the current token value. This is required to seed the Recursive Grep payload and will be used to begin the intruder attack.

Intercepted Post with Current Token Value

Now, return to the Burp Intruder attack and select the Payloads tab.  Select the appropriate payload index and select the Recursive Grep payload type. You should see the Grep Extract entry that you created above. Select this value and paste the current token value into the “Initial payload for first request” field.

Recursive Grep Payload Options

With all of our options set, we can finally execute our Intruder Attack. Since the “checkToken” parameter was selected as a tampered value, we can see the submitted value in our attack. In addition, because of the requirement for a Grep Extract to facilitate the attack, we can see the value returned in the previous form submission. Inspecting the output, we can see that the response indicates success, the word invalid no longer appears in the output, and that the token values cascade from response to request as expected.

Successful Intruder Attack Results

Hopefully this post will be valuable if you encounter behavior like this. While the Recursive Grep payload is effective against some Anti-CSRF behavior, it is not a one size fits all solution.

Within the same WebSphere portal that forced me to investigate the Recursive Grep payload there were multi-step form submissions that this feature just couldn’t handle. These forms involved multiple posts to the same location. Each post generated new token values which had to be submitted in sequence. One set of tokens would activate the form and the next would submit. Without the first, the page would simply reload without the active form.

I am currently investigating a solution to this problem and have started a Burp Extension to address it.  Look for this capability in a future post…