As indicated by `enctype`, and the resulting Content-Type on the request, you're POSTing plain text, not JSON. A server needs to verify the Content-Type of the incoming data to ensure it doesn't fall victim to this sort of thing, or just misinterprets other data. In this case, the server is mis-interpreting plain text as if it were JSON.
(A good HTTP framework, IMO, should come with this built into its API, on requesting the payload as a JSON object. Some frameworks … try. A lot do leave it up to the user, which is hideously error prone. Also, this isn't to defend that cross-origin POST is sort-of allowed. I wish we could remove that historical wart.)
If browsers could fix CSRF for JSON they could probably fix it in general. My impression is that browsers have done what they can. Sites without CSRF protection should do a better job.
It's been plagued initially be slow adoption and later by inconsistent support like the example in this article and others[1], but as a general spec. it should fix CSRF if implemented consistently and correctly by browser vendors.
SameSite cookies handle pretty much all cases and are supported in all modern browsers. If your login (which is what usually issues the cookie) does a module/nomodule check SameSite is probably enough.
It's more of a deliberate hack that takes advantage of "form submission is not subject to the Same-Origin Policy". So it opens up CSRF in cases where the target might have assumed they were safe. Maybe you could, for example, figure out someone's logged-in Google ID this way (made up example, they likely catch this).
You can actually just make an XMLHttpRequest that's the same as what the form would do; CORS won't block the request going through to the server, it just blocks the javascript seeing the response:
The only time the request is made by default is when it falls in to the "simple" category, which as far as I'm aware, is limited to
- GET requests
- That only include known header fields
In all other cases, you fall into the other bucket. In that case the browser will make a preflight options request (without any data) to check the CORS response headers configured by the server. Only then, if allowed by the response headers, will the browser actually make the POST.
---
Ok, I went and looked, apparently you can send POSTS, you just can't send application/json, only one of the default form content types (text/plain is one, though).
So I'm wrong - At least for Firefox, this would likely be the same request with the same behavior.
Does it? I mean, the returns the response to the browser, but I believe the browser then renders that new page, which should be harmless since the server isn't going to return a malicious page.
(A good HTTP framework, IMO, should come with this built into its API, on requesting the payload as a JSON object. Some frameworks … try. A lot do leave it up to the user, which is hideously error prone. Also, this isn't to defend that cross-origin POST is sort-of allowed. I wish we could remove that historical wart.)