73

I'm writing a Django RESTful API to back an iOS application, and I keep running into Django's CSRF protections whenever I write methods to deal with POST requests.

My understanding is that cookies managed by iOS are not shared by applications, meaning that my session cookies are safe, and no other application can ride on them. Is this true? If so, can I just mark all my API functions as CSRF-exempt?

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
alexgolec
  • 26,898
  • 33
  • 107
  • 159

5 Answers5

79

That's not the purpose of CSRF protection. CSRF protection is to prevent direct posting of data to your site. In other words, the client must actually post through an approved path, i.e. view the form page, fill it out, submit the data.

An API pretty much precludes CSRF, because its entire purpose is generally to allow 3rd-party entities to access and manipulate data on your site (the "cross-site" in CSRF). So, yes, I think as a rule any API view should be CSRF exempt. However, you should still follow best practices and protect every API-endpoint that actually makes a change with some form of authentication, such as OAuth.

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • 7
    What about user registration? That's my big one, since the way I'm writing it now, with no CSRF and (obviously) no login, there is nothing stopping someone from flooding my service with bogus registrations. – alexgolec May 24 '12 at 16:41
  • 18
    Simple. You don't allow it. No API that I know of allows you to actually create an account *with the API*. You create the account through their website, and then use an API Key to authenticate your requests. – Chris Pratt May 24 '12 at 16:52
  • 6
    Then how do Twitter et al. support signup via a native iOS view? My intuition tells me it's an API call, but security reasons make me thing that that's not the case. – alexgolec May 24 '12 at 17:07
  • Perhaps, but it's no public API, and it's going to be protected via some form of authentication that depends on a "superuser" class user to authenticate. But, it just as easily might not be, they could also be issuing commands to a remote shell. – Chris Pratt May 24 '12 at 17:12
  • 6
    This is not true. A CSRF attack relies on a currently authenticated session token stored as a cookie, so that a browser will reuse this session token when posting data to the site. Just because your API is exposed to 3rd parties doesn't mean you don't want to authenticate them, so you should at least verify the CSRF token when authenticating based on the session token. – nfvs Feb 13 '15 at 15:37
  • I think you're thinking of session hijacking. That's a totally different thing. CSRF is exactly for the purpose I describe and is relevant whether the user is authenticated or not. In fact, CSRF, doesn't even involve sessions, and can work independently of whether there's a session or not. – Chris Pratt Feb 13 '15 at 15:42
  • @Alex Do you also use CSRF tokens to protect against spamming of creation of accounts? – user805981 Sep 19 '16 at 15:56
  • 1
    To prevent users from spamming registrations, you may want to use a captcha, or have the user verify their phone number. – Nick Retallack Oct 10 '16 at 18:28
  • Such a shortsighted answer, @Chris you were too quick in dismissing nvfs. Say the user has logged already into PayPal and the attacker can trick him while skype chatting to click http://paypal.com?action=send_money&receiver=attacker_bank_no provided PayPal doesn't add a csrf_token either in their cookies or in their URL. The best practice is, every sensitive request after authentication should append some detail that cannot be guessed by attacker otherwise we call it as 'request forgery' – nehem Jan 13 '17 at 06:34
  • @itsneo: What you're talking about is a replay attack, which is *not* the same thing as what's being discussed here. CSRF is not intended to prevent replay attacks. The nonce that's used for preventing replay attacks is a totally different beast than the CSRF token. – Chris Pratt Jan 13 '17 at 13:45
  • 1
    OAuth is *NOT* an authentication framework. Please don't use it thinking it is such. – mak Apr 15 '20 at 23:22
  • It's not a *framework*. It's pattern/standard, but I have no idea what point you're making here, because it is very much for authentication. – Chris Pratt Apr 16 '20 at 01:25
  • @ChrisPratt No, _wrong_. For anyone else coming along, this is very important: OAuth _is not for authentication_. OAuth is for _authorization_, meaning the grant or denial of privileges to some resource, _assuming the actor requesting access to that resource is **authenticated**_. Something like OIDC describes _authentication_. – Travis Mehlinger Jul 16 '20 at 16:15
  • @TravisMehlinger Since the integration of OpenID the OAuth flows also can be used for authentication. – Sebi2020 Aug 10 '20 at 08:39
52

CSRF attacks rely on cookies being implicitly sent with all requests to a particular domain. If your API endpoints do not allow cookie-based authentication, you should be good.

Even if you do use cookie-based authentication, your cookies are safe because iOS apps do not share cookies. However, unless you intentionally block web browsers by requiring an unusual user-agent header, another party could build a browser-based app that uses your API, and that app would be vulnerable to CSRF attacks if your API supports cookie-based authentication and doesn't apply CSRF protection.

Community
  • 1
  • 1
Nick Retallack
  • 18,986
  • 17
  • 92
  • 114
19

They do apply if you're also using your API to support a website.

In this case you still need some form of CSRF protection to prevent someone embedding requests in other sites to have drive-by effects on an authenticated user's account.

Chrome seems to deny cross-origin POST requests by default (other browsers may not be so strict), but allows GET requests cross-origin so you must make sure any GET requests in your API don't have side-effects.

James
  • 24,676
  • 13
  • 84
  • 130
15

This currently accepted answer (May 2012) is mostly correct, except for when you are using session-based authentication. It's also worth mentioning the role of CORS.

The simple scenario is that you visit foo.com and the website executes JavaScript to make an AJAX-based DELETE request to api.com/users/123 and ends up deleting the user on your behalf. Now this isn't always possible because of CORS -- browsers will prevent foo.com from making a request to api.com unless api.com explicitly whitelists foo.com.

This also assumes that you are using session-based authentication for your APIs as opposed to token-based authentication. In session-based authentication, any user who is logged in to api.com can execute requests while they remain logged in. If you have token-based authentication (each request must be crafted with an HTTP Authorization header containing the auth token) then you are safe. Session-based authentication implicitly sends the auth token via cookies.

A slightly worse scenario is if one of your trusted CORS domains becomes compromised - say you have a form which doesn't sanitize JavaScript and a user manages to inject JS onto your site through that form. If you are using session-based authentication, then an authenticated user visiting the page will see the JavaScript run and make an API request. This could be disastrous and a very real possibility if you are using session-based authentication for your API.

informatik01
  • 16,038
  • 10
  • 74
  • 104
aleemb
  • 31,265
  • 19
  • 98
  • 114
6

According to DRF documentation, APIs are vulnerable to CSRF attack as long as the server uses authenticated session (instead of asking every time password)

The solution is

  1. Ensure that the 'safe' HTTP operations, such as GET, HEAD and OPTIONS cannot be used to alter any server-side state.
  2. Ensure that any 'unsafe' HTTP operations, such as POST, PUT, PATCH and DELETE, always require a valid CSRF token.
nehem
  • 12,775
  • 6
  • 58
  • 84