Last updatedAug 19, 2019

XSRF protection in Fisheye/Crucible plugins

This page refers to Fisheye/Crucible version 3.2.0 and later. Earlier versions do not provide the XSRF protection described.

What is XSRF?

An XSRF attack is carried out by tricking a user into clicking a link on another web site which submits a request to Fisheye/Crucible. If the user is logged in to Fisheye/Crucible their login cookie will allow the request created by the link to modify data in Fisheye/Crucible, as though that user had deliberately performed the action.

Fisheye/Crucible is protected against XSRF attacks, and if you write a plugin which modifies data in Fisheye/Crucible via a Servlet Plugin Module you should also protect your plugin.

How can you protect against XSRF?

Any request which alters data can include an XSRF token. This token is only available to pages rendered by Fisheye/Crucible, so an attacker's web page cannot create a request which includes the token.

Because XSRF attacks are triggered from the user's web browser the only vulnerable requests are GET requests or POST requests which have a request content type of application/x-www-form-urlencoded or multipart/form-data. There is no need to protect DELETE or PUT requests, or POST requests with a Content-Type header of application/json.

Protecting a Servlet Plugin Module

Marking the servlet methods as protected

You need to add the annotation @RequiresXsrfCheck from the package com.atlassian.fisheye.plugin.web to the servlet service methods which you wish to protect. i.e.

1
2
3
4
@RequiresXsrfCheck
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        changeSomething(...);
    }

You should not create GET requests which need protection - the XSRF token would need to appear in the URL, which would be a security risk. That is, your GET requests should not modify data.

Adding the token to a Form Tag

Form tags will automatically have an XSRF token added to the data submitted in their POST request, as long as the page is decorated by a standard Fisheye/Crucible decorator.

If you are not using a decorator you should add a hidden input field to your form:

1
<input type="hidden" name="atl_token" value="$xsrfToken"/>

You will need to provide the $xsrfToken value to whichever rendering tool you use. It is available from the SAL com.atlassian.sal.api.xsrf.XsrfTokenAccessor component by calling the getXsrfToken method:

1
2
3
4
5
6
7
8
9
10
11
/**
     * Get the persistent token for the given request, that is, the token stored in the users session or in a cookie,
     * not the token submitted as part of a form.
     *
     * @param request The request to get the token from
     * @param response The response to add the cookie to if necessary, can be null, if create is false.
     * @param create Whether a new token should be created if there is none in the request.  The new token should be
     *               persistent across subsequent requests, ie, added to the users session or a cookie.
     * @return The token for the request, or null if no token was found and create was false
     */
    String getXsrfToken(HttpServletRequest request, HttpServletResponse response, boolean create);

Remember that you only need to do this if you are not using a standard decorator.

Adding the token to an Anchor Tag

If you give your anchor tag the class anchor-post, Javascript loaded by the standard Fisheye/Crucible decorators will convert the tag into a form which will post to a URL given by a data-href attribute on the tag, e.g:

1
<a class="anchor-post" href="#" data-href="./fsscm?name=$config.name&delete=true">Delete</a>

Ajax Requests

Ajax requests do not require any action as long as they use the AJS.$.ajax function to call the server. (The AJS.ajax function is also protected, but that is deprecated - AJS.$.ajax should be used)