Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's to stop malicious code from spoofing the "Origin" header to exploit CORS?

The way I understand it, if a client-side script running on a page from foo.com wants to request data from bar.com, in the request it must specify the header Origin: http://foo.com, and bar must respond with Access-Control-Allow-Origin: http://foo.com.

What is there to stop malicious code from the site roh.com from simply spoofing the header Origin: http://foo.com to request pages from bar?

like image 878
Jay Lamont Avatar asked Oct 08 '22 09:10

Jay Lamont


People also ask

Can CORS origin be spoofed?

What I've found is that the browser may be smart enough to know a spoofed CORS request when it sees one, but your server isn't as smart. The first thing I found was that the Origin header is an HTTP forbidden header name that cannot be modified programmatically.

How do you deal with CORS problems?

In order to fix CORS, you need to make sure that the API is sending proper headers (Access-Control-Allow-*). That's why it's not something you can fix in the UI, and that's why it only causes an issue in the browser and not via curl: because it's the browser that checks and eventually blocks the calls.

What is CORS protection?

The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch to mitigate the risks of cross-origin HTTP requests.

How do you bypass CORS?

Try to add a callback parameter in the request. Maybe the page was prepared to send the data as JSONP. In that case the page will send back the data with Content-Type: application/javascript which will bypass the CORS policy.


2 Answers

Browsers are in control of setting the Origin header, and users can't override this value. So you won't see the Origin header spoofed from a browser. A malicious user could craft a curl request that manually sets the Origin header, but this request would come from outside a browser, and may not have browser-specific info (such as cookies).

Remember: CORS is not security. Do not rely on CORS to secure your site. If you are serving protected data, use cookies or OAuth tokens or something other than the Origin header to secure that data. The Access-Control-Allow-Origin header in CORS only dictates which origins should be allowed to make cross-origin requests. Don't rely on it for anything more.

like image 219
monsur Avatar answered Oct 09 '22 22:10

monsur


TLDR: There's nothing stopping malicious code from spoofing the origin. When that happens, your server will never know about it and will act upon the requests. Sometimes those requests are expensive. So don't use CORS in place of any type of security.


I've been playing around with CORS recently, and I've asked myself the same question. What I've found is that the browser may be smart enough to know a spoofed CORS request when it sees one, but your server isn't as smart.

The first thing I found was that the Origin header is an HTTP forbidden header name that cannot be modified programmatically. Which means you can modify it in about 8 seconds using Modify Headers for Google Chrome.

To test this, I set up two Client domains and one Server domain. I included a CORS whitelist on the Server, which allowed CORS requests from Client 1 but not from Client 2. I tested both clients, and indeed Client 1's CORS requests succeeded while Client 2's failed.

Then I spoofed Client 2's Origin header to match Client 1's. The Server received the spoofed Origin header, and successfully passed the whitelist check (or failed if you're a glass-half-empty kind of guy). After that, the Server performed dutifully by consuming all the resources that it was designed to consume (database calls, sending expensive emails, sending even more expensive sms messages, etc.). When that was done, the server happily sent the spoofed Access-Control-Allow-Origin header back to the browser.

The documentation I've read states that the Access-Control-Allow-Origin value received must match the Origin value sent in the request exactly. They did match, so I was surprised when I saw the following message in Chrome:

XMLHttpRequest cannot load http://server.dev/test. The 'Access-Control-Allow-Origin' header has a value http://client1.dev that is not equal to the supplied origin. Origin http://client2.dev is therefore not allowed access.

The documentation I read doesn't seem to be accurate. Chrome's network tab clearly shows both the request and response headers as http://client1.dev, but you can see in the error that Chrome somehow knows the real origin was http://client2.dev and correctly rejects the response. Which doesn't matter at this point because the server had already accepted the spoofed request and spent my money.

like image 59
Nocturno Avatar answered Oct 09 '22 22:10

Nocturno