15

To protect against CSRF, couldn't my page javascript just dynamically insert the session id from the cookie into the body of each HTTP request right before it's sent?

The server would then just validate that (value received from cookie) == (value from request body)...

12
  • 6
    Known fact: Your website has be able to work without JavaScript.
    – HamZa
    May 14, 2013 at 8:37
  • 9
    So what? I'll just make Javascript mandatory
    – ManRow
    May 14, 2013 at 8:40
  • 1
    Well whatever, this will not protect you from CSRF IMO. CSRF is about an attacker sending a link to a user tricking him to do something, so I don't see how this will stop it ?
    – HamZa
    May 14, 2013 at 8:41
  • 3
    @HamZaDzCyberDeV If a user running IE 3 hits any site i've created they'll promptly be told to go back to sleep.
    – NULLZ
    May 14, 2013 at 9:07
  • 4
    @D3C4FF: Doesn't matter. If your server accepts POST/GET requests without validating the request, it is vulnerable to CSRF. Servers don't care about javascript. May 14, 2013 at 9:38

5 Answers 5

17

No because you should never allow scripts to be able to access your cookies. Refer to HTTPOnly on the OWASP website.

To prevent people from being able to steal session id's, should XSS be present, you should always set this cookie flag. Your mechanism would not work anymore as it would not be able to access the cookie.

4
  • 1
    And what if the site doesn't have any inherent XSS vulnerabilities?
    – ManRow
    May 14, 2013 at 8:53
  • 5
    @ManRow, that is a dangerous assumption to make. Making security tokens available to user-land code should generally be avoided, unless one is completely comfortable with the consequences of doing so. It would only take one XSS vulnerability to allow an attacker to extract the token and have his way with it. May 14, 2013 at 8:57
  • 2
    Security doesn't work with "What if this is taken out of the equation". You either go for a good approach or you just don't. May 14, 2013 at 8:58
  • "Yeah, but what if the thief doesn't have a bolt-cutter"
    – xdhmoore
    Apr 24, 2018 at 17:43
17

Quoted from OWASP's CSRF Prevention page:

Double Submit Cookies

Double submitting cookies is defined as sending the session ID cookie in two different ways for every form request. First as a traditional header value, and again as a hidden form value. When a user visits a site, the site should generate a (cryptographically strong) pseudorandom value and set it as a cookie on the user's machine. This is typically referred to as the session ID. The site should require every form submission to include this pseudorandom value as a hidden form value and also as a cookie value. When a POST request is sent to the site, the request should only be considered valid if the form value and the cookie value are the same. When an attacker submits a form on behalf of a user, he can only modify the values of the form. An attacker cannot read any data sent from the server or modify cookie values, per the same-origin policy. This means that while an attacker can send any value he wants with the form, the attacker will be unable to modify or read the value stored in the cookie. Since the cookie value and the form value must be the same, the attacker will be unable to successfully submit a form unless he is able to guess the session ID value.

While this approach is effective in mitigating the risk of cross-site request forgery, including authenticated session identifiers in HTTP parameters may increase the overall risk of session hijacking. Architects and developers must ensure that no network appliances or custom application code or modules explicitly log or otherwise disclose HTTP POST parameters. An attacker that is able to obtain access to repositories or channels that leak HTTP POST parameters will be able to replay the tokens and perform session hijacking attacks. Note, however, that transparently logging all HTTP POST parameters is a rare occurrence across network systems and web applications as doing so will expose significant sensitive data aside from session identifiers including passwords, credit card numbers, and or social security numbers. Inclusion of the session identifier within HTML can also be leveraged by cross-site scripting attacks to bypass HTTPOnly protections. Most modern browsers prevent client-side script from accessing HTTPOnly cookies. However, this protection is lost if HTTPOnly session identifiers are placed within HTML as client-side script can easily traverse and extract the identifier from the DOM. Developers are still encouraged to implement the synchronizer token pattern as described in this article.

No real reason not to just use the built-in CSRF prevention mechanism, almost all serious frameworks have this now.

2
  • 1
    Two disadvantages with this approach: (1) An XSS vulnerability will now allow the attacker to also get your session id --- since it's now just another field in the DOM. (2) No cache-ability; setting this hidden field value requires the server to dynamically generate the HTML since the HttpOnly sessionid cookie values are inaccessible from javascript. While #1 still applies to my approach, at least my approach resolves #2.
    – ManRow
    May 14, 2013 at 22:07
  • Since this is the top-voted question for double submit cookies, interested users should look at this Blackhat video regarding hacks that relate to Facebook and Twitter integration youtube.com/watch?v=jauXjSY-9LA Jul 28, 2013 at 4:01
