Hacker News new | past | comments | ask | show | jobs | submit login

Ways this story could have ended badly for the developers:

- instead of hardcoding the allowed value, they set it to always echo the value of the Origin header - browsers are powerless against that much stupidity, and can't distinguish it from a correctly configured server that is allowing the request. evil.com sends the request, bank says "evil.com" is allowed, browser shrugs and sends the request.

- instead of using CORS, they could have tried to build their own custom solution that allows ournewbankapp.com. The attacker would have to analyze how it works, and would then most likely find a way to exploit it to perform the attack, while legitimate users with privacy extensions would make the support hotline despair due to countless people complaining "I can't send money".

- instead of adding the custom header, they could have decided to check if "origin" is present, and if so, assume it's a cross-site request and check the origin against a whitelist. This still relies on standard-compliant browsers but isn't the worst idea AS LONG AS YOU REQUIRE AN ORIGIN VALUE, AND TREAT LACK OF AN ORIGIN HEADER AS A FATAL ERROR, BEFORE TAKING ANY ACTION (e.g. the money transfer) BASED ON THE REQUEST. I think can force same-origin requests to include the origin header with some option on fetch(). But if you treat a missing (or "null") header as ok, the attacker will likely find a way to make some browsers send no header, and steal money again. Sending "null" (or some other default value, been a while since I played with it) is easy, I think with some iframe trickery.

- they could have used plain HTTP, exposing them to DNS rebinding attacks even from remote attackers who cannot sniff their user's traffic.

- they could have an XSS vulnerability somewhere on the main site or the whitelisted marketing site, allowing the attacker to proxy his malicious requests through that site (and thus make them use a whitelisted origin). Maybe some long-forgotten kludge designed to proxy requests to third parties that don't support CORS...




Variant of #1 that I've seen not infrequently:

They set it to check a regex for `bank.com` to also allow `subdomain.bank.com`, but inadvertently also allow `bank.com.evil.com`, `evilbank.com`, or similar.


How would DNS rebinding work? I thought DNS rebinding only works if there's some sort of authority that's ambient across hostnames (such as whitelisted user IP ranges, or connectivity to a network), which doesn't seem to apply here. If you do have authority that's ambient across hostnames, my thought of how to protect yourself is to check the Host header.

XSS is essentially completely separate from CORS and CSRF. XSS is a bad vulnerability, worse than CSRF, and you can't expect any type of CSRF prevention to protect against XSS.


How would one handle the situation of having to respond to (authenticated) requests from a web app running on both localhost and a domain-based website?

I've been in this situation before with web-based cross-platform apps using Cordova. As far as I remember, I ended up echoing the origin domain if it matched a set of allowed domains (basically localhost and example.com), since regular expressions or lists are not supported in allowed-origin headers. For session tracking, I used tokens rather than cookies to avoid CSRF issues. Would there have been any better solution for this? I think not.




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: