5

I have two different web application. Services web app has REST Services defined. Client web app has JSP pages which makes call to REST services using Ajax to get the data and display in the UI. I want to implement OWASP CSRF Gaurd 3 for my REST services.

How can I get CSRF token value in Client application so that it can pass token value as header and rest services gets validated and executed?

Let me tell my architecture bit clearly. Services Project - It is a spring/JPA project with REST web services defined. This project requires to be protected with CSRF. Its web context is /Services. So url might be in localhost like http://localhost:8080/Services/RESTSERVICE

Client Project - It is a JSP/Servlet project with jsp/html web pages. This project makes AJAX calls to Services project's REST Services to fetch the data and show it in UI. URL is like http://localhost:8080/Client/index.jsp

Now my doubt is if I implement CSRF Guard in Services Project, Client project required CSRF token to call protected REST Services. How do I get this token value into Client projects jsp pages?

I tried with adding cookie into the response of rest services, but Client javascript is unable to read it so with cookie i was not able to share token to the client. Is there any other approach? Any help will be appreciated...

MShah
  • 281
  • 2
  • 4
  • 6
  • Depending on how your authentication works, an AJAX based webapplication might not even need CSRF tokens. Those tokens are only needed because the browser implicitly adds cookies to each request. If you manually add an authentication header to each request, this implicit authentication doesn't happen, and CSRF is irrelevant. – CodesInChaos Dec 17 '13 at 08:41

4 Answers4

3

Just implement a /token endpoint that provides a CSRF token given a session cookie. Remember, as long as client side JS on a different domain cannot fetch and use this to construct requests (the most client side JS can do is dislpay it in an isolated iframe), CSRF is not possible. Allow the client app to fetch the token via CORS if the domains differ.

Manishearth
  • 8,317
  • 5
  • 37
  • 56
  • Couldn't a CSRF attack be used to get the CSRF token in your example? – Abe Miessler Oct 08 '13 at 14:52
  • @AbeMiessler How? The token could be retrieved without the user's consent, but it wouldn't be accessible because of CORS. Normally, CSRF tokens are stored in the HTML of a page. This is the same thing, just more machine-friendly. – Manishearth Oct 08 '13 at 14:53
  • 2
    Well a malicious user could make a POST request to the /token endpoint if the user has an active session, correct? You are right that this is not a vulnerability though, because the attacker would have no way to read the token that was returned. Does that make sense? – Abe Miessler Oct 08 '13 at 15:04
  • @AbeMiessler Yep. The /token endpoint is a GET one anyway. – Manishearth Oct 08 '13 at 15:36
  • I am sorry but I am very new to web app security so may be asking these many questions... You mean to say, I get token value in my client app with an AJAX call (method=GET) and use that token value in further REST Services invocation? I want to implement new token per page concept, so before making any request i need to fire another ajax to get the token value? Is this an efficient and a safe way to implement? wont /token service be vulnerable? – MShah Oct 09 '13 at 06:57
  • 1
    @user31699 You can do that, or have the server for the client webapp request the token internally by providing the cookie. It won't be vulnerable; as the /token service cannot be both fetched and read with your cookie without your knowledge due to CORS. – Manishearth Oct 09 '13 at 08:57
  • @Manishearth thank you for quick reply. I didnt understood "have the server for the client webapp request the token internally by providing the cookie." part. You mean to say let Service API create cookie with token value and client reading that cookie to get token? Since web context is different will client be able to access cookie set by services? – MShah Oct 09 '13 at 09:12
  • @user31699 I don't think I've totally understood your framework, maybe you could edit your question to be clearer? Basically, implement some sort of internal cookie sharing. Or, when the client logs in, auto log them in to the service api as well (this is possible by embedding an image with a hash that sends over the session cookie) – Manishearth Oct 09 '13 at 13:13
  • @Manishearth Thanks for your reply... I have edited question to explain design more clearly. Do let me know if you need any other information... – MShah Oct 10 '13 at 04:49
0

Adding the CSRF Token in the Client

pom.xml:

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>js-cookie</artifactId>
    <version>2.1.0</version>
</dependency>

Import it in HTML:

<script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script>

then we can use Cookies convenience methods in xhr:

$.ajaxSetup({
beforeSend : function(xhr, settings) {    
      xhr.setRequestHeader("X-XSRF-TOKEN",
          Cookies.get('XSRF-TOKEN'));
    }
  }
}
});

source: https://spring.io/guides/tutorials/spring-boot-oauth2/

0

I recently had to do this and ended up putting the CSRF token in a global javascript variable. Then when I would make my calls I would include this token as a parameter. Since an attacker would not be able to read any state from your browser it should be safe there.

Example:

$.ajax({
  type: "POST",
  url: "some.php",
  data: { name: "John", location: "Boston", _csrf: _GLOBALS._csrf }
});
Abe Miessler
  • 8,195
  • 11
  • 49
  • 73
  • Thank you Abe Miessler... My issue is to get token value in client application from my webservice app.. since both are having different web context – MShah Oct 09 '13 at 07:36
0

I've faced the same problem and have decided to use “one-time token requests”. Something like this:

  1. Enter login-password, authenticate, authorize, load main project page
  2. Call method /csrf-token before any other requests, e.g. during initial bootstrap stage
    • The server generate token and then somewhere in the server session data makes note, that csrf token has been already requested, so all future calls of /csrf-token will fail.
  3. Client remember that token and use it for all future requests; it could rememeber in some javascript namespace for example, so it will be accessible only from that page/tab.

Major drawback from this method: you have to sign if you reload the page for example.