15

I have REST api that is using access token which is sent either in header or as url query. I don't use cookies at all.

Am I still vulnerable to CSRF attacks? I know that I would if I would use cookies since other tab can send request and cookies will be sent as well but in my case Headers/UrlParam won't be sent at all.

sed
  • 313
  • 2
  • 4
  • This is the correct way to do it, check how django does it: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/. It's basically a randomly generated and unique CSRF token that's on the page you visit. If the server doesn't receive it then it will not process the request at all. – Aki Jun 30 '14 at 02:13

4 Answers4

14

No you are not vulnerable in that scenario.

The reason is exactly as you explain - a third-party site could generate a request to your site, but the authentication details will not be attached.

paj28
  • 32,736
  • 8
  • 92
  • 130
  • Based on what? Since when authentication details cannot be stored in WebStorage and can be used as long as the session is active? It will be done on the behalf of the browser for you. – Zack Jul 06 '17 at 13:07
  • 1
    @Zack - browsers do not automatically attach WebStorage tokens. That behaviour is specific to cookies – paj28 Jul 06 '17 at 18:46
  • ok but then how do browsers send those WebStorage tokens when the user actually click on a link that needs those tokens for the action to take place (say transfer money)? And at that point, what if that same user clicks on a link that was sent to him via email? Why would the browser do the first but not the second scenario? what if the user copies/paste the link? @paj28 – Zack Aug 31 '18 at 23:19
  • 2
    @Zack - Web storage tokens have to be attached by JavaScript, e.g. when making an Ajax request. They are not automatically attached when you cick a link. More reading: https://portswigger.net/blog/web-storage-the-lesser-evil-for-session-tokens Please, no further questions until you have read and understood that link and other background material. – paj28 Sep 01 '18 at 09:41
  • 1
    Thx for that link. So basically, if I understand correctly, only the JS from a certain specific domain (example.com) can execute those AJAX calls to include the tokens in WebStorage. Furthermore, even if I copy that JS to be modified and executed from another domain (evil.com) it wont work. If a user clicks on a specially crafted link, no Ajax calls will be made, therefore no CSRF. At that point an XSS is needed to proceed any further... Did I miss anything? @paj28 – Zack Sep 02 '18 at 15:15
  • Hi @Zack yes you got it! – paj28 Sep 02 '18 at 15:43
8

CSRF would still be possible if you are using HTTP Basic or HTTP Digest authentication.

The reason for this is that browsers implement those protocols "natively", meaning the browser will automatically insert HTTP Basic/Digest credentials for a domain if the browser knows the credentials.

If you are using some other form of authentication without cookies, then CSRF isn't possible.

Chris Clark
  • 916
  • 6
  • 5
  • Strictly speaking, IP-based authorization (with no credentials at all) would also be at risk of CSRF, but anything else that can properly be called a form of authentication is probably fine. – CBHacking Apr 21 '21 at 10:46
  • Client certificates are also at risk. – Codepunkt Apr 13 '22 at 17:17
3

From your question it is not clear if you are vulnerable or not. Is the token fixed or is it a cryptographically strong random generated token? if it is fixed it is of no value.

Are you using SSL? if not your token can be sniffed and stolen - it is highly recommended that you use SSL.

Note also that it is not recommended to pass the token in the url. URL's are sensitive since they are subject to logging in many places such as browser history, network appliances etc... https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Disclosure_of_Token_in_URL

How do you validate in the server side that the token is valid? do you keep it in the server session? Usually REST API's are designed to be stateless - meaning no session should be kept. If you want to stick to this rule you should create the token in a http-only cookie and upon every API call send the cookie value as part of the request. Your API should then check that the cookie value is same as the token in the request. An attacker could not read the cookie and hence would not be able to send the correct token in the request.

this is a nice blog about it: http://blog.codinghorror.com/preventing-csrf-and-xsrf-attacks/

aviv
  • 1,267
  • 7
  • 8
  • Token is in database session (mongodb). It's TTL 30 minutes. Every time user does something TTL is reset. So inactive 30 minutes = session is deleted. SSL is obviously turned on. If wrong token is used more than 10 times from one IP that ip is blocked for 10 minutes. Is it good security? – sed Jun 30 '14 at 17:59
  • I am not familiar with mongodb sessions. It is more secure to calculate a new token for each request, but never the less it is very common to keep the same token for the entire session and it is still secure. New token for each request may break some functionality like when the user clicks on the back button of the browser and tries to resubmit something. – aviv Jul 01 '14 at 10:34
  • 2
    Regarding blocking the IP - just remember that the IP belongs to a legitimate user that is being attacked via a third party web site. Blocking the user may result in DOS'ing your user's. I believe dropping the request and maybe alerting the user via email is sufficient. – aviv Jul 01 '14 at 10:37
1

That seems a right way to protect against CSRF attack. Although, you may want to generate a fresh token on each request and invalidate the previous used tokens.

p_upadhyay
  • 1,121
  • 3
  • 14
  • 31