Revisit the JSON only API is safe statement
bitinn opened this issue · 8 comments
I asked this in #3 but at the time I wasn't using JSON only API, so I didn't try it out.
Now that I am designing such an API, this question pops up again: it seems JSON only API is not immune from XSRF, you need at least request.type check and possibly more:
http://security.stackexchange.com/questions/10227/csrf-with-json-post
@bitinn I can confirm that you can trigger a cross-domain request using a form post, including cookies because I've successfully executed that attack myself on multiple occasions in order to test this. The only reason CSRF tokens protect you here is that they prevent you from accessing the results of the cross-domain call (see http://stackoverflow.com/a/11423778/486547 for more info)
@bitinn to clarify further, I believe what @jonathanong is getting at in the README is that if you have an endpoint that only accepts JSON-encoded request data, and you don't expose it to untrusted domains using jsonp or cors, then you're safe (because you can't execute a CSRF attack using someone's cookies if the targeted endpoint doesn't accept form-encoded data)
@bitinn which... after re-reading your issue, it's actually pretty clear you already realize that :p Sorry! (I'm too used to thinking about request encodings interchangeably from the projects I work on) Your point is totally valid. To recap, from reading that link, it seems that it would be useful to update the readme: API endpoints that accept only JSON-encoded request data and also demand the content-type:application/json
header are safe by default from CSRF attacks.
While it is true, that you cannot do a cross-origin XMLHttpRequest, it is possible to use JavaScript to do a cross-origin HTTP POST request, even with the content-type application/json
using Navigator.sendBeacon()
. To hinder this, you have to configure the server to return appropriate Access-Control
headers on the preflight request.
So the barrier to rely on “AJAX calls use JavaScript and are CORS-restricted” is quite high (ensure correct Content-type + provide correct headers on a preflight) and I recommend not to rely on it.
So I advise you to remove the advise “if you don't support CORS and your APIs are strictly JSON, there is absolutely no point in adding CSRF tokens to your AJAX calls.” or at least explain what is needed to really make sure that your API is “strictly JSON”.
Folllow @datenreisender
Do a cross-origin POST request with Content-Type:application/json
using js:
var data = new Blob([JSON.stringify({foo: "foo"})], {type : 'application/json'}); navigator.sendBeacon("other origin", data);
Hinder this:
Explicitly setting Access-Control-Allow-Origin: "your origin"
So the barrier to rely on “AJAX calls use JavaScript and are CORS-restricted” is quite high (ensure correct Content-type + provide correct headers on a preflight) and I recommend not to rely on it.
Yes, a very high bar. Let me update this to be clearer.
(sorry about the delay, I forgot about this)
The only reason CSRF tokens protect you here is that they prevent you from accessing the results of the cross-domain call (see http://stackoverflow.com/a/11423778/486547 for more info)
I should add this too
also i did not know about the beacon thing