In Nowadays web technologies a common defensive mechanism against Cross-Site Request Forgery (CSRF) attacks is to use a synchronizer token. This token might be unique for each request and thus it blocks us from using the recorded JMeter test session off the shelf.
This blog will describe how this CSRF feature can be handled in JMeter.
How to implement this feature
The solution is to identify and extract the CSRF token from the response data or header depending how is it has been set.
The site I was doing the Load test using JMeter is using a cookie to set the CSRF Token and adds a X-CSRFToken header to the following HTTP requests.
The HTTP Response header contains something like:
Set-Cookie: csrftoken=sTrKh7qgnuKtuNTkbwlyCv45W2sqOaiY; expires=Sun, 21-Jan-2017 11:34:43 GMT; Max-Age=31449600; Path=/
To extract the CSRF token value from the HTTP Response header, add a Regular Expression Extractor Post Processor globally.
This way if the token value is reset to a new value somehow, it will be dynamically updated in the following response.
Now configure it as follows:
Apply to: Main sample only
Field to check: Response Headers
Reference Name: csrfToken
Regular Expression: Set-Cookie: csrftoken=(.+?);
Get the Response Cookie via the Regular Expression Extractor
It is always better to have a user variable attached to the extracted value to be kept during the complete load test run.
select user defined variables and add a new variable with the same name as the reference name declared above in the regular expression Extractor.
The next step is to analyse each HTTP Request recorded in the scenario to replace the hard coded value for the X_CSRFToken header with the variable set by the Post Processor as shown below:
To avoid having to check every request HTTP Header Manager as displayed above which can take some time and might introduce errors, a pre-processor can be used that checks the headers
and replace automatically the X_CSRFToekn hard coded value with the variable set by the post processor task. This kind of pre-processor can be time consuming and should be as simplest as possible. Thus I decided to not check if the X_CSRFToken exist in the request header and just call the remove header attribute and add the X_CSRFToken one to all requests. This worked fine for the site I was working on.
The pre-processor code used was the following:
import org.apache.jmeter.protocol.http.control.Header; sampler.getHeaderManager().removeHeaderNamed("X-CSRFToken"); newValue=vars.get("csrfToken"); sampler.getHeaderManager().add(new Header("X-CSRFToken",newValue));