0

Ok, first I was a bit confused when reading

Remember - you must never rely on the sessionID sent to your server in the cookie header ; look only at the sessionID that your GWT app sends explicitly in the payload of messages to your server.

at https://code.google.com/p/google-web-toolkit-incubator/wiki/LoginSecurityFAQ because I didn't understand the nature of XSRF completely and thought: why does it matter how the id gets transmitted?

Then I read http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html and now I understand that XSRF works despite NOT knowing the cookie content (your browser just attaches it to the request, so you exploit your browser's knowledge of the cookie's content - although the browser does not tell 'YOU' or the attacker about the content. The cookie content itself remains uncompromised by that attack). So any proof of knowing the cookie's content validates that the request is not part of XSRF.

I don't like the solution as implemented by GWT (http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html) because it needs a separate call to the server. Please tell me if my ansatz is secure and if I understand the XSRF stuff correctly:

To prevent XSRF, I just copy the session ID contained within the cookie into some non-standard HTTP header field, ie. "X-MY-GWT-SESSION-ID: $sessionId", when doing RPC calls.

That way, I do not need to make any additional calls during app startup because session validation is already done during delivery of the gwt app by destroying the cookie if the session is not valid any more (see How can delete information from cookies?).

So here is the complete security implementation:

  • registration: client submits cleartext credentials via RPC call to the server, which in turn stores the password using a hash during registration in the server's database (How can I hash a password in Java?)
  • login: client sends cleartext pwd via https+RPC, check password on server, if ok: store and return (via https) random UUID. That UUID is the shared secret stored on server and client that is used to identify the authenticated user over possibly many browser sessions to avoid requiring the user to log in each time he visits the site.
  • server sets cookie expiry time to 0 if session is not valid any more so that the client clears the session id and the GWT app detects that it needs to re-authenticate.
  • on server side only accept session UUIDs sent through a special HTTP header field to prevent XSRF
  • handle invalidated sessions on client side (either no session cookie or RPC request produced auth failure)
  • to prevent re-authentication shortly after gwt app loading, the server side devlivery mechanism (ie. index.jsp) deletes the cookie some time before the timeout actually happens - delivering a page and asking for authentication a few seconds later is a bit dumb.

Example sources for the GWT part can be found there: https://stackoverflow.com/a/6319911/1050755. The solution bsaically uses GWT XSRF classes, but embeds the MD5-hashed session ID directly into the web page instead of getting the token via a separate RPC call. The client actually never calls any cookie-related code and the server has only embedded a request.getSession().getId() call into the jsp page.

Any comments, suggestions, critique? Do I miss something important?

Community
  • 1
  • 1
user1050755
  • 11,218
  • 4
  • 45
  • 56

1 Answers1

0

Disclaimer: I'm not a security expert.

Actually, if you obtain your xsrf token by an RPC call, then you're subject to XSRF, as an attacker could possibly forge both requests (this is very unlikely though, because it would have to read the response of the first call, which is most of the time prohibited by the cross-origin nature of the request and/or the way it has to be executed).

So ideally you'll make your xsrf token available to the GWT app through any mean.
You'll generally want your session cookie to be unaccessible through scripts (HttpOnly flag), so you'll need to find another way of passing the value (e.g. write it in the HTML host page that's delivered to the browser –as a JS variable, or a special HTML attribute on a special HTML element–, and read it there with GWT, either through Dictionary, JSNI or the DOM).

Also, you'll probably want to use both the cookie and the request header to validate the request (they must match), or you might be vulnerable to session fixation attacks (would probably need an XSS vulnerability too to make it truly useful)

Thomas Broyer
  • 64,353
  • 7
  • 91
  • 164
  • "if you obtain your xsrf token by an RPC call, then you're subject to XSRF" - why? you get it only in exchange for your correct credentials (login). The "token" (session id) gets stored in a cookie on the client side. How do I put it into the host page without identifying the client first? About that session fixation stuff, I have to read up on that one first. – user1050755 Mar 20 '14 at 17:54
  • I was talking about the `XsrfTokenServiceServlet`, which only reads the auth cookie. – Thomas Broyer Mar 20 '14 at 18:34
  • yeah, sounds problematic, though I haven't looked at it that thoroughly because an additional request and reworking the entire servlet stack seemed a bit odd. On the other hand, one should be able to rely on that the response only gets sent where the corresponding request came from, don't we? I'll use AOP to check access to individual calls and putting the auth info outside the payload seems always the better way to go. – user1050755 Mar 20 '14 at 18:41