83

I recently learned about CORS and got the impression that its purpose is to prevent XSS. With CORS, the browser blocks requests to different domains, unless particular headers are in place.

But if a person with malicious intent injects some JavaScript into a page to steal users' cookies and send them to a URL he controls, all he has to do is add the following header on the server side to make the request work anyway:

Access-Control-Allow-Origin: *

So how does CORS prevent XSS? Or did I misunderstand the purpose of CORS, and it simply has nothing to do with XSS per se?

2
  • 4
    all he has to do is add the following header on the server side to make the request work anyway - if somebody has access to HTTP header config on the server there are bigger problems than cross-domain attacks.
    – user81147
    Dec 23, 2015 at 14:28
  • 16
    He can do that because it's his server (in the scenario I suggested): "a URL he controls".
    – Gigi
    Dec 23, 2015 at 14:30

6 Answers 6

63

TL;DR: How does CORS prevent XSS? It does not. It is not meant to do so.

CORS is intended to allow resource hosts (any service that makes its data available via HTTP) to restrict which websites may access that data.

Example: You are hosting a website that shows traffic data and you are using AJAX requests on your website. If SOP and CORS were not there, any other website could show your traffic data by simply AJAXing to your endpoints; anyone could easily "steal" your data and thus your users and your money.

In some cases that sharing of data (Cross Origin Resource Sharing) is intended, e.g. when displaying likes and stuff from the Facebook API on your webpage. Simply removing SOP to accomplish that is a bad idea because of the reasons explained in the above paragraph. So CORS was introduced.

CORS is unrelated to XSS because any attacker who can place an evil piece of JavaScript into a website can also set up a server that sends correct CORS headers. CORS cannot prevent malicious JavaScript from sending session ids and permlogin cookies back to the attacker.

12
  • 3
    Whether or not SOP and CORS were there, any other website could proxy its users' requests. Dec 23, 2015 at 15:22
  • 3
    @tepples: But in this case the cookies for the original site will not be sent with the request and thus it would not be possible to read data which only the logged in user can see. Dec 23, 2015 at 15:50
  • 13
    Exactly. CORS doesn't restrict or prevent anything. CORS is intended to provide a controlled way to relax the restrictions imposed by the same-origin policy. Without CORS, the web would still be just as secure (though not as functional).
    – Ajedi32
    Dec 23, 2015 at 16:42
  • 2
    Yes, they can unless the sensitive data is protected with a login. A foreign website has no access to the session cookies of the "target"/"cors-protected" website. Thus, a malicious server cannot send a valid request for the data - only the users browser and the resource owning party can construct a valid request
    – marstato
    Apr 13, 2017 at 13:10
  • 10
    The example is misleading. This is not the purpose of CORS. Your rival can make a similar website to your, which on the backend would call your server with proper origin headers, and CORS won't stop it. Jul 21, 2017 at 8:54
29

Cross-Site-Scripting (XSS) is the execution of attacker defined script code in the context of another site. CORS does not prevent XSS, in fact it is unrelated to XSS.

Instead CORS offers a way to weaken existing restrictions on Ajax requests (i.e. XMLHttpRequest) in a way which hopefully does not introduce more security problems. Traditionally XMLHttpRequest was restricted to communicate within the same origin, that is it was not possible to sent a request to some external site. This restriction was done so that an attacker cannot do a cross site request and get the result of the request back, because this would allow an attacker to read data from sites where the users was logged in (because session and other cookies are sent with each request to a site).

With CORS this restriction is partly removed. It is now possible to send an XMLHttpRequest to another site but the result can only read inside the application if the remote site explicitly added some CORS headers which allow the access. But again, this is not executing script on the remote site and thus this is unrelated to XSS.

2
  • 7
    To be clear, even before CORS it was possible to send a request to an external site by using a form. What CORS allows is actually reading the response back from a cross-site AJAX request.
    – Ajedi32
    Dec 23, 2015 at 16:49
  • @Ajedi32 You can use CORS to relax both reading and sending restrictions, e.g. with Access-Control-Allow-Headers: Authorization.
    – jub0bs
    Feb 17 at 20:54
11

CORS and XSS are related, but not directly. The best way to explain it is by example: we shall consider 3 servers (your_bank.com, api.your_bank.com, badguy.com*) and 1 client (your browser).

  1. You are logged into your_bank.com (your browser holds authentication cookies).
  2. Your_bank.com makes transactions by sending AJAX requests to api.your_bank.com using yet more cookies (held in the browser). Normally your browser's SOP would block this request, but instead CORS (granted by api.your_bank.com) allows it.
  3. You see something shiny at badguy.com, and visit that page.
  4. Badguy.com attempts transactions by sending AJAX requests to api.your_bank.com using the cookies for that domain held in your browser.

At step 4, your browser (which is not compromised) owns the "Origin" header sent to api.your_bank.com. If CORS is correctly configured, this step will be blocked. Your browser, being the owner of the cookies and request headers, is gatekeeping access to other sites.

* The badguy.com site may be legitimate, but suffer from an XSS issue.

