20

According to the OWASP testing guide a CSRF token should not be contained within a GET request as the token itself might be logged in various places such as logs or because of the risk of shoulder surfing.

I was wondering if you only allow the CSRF token to be used once, (so after one request it's invalidated) would this still be insecure? Considering that by the time someone logs the token, it will already be invalidated and unusable should the attacker want to perform CSRF.

3
  • 4
    If you're generating the tokens in a secure random fashion, then an attacker cannot infer the next token from the previous ones. So there shouldn't be any realistic risk. It feels weird telling you that.
    – Adi
    Commented May 30, 2013 at 11:43
  • I just wanted some kind of confirmation Commented May 30, 2013 at 12:19
  • 1
    @LucasKauffman I can't find a reference of "CSRF token should not be contained withing a GET request" can you please share if you have any OWASP reference for this ?
    – Amit
    Commented Mar 14, 2017 at 14:49

4 Answers 4

15

If you're generating the tokens in a secure random fashion, then an attacker cannot infer the next token from the previous ones. So there shouldn't be any realistic risk.

Another important point here is to use SSL. Any proxies/reverse proxies between the user and the server cannot even see the GET parameters to log them. The only places where the token is logged is on the two ends of the SSL connection.

Logging on the user's end (History, for example) happens after the link is clicked. Logging on the server's end carries no risk (if you don't trust the place where the SSL traffic is decrypted, then there are bigger problems).

1
  • 1
    Of course, TLS/SSL is important, however if a MITM/proxy can grab a CSRF token then they can grab anything anyway. Avoiding logging shouldn't be a reason alone, as CSRF tokens should be session based and should have expired by the time logs are archived. Commented Aug 31, 2016 at 8:13
10

GET requests should be idempotent, which means you can't invalidate the token once used because any repeat requests won't give the same response.

GET requests should also never make state changes to the system, therefore should not be required to have CSRF protection. Even logout should not be a GET request for the method that actually executes the logout (although you could have a GET link that navigates to another page before a POST request carries out the action).

To fix the idempotent problem, with a repeated GET request and with the same CSRF token supplied, you could display the cached response from the first request, without making any state change. However, you're still violating the standard if you make state changes at all, see rfc7231:

Request methods are considered "safe" if their defined semantics are
essentially read-only

Of the request methods defined by this specification, the GET, HEAD,
OPTIONS, and TRACE methods are defined to be safe.

As a side note, I would also argue that resource intensive processes should also be POSTs (with CSRF protection) rather than GETs, otherwise an attacker could DoS a system using a CSRF vector.

Therefore, if you need CSRF for a method, then don't implement this as a GET.

5

Considering that by the time someone logs the token, it will already be invalidated and unusable should the attacker want to perform CSRF.

There is a corner case if the user gets the address but fails to actually use the token (due to transient network failures etc). It's unlikely this is significant enough to worry about for a CSRF token, but can be a problem for other more sensitive tokens.

Single-use CSRF tokens tend to pose usability problems, though, such as breaking navigation and multi-tab browsing... not to mention they're super-ugly. :-) Given that GET requests should be idempotent and thus not in need of CSRF protection, token-in-URL is usually a design smell. But I doubt there's much you can exploit here.

1
  • 4
    GET requests don't need a CSRF token because they should not change the server's state. Idempotence is not a sufficient condition. Consider PUT requests which are idempotent but still potentially vulnerable to CSRF. Commented Aug 6, 2014 at 15:07
3

It's probably secure enough, but it doesn't entirely eliminate the shoulder surfing and logging problem. An attacker could temporarily DoS the network so that he can use a shoulder-surfed token before the user gets a chance to, and a request may show up in logs but not get invalidated when the website (or database, or network) is down during an attempted pageload. Beyond that, I can't think of any vulnerabilities that don't also occur when you put the token in POST-data.

I'm not sure it's practical to invalidate all tokens after usage though. I often open multiple pages in a new background tab, for example on older SMF forums I middle-click the delete button of private messages so that it doesn't need to reload the page before I can delete another. You can generate a unique token for all links appearing in a page, but then you get to a level of complexity where you might as well start using HMACs instead of a simple token.

You must log in to answer this question.

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