Changes to CSRF protection in the MQ REST API in 9.0.5

The MQ REST API has been continually enhanced through the CD releases with support for extra object types. In 9.0.5 you can see that we continued this trend by adding the first set of APIS for MFT. I want to use this post to highlight an important change in behavior in the REST API regarding CSRF (Cross Site Request Forgery) protection.

CSRF is a type of attack which occurs when a malicious website causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated. A good explanation of CSRF is available here.

Since MQ 9.0.2 the MQ REST API has provided protection against CSRF attacks using CSRF synchronizer tokens. These tokens were generated by the REST API and returned to callers of the REST API in a csrfToken cookie. Any user of the REST API that wanted to perform a state changing request, i.e. use the HTTP POST, PATCH or DELETE verbs needed to take the contents of the csrfToken cookie, put it into an HTTP header called ibm-mq-rest-csrf-token and send it with their request. If the header wasn’t set, or its value wasn’t correct, the request would fail.

While this approach provided protection against CSRF attacks it was cumbersome, and overly restrictive in certain cases where it actually prevented any use of the MQ REST API. In MQ 9.0.5 we have changed how CSRF protection works, and made it simpler. From 9.0.5 onwards there is no longer a csrfToken cookie. CSRF protection is still provided by setting the ibm-mq-rest-csrf-token header, but its value can be anything including blank. An example of this is in the following curl request:

Now, you may look at this request, and wonder how it can be more secure. Surely anyone can set an HTTP header? Well, yes and no. If you are calling a REST API from curl, or Java than yes, anyone can set an HTTP header. But that is not the case from JavaScript running in a web browser, which is where CSRF attacks occur. In a browser environment there are very strict rules about what HTTP operations JavaScript can perform, including the HTTP headers that can be set. More information on these rules can be found here.

These rules will by default prevent any JavaScript code running in a web browser from calling the MQ REST API, let alone set the ibm-mq-rest-csrf-token header. To allow JavaScript running in a web browser to call the MQ REST API and set the ibm-mq-rest-csrf-token header, the origin (host/port information) of the JavaScript must be white-listed in the configuration of the mqweb server. More information on how to do this is here.

Unfortunately this change means that any existing code, regardless of whether it is JavaScript or not, that makes use of the csrfToken cookie will need to be changed to no longer use the cookie, and instead set the ibm-mq-rest-csrf-token header to an arbitrary value. While this is a breaking change, it does mean that going forwards users of the REST API will be able to write simpler code, and still benefit from protection against CSRF attacks.