5
  • 2
    "this step will be blocked" I agree that the read will be blocked (i.e. the malicious origin cannot retrieve sensitive information from your bank account), but writes currently aren't blocked by the browser (so CSRF may be in play here) Jan 14, 2020 at 22:21
  • This is an excellent answer, in plain language I can understand.
    – Dean
    Jul 18, 2020 at 18:56
  • I think this post may be more describing a cross-site request forgery (CSRF or XSRF). I'm not a security expert, but from all I have seen, XSS is more commonly used to refer to the likes of it being possible for a hacker to inject client-side script, e.g., if a website does not escape user data when displaying it in HTML. XSS can be mitigated also be headers though: the Content-Security-Policy header may be used to help with XSS such as by preventing inline scripts. Jun 7, 2021 at 15:41
  • 1
    This answer is wrong, I do not understand why it has upvotes. If CORS is configured correctly, the step will not be blocked. The browser will not let badguy.com read the contents of the response. That is all. badguy.com can still send requests to api.your_bank.com. Aug 1, 2021 at 22:57
  • 1
    @KorayTugay While you are technically correct (the best type of correct!) in some circumstances, requests with side effects must be "preflighted". This will block the step. I direct the interested reader to developer.mozilla.org/en-US/docs/Web/HTTP/CORS and fetch.spec.whatwg.org. However, the standards are not easy to read, and I will happily edit if a correction is needed.
    – Daniel
    Aug 3, 2021 at 2:05
6

CORS does not protect anything, SOP (Same Origin Policy) protects something instead. SOP protects the target domain and the browser user.

In fact, CORS weaken existing restrictions of SOP to help website developers to use shared data from other origins.

4

The browser uses SOP (same-origin policy) to protect the user. SOP/CORS does not to protect the services. CORS is a way of the original domain informing the browser that other domains are trusted.

By default, browsers block JS requests made from a.com to b.com.

b.com can publish CORS headers to notify browsers that a.com is trusted (e.g. facebook.com can publish that their messenger.com domain is trusted)

Good browsers block cross origin scripts to protect users. If b.com publishes CORS with certain trusted domains, the browser allows those domains to access services at b.com. If the browser didn't block these for the user, a user could access innocent-looking-malicious-site.com which could access facebook.com services on the user's behalf and get access to secure cookies and other information.

Loose Relation to XSS

If a legitimate site has been compromised by an XSS attack, the SOP/CORS/browser combination can protect the user if the legitimate site's domain name isn't published in the CORS header.

SOP/CORS can't protect a site from being compromised by XSS, but it can help the user if they access an XSS compromised site.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Added clarifications pointed out by user jub0bs

5
  • 1
    This should be the accepted answer. An API is not protected by CORS or any allow headers. It is a restriction that the browser imposes to protect the user (one that can be disabled pretty easily). eg. an API service can still be accessed via nodeJS even without allow *
    – phocks
    Nov 6, 2020 at 10:31
  • 1
    The browser uses CORS to protect the user. No. It's the opposite. The SOP protects users, and CORS is a mechanism to relax some of the restrictions of the SOP.
    – jub0bs
    Jul 30, 2022 at 11:43
  • By default, browsers block JS requests made from a.com to b.com. Not true. Browsers don't block all such requests. As an example, open your console and run fetch("https://example.com", {mode: "no-cors"}). Your browser will prevent the client from reading the response, but the browser will send the request.
    – jub0bs
    Jul 30, 2022 at 11:52
  • @jub0bs Thanks for the clarification, but running fetch in a console is not the same thing as making a request from one site to another.
    – Micah B.
    Aug 2, 2022 at 20:40
  • @MicahB. Yes it is. If you open your Console tab while you're on https://stackoverflow.com and use fetch to send requests to https://example.com/foo, the Origin header of those requests will be https://stackoverflow.com. My point stands.
    – jub0bs
    Aug 3, 2022 at 8:43
2

CORS configuration of your site can allow non-simple requests of your UI to your backend services and at the same time help preventing CSRF (not XSS) (against your site) in case user uses a secure web browser.

By default (when no CORS configuration is set for the site) modern browsers don't allow such requests, which is to prevent CSRF. That is called same-origin policy.

With XSS the inserted malicious js accesses resources on the same web site (origin) so CSRF has no play there.

Basically CORS allows your website js frontend code to access your website backend with the cookies and credentials entered in your browser while your backend stays protected from some other site's js, asking client browser to access it (with the credentials user has already obtained).

This is when Control-Allow-Credentials: true is set (which allows browser to send cookies and basic/gssapi/napi auth). I'm still not sure how CORS helps without this option. See my question "https://security.stackexchange.com/questions/148313"

7
  • CORS can help limit impact of XSS to the vulnerable site How?
    – jub0bs
    Jul 30, 2022 at 11:41
  • @jub0bs, actually my wording is not good. If you have some suggestions to improve, let me know. It's more about proper CORS configuration of the web site can help prevent XSS, provided client browser behaves according to standards. Aug 4, 2022 at 9:04
  • Because I don't know what you had in mind exactly, I'm not sure I can offer a better formulation.
    – jub0bs
    Aug 4, 2022 at 9:41
  • 1
    @jub0bs, I amended that paragraph, let me know if it is clear now. Aug 4, 2022 at 13:12
  • 1
    @jub0bs, thank you for pointing this out! There is actually none connection as you stated. Do you see anything fishy still? Aug 4, 2022 at 17:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .