Most of web developers encounter at one point or another some errors about CORS in the console, of course, we look it up on Google, other devs tell us to just put a line in our backend, and then it's all good from there .... Or is it ?
What really happens when we add that magical StackOverflow one liner response.header("Access-Control-Allow-Origin", "*");
in our server
And how does it affect our security ?
If we try to understand CORS, we find soon enough that we also need to understand SOP. And in this article we'll try to understand how both of them work !
TL;DR
SOP and CORS are web security mechanisms that prevent unauthorised access to resources from different origins.
- Origin : Web content's origin is defined by the scheme (protocol), hostname (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, hostname, and port all match.
- SOP : Same Origin Policy : SOP restricts web resources from being accessed across different origins
- CORS : Cross Origin Ressources Sharing : Allows web resources to be accessed across different origins with appropriate permissions.
Definitions
Some definitions are a bit necessary, for this article, they are perfectible and not precise, but they do the job for the scope of this introductory article :
- Web Resource : A web resource is basically any resource that is the target of a web request.
-
Origin : An origin is defined by the scheme, hostname, and port of a URL. If two URLs have the same scheme, hostname, and port, they are considered to be from the same origin. For example, comparing
"**<https://ovrsea.com:443>**"
to other urls
Same-Origin Policy (SOP)
The Same-Origin Policy is a web security mechanism implemented on the browser side that restricts access to web resources ( by resources, we mean anything that is the target of a HTTP Request, the nature of which is not more defined ) from being accessed across different origins.
The purpose of SOP is to prevent malicious scripts from accessing sensitive resources by restricting them to only access resources from the same origin. This is because web browsers have the unfortunate* tendency to send cookies and other informations to their corresponding origin on each request, which is quiet handy for all legit use cases, but can become problematic if a malicious person try to use this fact.
For example, imagine a malicious website "**<https://evilWebsite.com>**"
that integrates malicious calls to "**<https://bank.com**>"
to steal money from unsuspecting users. If there was no security mechanism, the malicious website will be able to request access for the cookies of the user and read them, and therefore he’ll be able to make the request to the bank to steal money.
But because of the Same-Origin Policy, the malicious website cannot directly access the user's banking information since they have different origins.
However, SOP only prevents the malicious origin from reading the answer, not making it. So, the malicious website can still make the request to the bank domain on behalf of the user, but it cannot read the response due to SOP.
That would need a different kind of protection to Cross Site Request Forgery , which may be the subject of a next article 👀.
In this exemple, the attacker makes the request to bank.com/pay?to=evil&amount=5000
and assuming it doesn't need any kind of authentification or verification more than the cookies, the request will succeed. Hopefully, most banks and websites will actually have CSRF protection and Multi Factor Authentication.
One common misconception is to believe that the SOP prohibits all cross-origin requests. If that were the case, content delivery networks (CDNs) and even the web would be worthless since it would be impossible to use images from other origins, or using javascript packages.
<img href="https://gravatar.com/my-avatar.com" />
<script src="https://unpkg.com/htmx.org@1.9.2"></script>
This is actually permitted in browsers with SOP !
Moreover, the SOP does not prohibit origins from contacting one another or sending and receiving requests (such as submitting forms), they only prohibit reading the results. SOP allows embedding resources ( like images, javascript scripts, or more full html pages ) but again, they don't permit the reading if the request originated from another origin !
But even with this set of rules, it is still too strict for some legitimate usage, like for our case, our frontend https://ovrsea.com
will be able to make the HTTP Request to https://api.ovrsea.com
but will not be able to read the answer (as they are not on the same origin ) , which is no good for us. But thankfully, there is a way to allow us to relax the rules of SOP: by using CORS !
Cross-Origin Resource Sharing (CORS)
Cross-Origin Resource Sharing is a web security mechanism that allows web resources to be accessed across different origins with appropriate permissions. CORS is based on adding HTTP headers to web requests and responses that allow browsers to determine if a web resource can be accessed from a different origin.
CORS works by adding HTTP headers ( the famous Access-Control-Allow-Origin
) to responses that indicate which cross origin is allowed to access a particular resource.
For example, if a web page from "**<https://ovrsea.com>**"
wants to access an API from **“<https://api.ovrsea.com>"**
,
the API should tell the browser
"hey dude it's cool , ovrsea.com is a safe site for me, you can send him my data",
To do that technically the server of the api will set the header to allow for https://ovrsea.com
:
Access-Control-Allow-Origin: '<https://ovrsea.com>'
So now, we understand a bit more about what happens when we set "Access-Control-Allow-Origin": "*"
: it means that everybody is able to request the origin and read from it ! So if that’s not your intended purpose, you better restrict it !
By the way, if you ever wondered about the utility of the OPTIONS
method request you see before making the actual request in your network inspector , well it’s because of CORS. It’s a preflight request that precedes the actual request, to ask the other origin if it’s okay to proceed with the actual request, or if it should be aborted. It’s made this way so that the server can decide on an origin based on whether or not to allow resource sharing.
There is also other headers that may be interesting to use that are more detailed here !
Conclusion
SOP will restrict how we can share resources by limiting the readability of the resources, and CORS will relax those restriction to allow us to access them if they are explicitly allowed to !
But those protections and mechanisms are only implemented on the browser side, this doesn’t block requests made by other means like curl
, wget
, and any other request made by non browsers , so it shouldn’t be used as a way to restrict access to a backend, this should be done by other tools and mechanisms !
Top comments (0)