Attacks like CSRF or XSS are still not clear to many of us. It is not because they are super hard to understand, but it requires some basic understanding of concepts like SOP, CORS, CSP, HTTPS. In this series of posts, I’ll try to clear them up one-by-one, and next time you read about attacks, you’ll understand everything.
It is a security measure implemented by most browsers to protect users from the bad guys. It’s meant to keep you secure and it isn’t something new. It dates back to the old Netscape times. What it does is simple, blocks reading resources from other domains, only same-origin is allowed.
The resource here can be the DOM of an iframe you embedded in the page, a JSON response in an http request, or cookies.
Why does it exist? It’s there to keep you secure from the malicious scripts which might be running on the websites you visit. Although you’re visiting evil.com, scripts running on this site can make requests to my-bank.com/get-account-details, or embed an iframe with source my-bank.com/get-account-details and then try to read the response/DOM to access your data. In case you think “it’s fine as they don’t know my credentials”, think twice. Browser will use existing cookies for my-bank.com automatically. It means if you have an active session on my-bank.com, malicious scripts don’t need your credential.
There are also some common misconceptions on SOP. It does not block sending requests to the backend. It only blocks reading the response. “That’s great, let me trigger a call to mybank.com/transfer-money in my malicious script. I just want the request to reach the backend, I don’t care about the response, I’ll see it in my bank account anyways” you might be saying. Not that fast. Of course, from SOP point of view, that’s perfectly fine. But, there are other security measures to prevent that. That’s the most important aspect you should really understand about SOP. Let’s repeat again: you can freely send any request to any domain, SOP does not care about requests, it only blocks reading the response from other domains.
Due to the same reason above, SOP not blocking the requests, it does not help with CSRF attacks. This attack relies on sending the request under the hood with the cookies you already have for that domain . It does not care about the response.
If you’re saying “yes, there is no news here to me”, great! you can stop reading. Otherwise, keep going.
Protocol (http, https) +Host (example.com) +Port (8080)
- http://example.com:8000/abc due to different port
- https://example.com/abc due to different protocol
- http://test.example.com/abc due to different host
Please note that below examples assume there is no additional security checks at the backend and focuses on SOP only.
SOP saves the day and blocks reading the DOM of an iframe which belong to another domain.
I hear some of you saying “I never used iframe, do you have some other example?”. Okay, let’s give the same example without iframes. I own evil.com and you visit it since you don’t know I do evil things. The JS code I added in evil.com sends a GET request to gmail.com/get-all-emails. Do you think I’ll be able to send it?
The answer is yes (what?!). Just to point out again, SOP does not do anything for the requests, it blocks response only. My request will be sent to gmail and browser will get a 200 success. When my script tries to see the response, however, it won’t be able to, neither will you when you check Network/Response tab in Chrome dev tools. Browser will block it as SOP promised. (This can be relaxed using CORS though)
SOP rescues us again and blocks reading the response of an http request from another domain.
Web mostly relies on cookies for authentication. Web server sets some cookies for its domain so that it can identify you when it receives a request from you. To keep things simple, let’s say when you login to gmail.com it sets a cookie username="email@example.com" for domain gmail.com. Whenever there is a request going to gmail.com, your browser will add all your valid cookies belong to that domain. That means, when you call gmail.com/get-all-emails, it will also send username=”firstname.lastname@example.org” without you realising. And Gmail’s web server will see who you are from the cookie and return all the emails you have.
In real world, it’s not that simple. Gmail actually sets something to identify you, but it’s more complex and if anyone changes any part of that string, they would know and refuse to respond to your request.
I think it’s somewhat clear now that whoever has that string can actually get all your emails. So, it’s super important for the browser not to expose cookies from one domain to another one. Again, as being the owner of evil.com, I can send a request to gmail.com on your behalf and browser will include all cookies belong to gmail.com domain. But, the scripts running on