Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


Warning


Excerpt

This is mostly a tour of how Jira does CSRF (cross-site request forgery), written for my own benefit while investigating the problems eventually logged as

Jira
serverAtlassian JIRA
serverId144880e9-a353-312f-9412-ed028e8166fa
keyJRASERVER-73880
.



Have you ever tried to attach a file or image to a Jira issue, and got the error Jira could not attach the file as there was a missing token. Please try attaching the file again. ? This commonly happens when:

...

While you are actively using Jira, Jira maintains a 'session' for you. A session is just a handful of key:value pairs in memory, grouped by 'session id', which is associated with your browser requests with the JSESSIONID cookie your browser sends.

If you are a Jira administator you can see your session's attributes by dropping sessionattributes.jsp into your atlassian-jira/secure/  directory, and hitting the /secure/sessionattribute.jsp  URL:

...

There in the session, you see where Jira is storing your CSRF token: in the atlassian.xsrf.token attribute (Jira uses 'XSRF' as a synonym for CSRF).

There are a few more wrinkles, but that is the essence of Jira's CSRF protection: all state-modifying HTTP requests must have an atl_token field, whose value must match the atlassian.xsrf.token session parameter. 

The atlassian.xsrf.token cookie

...

It would therefore be easy to think thatthis atlassian.xsrf.token cookie  cookie is the thing in the request that needs validating. Isn't the server just comparing the atlassian.xsrf.token request cookie with the atlassian.xsrf.token session attribute is knows is correct, and if they match, passing the CSRF check?

No! Remember that the atlassian.xsrf.token cookie is sent by the browser, and will always be present in malicious and non-malicious requests. Its value will always be correct, because cookies aren't under the attacker's control. The presence of a correct atlassian.xsrf.token  cookie tells Jira nothing about whether the request has a malicious origin. It is the atl_token  form parameter which needs validating, not the atlassian.xsrf.token  request cookie.

In fact, when the server receives a request, it could compare the atl_token  form parameter with either the atlassian.xsrf.token request cookie, or the atlassian.xsrf.token session attribute. In fact Jira does both (in XsrfTokenStrategy.java).The reason Jira sets

Why does Jira even set the atlassian.xsrf.token  cookie is because sessions expire after 5 hours, but cookies don't expire.  Typically your browser will store 3 Jira cookies:

Image Removed

When you request a Jira page first thing in the morning, your server session has expired, so JSESSIONID  is invalid and a new session will be created. The seraph.rememberme.cookie  cookie will automatically log you in to Jira. Your empty session won't have a token cookie? No idea. The general question of "why send the CSRF token as a cookie" is asked and answered on Stackoverflow. I'm not sure if any of those advantages actually apply to Jira. Certainly Jira does not populate the atl_token form field from the cookie, as it might do. and does not implement the "double submit cookie" pattern where the cookie value is compared with the form value, removing the need for server-side state. Perhaps it is handy to have AJAX Javascript-initiated requests automatically CSRF-protected.

When sessions expire..

One nice thing Jira could  have done with the incoming atlassian.xsrf.token  attribute in it, but because there is a trusted cookie it is re-initialize the atlassian.xsrf.token  session parameter from the cookie if the session has expired. Then if your session expired overnight, Jira uses the cookie value for the session attribute (in XsrfTokenAdditionRequestFilter.java ). That means that if your first JIRA request of the day was an operation requiring CSRF validation, then the validation should pass, as the atl_token in the page is validated against the cookie / session attribute. Neat!

The failing edge-cases

Submitted xsrf 40206:

Image Removed

Next request, submitted 08713

Image Removed

Image Removed

Image Removedand you had a Jira form half-filled in, the submit (next morning) would work, as the session atlassian.xsrf.token would be seeded from the atlassian.xsrf.token  cookie. Currently that doesn't happen: if the session has expired, XsrfTokenAdditionRequestFilter.java (very early in the filter chain) just generates a new atlassian.xsrf.token session attribute, which is then compared to the atl_token field, fails to match, and you get a 'missing token' error to brighten your Monday morning:

Image Added

..to Be Continued

Apologies to anyone reading, but there is no conclusion yet. The fix suggested above (copy the token from cookie to session) could be implemented as a custom servlet filter, even implemented as a plugin.  If I ever do so I will update this post.