CSRF with JSON POST when Content-Type must be application/json

Is this application vulnerable to CSRF attack?

Yes, it's vulnerable. The prerequisite, however, here is Flash. With the help of Flash, it's possible to forge a Content-type header with any arbitrary value. What you need to do is POST a request to your own domain, and then issue a 307 redirect. Please refer to below screenshot:

x-domain application/json request

For more information, please refer to this cm2.pw article.

Use something like this: var blob= new Blob([JSON.stringify(YOUR JSON)], {type : 'application/json; charset=UTF-8'}); to generate a JSON blob and it'll send perfectly. CSRF in seconds!

This, afaik, is already fixed in modern browsers. However, it still works in IE with file URI.

Update:
Since it's still getting a lot of views lately, I'm adding links to fixes; https://bugzilla.mozilla.org/show_bug.cgi?id=1436241 https://bugs.chromium.org/p/chromium/issues/detail?id=332023

For some reason, chromium fix does not work and still allow sending POST request with custom Content-type headers.


Warning: This answer may be wrong and to optimistic. See 1lastBr3ath's answer above.

No, I don't think the application is vulnerable.

You can change the Content-Type header, e.g. using the fetch API. However, there are only three values that you can use for cross domain requests:

application/x-www-form-urlencoded
multipart/form-data
text/plain

If you change it to anything else, such as application/json, the browser will first make an OPTIONS request to server, to see if it allows that header to be changed. This behaviour is part of CORS, and it is designed to limit what cross domain requests you can make with JavaScript to the old fashioned ones you could do with simple HTML. So unless the server specifically allows any domain to set this header (which would be a stupid thing to do), you are out of luck.

Note, however, that this seems to be a case of "security by accident". I would rely on something stronger for my CSRF protection (and perhaps they do, once you get past the content type hurdle). What happends if someday someone thinks it would be nice if the server accepts other content types and removes that limitation? With this configuration, it would be easy to accidentally open up a security hole.