Cross Site Request Forgery (CSRF) protection changes in Atlassian REST

Recent changes in Atlassian REST mean that some browser requests may be blocked because the origin of the request is not trusted.

A REST request is subject to origin CSRF checks if the following conditions are met:

  1. the request is a POST request (the http verb is POST)
  2. the request is from a known browser
  3. the request is sending a content-type which is not one of the following
    1. application/x-www-form-urlencoded
    2. multipart/form-data
    3. text/plain
    4. empty or not specified

When an untrusted origin attempts to send a request that meets the conditions specified above it will be blocked and a log entry similar to the following should be present in your application's log file:

 

2015-09-01 17:25:46.530585500 2015-09-01 07:25:46,530 ajp-nio-127.0.0.104-8009-exec-23 WARN anonymous 1045x1465x1 sibktb 127.0.0.1 /rest/auth/latest/session [c.a.p.r.c.security.jersey.XsrfResourceFilter] Additional XSRF checks failed for request: https://example.domain/rest/auth/latest/session , origin: https://another-origin.domain , referrer: null , credentials in request: true , allowed via CORS: false}}


Symptoms

The following symptoms have been experienced and resolved by fixing the configuration:

  • update an add on, including the Universal Plugin Manager,  from the Atlassian marketplace

 

How does the CSRF origin protection work?

The CSRF origin protection works by comparing the origin of incoming requests via the origin and referer headers. In simple terms it checks that the origin of a request is in the same origin as the application itself or if the request origin is trusted by the application.

 

Examples:

Note: Assume that https://trusted-origin.com is trusted by the application. 

Referer Header Value Origin Header Value application URI Allowed?
http://example.com   http://example.com (tick) - the host, port and scheme match
https://example.com/foobar   https://example.com/example (tick) - the host, port and scheme match
http://somethingelse.com   http://example.com (error) - the host does not match.
http://example.com:81/   http://example.com/ (error) - the port does not match.
http://example.com   https://example.com (error) - the scheme does not match, http != https
  http://example.com http://example.com (tick) - the host, port and scheme match
  https://example.com/foobar https://example.com/example (tick) - the host, port and scheme match
  http://somethingelse.com http://example.com (error) - the host does not match.
  http://example.com:81/ http://example.com/ (error) - the port does not match.
  http://example.com https://example.com (error) - the scheme does not match, http != https
https://trusted-origin.com   https://example.com (tick) - allowed because the request comes from a trusted origin. As per the assumption above, https://trusted-origin.com is trusted by the application.
  https://trusted-origin.com https://example.com/ (tick) - allowed because the request comes from a trusted origin. As per the assumption above, https://trusted-origin.com is trusted by the application. 

How to fix it?

As of Bitbucket Server 5.0, you can't configure any Tomcat connectors directly.

server.xml configurations have been replaced by <Bitbucket home directory>/shared/bitbucket.properties

Please read through Migrate server.xml customizations to bitbucket.properties

This usually happens due to Tomcat proxy configuration issues.

If an Atlassian application is run behind a proxy and you are encountering issues with the origin based CSRF protection then please check the following parameters are configured in the server.xml:

  • the configured proxyName matches the hostname that the application is accessed on.
  • the configured proxyPort matches the port that the application is accessed on.
  • the configured scheme matches the scheme that the application is accessed with. 

For example, if JIRA is running behind apache and the url to access JIRA is https://example.domain/ then the correct proxy settings are the following

  • proxyName="example.domain"
  • proxyPort="443"
  • scheme="https"

For the same example, if there is a misconfiguration on the server.xml and the parameters are configured pointing to HTTP, you'd reproduce this UPM issue:

  • proxyName="example.domain"
  • proxyPort="80"
  • scheme="http"

Postman extension workaround

If you wish to use the Postman browser extension then you may need to install the Postman Interceptor browser extension. The following steps sets the Origin header to be in the same origin as the request destination as per the same origin policy:

  • Click the 'Proxy / Interceptor' button at the top of the Postman application':
  • Install the Postman Interceptor as directed:
  • Enable the Intercepter in Postman:
  • On the Headers tab, update the Origin to the server the request is being sent to and Content-Type to application/json:

For example, if you are using Postman to send a request to https://foobar.example/ then set the Origin header to https://foobar.example/.

 

Last modified on May 2, 2017

Was this helpful?

Yes
No
Provide feedback about this article
Powered by Confluence and Scroll Viewport.