3 ms·
My understanding was that "preventing otherwise disallowed HTTP requests" was the entire point of the preflight OPTIONS request, and that CORS will do nothing i
by Sophira 4mo ago
My understanding was that "preventing otherwise disallowed HTTP requests" was the entire point of the preflight OPTIONS request, and that CORS will do nothing if the request would otherwise be allowed.
For example, a POST request with a Content-Type of "text/json" would not be allowed to be sent to third-party hosts without an OPTIONS preflight, but one with a Content-Type of "multipart/form-data" would be allowed and wouldn't be stopped by CORS at all, even to third-party hosts.
(And, of course, if your endpoint just assumes JSON without strictly checking the Content-Type, then congratulations, you've just allowed any website to POST to you, with no user action required.)
- xg15 4mo ago> (And, of course, if your endpoint just assumes JSON without strictly checking the Content-Type, then congratulations, you've just allowed any website to POST to you, with no user action required.) Is that so? Neither urlencoded forms nor multipart/form-data are valid JSON on the wire, so while other websites could send requests, wouldn't they just hit a parse error?
- RagingCactus 4mo agoYou can massage a text/plain form into valid JSON. text/plain is also one of the allowed default types. It works if the server doesn't check the content-type. Source: I've done that successfully in multiple pentests. Edit: lazy LLM generated example: <form action="https://example.com/api" method="POST" enctype="text/plain"> <input name='{"key":"value", "ignore":"' value='"}'> </form> That gives you {"key":"value", "ignore":"="} The trick is to stuff the = character you cannot control into an irrelevant value.
- xg15 4mo agoOuch! Ok, I wasn't aware text/plain was also one of the whitelisted values and lets you do that. That looks pretty bad indeed.
- TeMPOraL 4mo agoOr good, depending on who you are. I find CORS to be pain in my butt by effectively preventing ad-hoc client-side browser tools from being able to use most APIs, and forcing me to do bullshit make-work involving a server side component and certificates just to work around this + HTTPS, at which point I may as well just have my "backend" shell out to `curl`, which happily doesn't care about any of that nonsense.
- xg15 4mo agoI mean, it still relies on a vulnerable configuration (not checking the content type) For adhoc dev tools, you could also just disable CORS: https://berkkaraal.com/notes/other/chrome-disable-cors/ https://berkkaraal.com/notes/other/chrome-disable-cors/
- TeMPOraL 4mo ago> I mean, it still relies on a vulnerable configuration (not checking the content type) Unless I'm misunderstanding the claim, that's not "vulnerable configuration", but extreme lunacy - basically treating parsing outcome as access control. "Did the payload parse correctly as JSON? No -> go away; Yes -> oh that must mean you're supposed to be here". I'm at a loss of words that this is even a problem in practice. > For adhoc dev tools There's a whole space between "adhoc" and "dev" tools, though, and this is what interests me the most. Yes, when I'm in full dev mode, I can make my computer do anything I need to. But more often than that, I'm just a user that wants to exercise some basic freedom of computing - to remove some toil or frustration from daily computing experience - without switching my hat from "user" to "developer". That's what CORS has been successfully defeating, by forcing any ad-hoc non-dev tool I could make for myself to require being in "developer mode" to use it.
- Sophira 4mo agoRegarding the first part, it's easier than you might think to have a false sense of security. I've seen a web application that did, in fact, check the Content-Type header to make sure that "application/json" was there - but it didn't check that the header value started with that. That meant that setting the header to "multipart/form-data; boundary=application/json" was enough to bypass a CORS preflight!
- Sophira 4mo agoIf your web application specifically parses data based on the Content-Type that it advertises itself to be, then yes, the webapp would hit a parse error. But there are many applications that don't do that. An attacker might use JavaScript to set a "multipart/form-data" Content-Type (thereby bypassing the otherwise required OPTIONS preflight), but send JSON in the request body. Unless your web application specifically parses the body based on the Content-Type (web servers don't do this for you), then you wouldn't detect that.
- xg15 4mo agoWell, if your endpoint expects JSON, then at some point it will have to parse it. Even if it completely ignores the content-type header and simply always passes the request body to the JSON parser, the parser would throw. (But I was wrong, there are ways to produce request bodies that are valid JSON even if the browser forces you into a different format, as the sibling comment demonstrated)
- TeMPOraL 4mo agoObviously JSON is a subset of text/plain, so I don't know what people were expecting? For text/plain to mean "plaintext, excluding any string that could possibly parse as any of the other named formats that have a plaintext representation"? Are people using JSON parser as proxy for access control? "Payload successfully parsed as JSON, therefore you are allowed to use this endpoint"?
- xg15 4mo agoI wasn't aware that plaintext was one of the whitelisted types that are allowed without a preflight request. I guess the same trick might work with urlencoded forms, but it wouldn't work with multipart/form-data > Are people using JSON parser as proxy for access control? "Payload successfully parsed as JSON, therefore you are allowed to use this endpoint"? For better or worse, yes, or at least as one layer. That's one of the rationales behind the "safe" requests AFAIK. And this wouldn't be the first time, protocols are made intentionally incompatible on the wire, so an attacker can't smuggle one inside the other. That's the entire reason for WebSocket's weird handshake dance and the "xor encoding" it applies to messages from the client.