2

You could, but it seems a bit unwieldy to me. Any CSRF-prevention mechanism works like this:

  • Make the server only accept requests that satisfy some conditions
  • Ensure that the conditions are something that can't be forged
  • Write your HTML so that the requests it generates follow the conditions set by the server.

The tried-and-tested method is to use <input type=hidden> in the HTML fields that contains some anti-CSRF token. Your method works as well1, but using JS to intercept and inject POST requests sounds icky and unnecessary when the whole client-side logic can be contained in the HTML.

1 As TildalWave noted, puting sensitive data in non-httponly cookies and making the accessible to client side JS could be a problem if you have XSS vulnerabilities. Stick with the tried and tested method then.

11
  • Can that token just be my session id?
    – ManRow
    May 14, 2013 at 10:26
  • @ManRow: I don't see anything wrong with that. May 14, 2013 at 10:29
  • 1
    @ManRow - Well, it could potentially be a problem, if this value is read by a XSS, collecting end user session IDs and later used to forge requests (CSRF), or hijack user sessions. The whole point in using httponly in cookie headers is to signal the client (browser) not to enable client side scripts access to these cookies (usually session cookies), so they're not exposed to XSS. By adding this session ID value to a form field, you're needlessly enabling access to it. It's just safer to assume you can't trust the client, and since there's no need to do it this way, I'd suggest not to.
    – TildalWave
    May 14, 2013 at 10:47
  • 1
    @SébastienRenauld: If someone is sniffing the request, they can just take the session cookie and be done with it. Why attempt CSRF when you have something better? May 14, 2013 at 15:15
  • 2
    @SébastienRenauld: How would you "load up a form"? Same origin policy makes sure that you don't GET x-site forms. May 14, 2013 at 18:06
2

As mentioned by a number people - double submit is an ok CSRF protection, provided that you use a separate nonce. Using session id is very wrong in this context, starting with the fact that sessionid has to be HTTPOnly for XSS protection.

An argument of "what if there is XSS on this page/website" is not valid - when you have XSS, CSRF is the least of your worries. The browser becomes fully remotely controllable via an injected script and CSRF is not required to force the browser to do actions on behalf of the user.

2
  • So? You could then just keep your sessionid cookie "HttpOnly" and instead just use a separate non-HttpOnly anti-CSRF token cookie for my javascript mechanism.
    – ManRow
    May 16, 2013 at 6:11
  • @ManRow: A separate cookie - yes, SessionID - no May 24, 2013 at 7:00
-1

*Edit: what I propose below is apparently known as the double-submit cookie scheme. And, contrary to the original question, it is a separate nonce altogether as well (or even a simple hash of the session id)...


Looks like the simple solution (i.e., CSRF protection but with all-cacheable web resources) is to just add a separate cookie containing the anti-CSRF token but accessible to page javascript. And add this to all requests from the page (e.g., just before they're sent).

In other words, when the client logs in, I'll actually set two cookies (one HttpOnly sessionid and one nonp-HttpOnly anti-CSRF token, accessed by page scripts). So, the server will store (along with a client sessionid) their anti-CSRF token value and validate that it's the same value as the one originally set via the second cookie. If validation fails, you have a potential CSRF.

This approach is also mentioned in some other places on the web...

6
  • And what would stop the 2nd cookie from being submitted by a CSRF attack, same as the session id cookie...?
    – AviD
    May 21, 2013 at 6:51
  • Because the CSRF cookie is submitted twice: (#1) once as a regular cookie (just a regular cookie w/o CSRF protection), but ALSO (#2) as a property dynamically added (at the same time) via the page's javascript into the body of every request from that page. The server will validate that the anti-CSRF token value passed via mechanism #1 (standard cookie mechanism) is the same as the one sent (at the same time) via mechanism #2 (the value of which only your page's javascript can access); if it's not the same or missing, the server will suspect CSRF.
    – ManRow
    May 21, 2013 at 7:20
  • Of course, the anti-CSRF cookie value will just be overwritten/reset every time the user gets a new sessionid...
    – ManRow
    May 21, 2013 at 7:24
  • ah, I see - that was not clear from your answer. However, while this scheme could work fine (I dont see any issues with it offhand), it needlessly over-complicates things. Why try to build this (and you will probably get some parts wrong, like the cryptographic bits), when you have a perfectly fine mechanism built in to almost any framework or platform you're using?
    – AviD
    May 21, 2013 at 7:43
  • Cache-ability: my entire site is now cache-able, since the server doesn't need to cook this token into the returned HTML each time. I can now just use all static HTML & JS files...
    – ManRow
    May 22, 2013 at 4:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .