From what I've read, CSRF prevention seems to focus on (1) making GET requests side-effect-free and (2) using only POST requests with CSRF tokens to alter state. It seems to me, though, that this assumes that the only objective an attacker might have would be to maliciously update the victim website. What if the attacker just wants information which can be retrieved via a GET request? Couldn't someone embed a sensitive resource from the victim site into the attacking site and interact with it via Javascript?
So my questions are (1) is that possible, and (2) how do you prevent it?
An attacker could include the following script on their page:
$.get('http://vulnerable.example.com/json')
However, due to the Same Origin Policy, the JavaScript on the attacker's domain couldn't read the response. The same origin policy checks whether the domain, protocol and port match - if they don't the JavaScript will encounter a security error when trying to read the response. For example, this is the warning Chrome gives when trying to access an IFrame from another domain - this is exactly the same mechanism that will protect the JavaScript response.
Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': blocked a frame with origin "http://evil.com" from accessing a frame with origin "http://vulnerable.example.com". Protocols, domains, and ports must match.
So in summary, POST requests must use a CSRF token as the POST request will still be made even though the response cannot be read and GET requests are not normally a cause for concern as the response cannot be read and they are non destructive. There was the issue with JSON Hijacking, but you have to go back as far as Firefox 3 to find a browser vulnerable to this. See Is JSON Hijacking still an issue in modern browsers?
If an attacker had a way to receive the server's response to the victim's request (the response would be transmitted to the victim's browser, but not transmitted to the attacker), then the attacker could potentially benefit from a CSRF GET request.
However, in a typical CSRF scenario, the attacker does not have access to the response, because it is transmitted from the server to the victim's web browser (and not transmitted to the attacker). Usually the intent is to cause some state change, such as initiating a payment, sending an email, etc, which is usually initiated by a client making an HTTP request with a method like PUT, POST, PATCH or DELETE.
Related
So I have been developing a webpage the would give random quotes whenever a user clicks on a button by calling an API.
Please refer to my previous question for more information Not able to get values (quotes) from the API using jquery
I was told that the reason I couldn't get the response from the API is because my ACAS(Access-control-Allow-Origin) is not set properly in my server and I have to debug it.
Now that I don't much about ACAS or CORS. I have some questions. SO here they are:
1. What exactly is ACAS and how is it related to CORS?
2. How do I debug my page and set the ACAS?
3. Does that have to do anything with my jQuery? Or should I configure only my browser.
You can find many documents on the internet
,so I'll just briefly talk about CORS.
When you're sending request to different domain
for example from a.com to b.com, or localhost:8080 to a.com......
your're making a cross-origin HTTP request ,
sometime this is not allowed, for example Ajax (as you're doing) requests.
Because XhttpRequest, Fetch (both are Ajax API) follow same-origin policy, which means by default you can only make requests form the same domain, ex: from site.com to site.com/users.
The reason they follow the same-origin policy is to prevent CSRF attack (Cross-site request forgery).
1.So basically you cannot get the result of cross site Ajax request, it will block by browser because of the security issue, unless the response header Access-control-Allow-Origin is set to allow client's site to send cross site ajax request. ex: Access-control-Allow-Origin:*allow all sites form different domain; Access-control-Allow-Origin:www.b.comonly allow www.b.com domain.
2.Take Chrome for example If the cross site request's result is blocked, it will show on browser's console:
You need to set the response header in your server, for example I set Access-control-Allow-Origin:*, then in browser's "network" console you can see the header is set, and now I can get the Ajax result.
I think nothing should do at client side, all is at server side.
Refer to this post as it makes this clear
Note also that there are some techniques frequently used in order to bypass CORS like setting up a proxy which acts as a relay for your request or using JSONP instead of JSON.
I just found out that in order to allow cross-domain AJAX calls, Access-Control-Allow-Origin header should be set on SERVER side. This looks frustrating to me, let me explain why:
1) Typical use case is that the client wants to make a cross-domain request. I have never heard of a server trying to restrict access from alien webpages. Oh, I remember 'prevent images hotlinking', a funny feature of my hosting, which can be easily beaten by sending fake 'Referrer` header.
2) Even if server wanted to restrict connections from other domains, it's impossible to do this using capabilities of HTTP protocol. I suggest using tokens for that.
3) What's the use of blocking XMLHttpRequests while you still can use jsonp?
Can you explain why is this done that way?
For those who are still reading, there's a bonus question:
4) Do you know a way to prevent any cross-domain request from a webpage? Imagine a junior web developer creating a login form on a page having ads or other scripts potentially sniffing passwords? Isn't this the essence of web security? Why anyone is talking about that?
I have never heard of a server trying to restrict access from alien webpages.
The Same Origin Policy is a restriction imposed by browsers, not servers.
CORS is the server telling the browser that it can relax its normal security because the data doesn't need that level of protection.
Even if server wanted to restrict connections from other domains, it's impossible to do this using capabilities of HTTP protocol.
Which is why HTTP the protocol isn't used for that.
I suggest using tokens for that.
Using a nonce to protect against CSRF solves a different problem.
It's a relatively expensive solution that you only need to get out when it is the side effects of the request that can be problematic (e.g. "Post a new comment") rather then the data being passed back to JavaScript running on another site.
You couldn't use them instead of the Same Origin Policy to protect against reading data across origins because (without the Same Origin Policy) the attacking site would be able to read the token.
What's the use of blocking XMLHttpRequests while you still can use jsonp?
You can't use JSONP unless the server provides the data in JSONP.
Providing the data in JSONP and using CORS to grant permission to access resources are two different ways that the server can allow the browser to access data that is normally protected by the Same Origin Policy.
JSONP was a hack. CORS came later and is more flexible (since it can allow access to any kind of data, respond to request methods other than GET, and allow custom HTTP headers to be added).
Can you explain why is this done that way?
The default policy is "No Access" since there is no way for the browser to know if the data being requested is public or not.
Consider this situation:
Alice has an account on Bob's website. That account is password protected and has information that should be kept secret between Alice and Bob (bank records or exam results, for example).
Mallory has another website. It uses Ajax to try to access Bob's site.
Without the Same Origin Policy, Alice might (while logged in to Bob's site) visit Mallory's website. Without Alice's knowledge or permission, Mallory's website sends JavaScript to Alice's browser that uses Ajax to fetch data from Bob's site. Since it is coming from Alice's browser, all of Alice's private information is given to the JavaScript. The JavaScript then sends it to Mallory.
This is clearly not a good thing.
The Same Origin Policy prevents that.
If Bob, as the person running the site, decides that the information is not secret and can be shared publicly, then he can use CORS or JSONP to provide access to it to JavaScript running on other sites.
Do you know a way to prevent any cross-domain request from a webpage.
No. The webpage is a single entity. Trying to police parts of it from other parts is a fool's errand.
Imagine a junior web developer creating a login form on a page having ads or other scripts potentially sniffing passwords? Isn't this the essence of web security? Why anyone is talking about that?
"Be careful about trusting third party scripts" is something that doesn't get mentioned as much as it should be. Thankfully, most ad providers and CDN hosted libraries are supplied by reasonably trustworthy people.
Do you know an easy way of overcoming the problem of missing Access-Control-Allow-Origin
Configure the server so it isn't missing.
Use JSONP instead
Use a proxy that isn't blocked by the same origin policy to fetch the data instead (you won't get any credentials the browser might send because Alice has an account with Bob though).
I have read some articles on Same Origin Policy and CORS and still doesn't understand well the security that it brings to the user.
The Same Origin Policy gives a true valuable security, preventing a site from an origin from accessing some webpage content on another website. Thus preventing the threat of having the content of a iframe accessed by the script of the container, possibly faked/phishing website.
But here comes AJAX and CORS. CORS gives the ability for the server to control which origins can access it. But, at the end, it is the browser which stops the request if not allowed, after headers handcheck.
So, imagine you get some malicious website myphishing.com. You want to show information from another trusted website mybank.com through AJAX request to this site. This one is protected by well configured CORS headers only allowing request from mybank.com origin. What if, me author of myphising.com, relay all requests to mybank.com by a proxy that alter headers in both request and response way to fake client browser and bank server? It seems one can change the origin header in the request for a mybank.com one, and change the CORS response headers to make the browser think myphishing.com is allowed to make the request. Headers handcheck passed, you can then send the request and get the response with similar headers substitution tricks.
Perhaps I'm totally misleaded, but I would be very pleased if someone could show me where I have misunderstand the whole thing.
Possible duplicate but I didn't find my answer here: What is the threat model for the same origin policy?.
What if, me author of myphising.com, relay all requests to mybank.com by a proxy that alter headers in both request and response way to fake client browser and bank server?
You could do that anyway, CORS or no CORS.
If the request is coming from your proxy, however, then it has no way to know what credentials the browser would have sent to the server if the request was coming from the browser.
This is a concept that I thought I understood, but recently found out I had all wrong. I've looked all around the internet and find plenty of examples of small details and code snippets, but I still lack an understanding of what it prevents and why it prevents it and for whose sake. So this is more of a request for a high-level explanation than a question.
Anyways, here's what I THINK I understand about it:
Let's say I have domain A.com and domain B.com. Each on their own apache servers with their own IP addresses.
I load an html file from domain A.com into a browser. The browser executes a POST XMLHttpRequest to B.com/doStuff.php, which fails because the same-domain-policy was set.
So:
Who's same-domain-policy is relevant? I think the answer is B.com/doStuff.php's... right? So when A sends the request, B checks the request headers for an origin and says "whoops, different domain, won't listen to you". Or does A send the request, B responds with headers that specify "same-domain-policy", and then the browser checks that because same-domain-policy was specified, and the domain from the headers of the A request don't match the one from the B request the BROWSER refuses to send out the xhr?
If that's the case, it seems that the point of not allowing cross-origin-requests is because "I don't want anyone other than me accessing my API". Is that all? Because wouldn't you want to solve that with some kind of authentication instead? Couldn't someone just construct an HTTP request with a fake origin header (simply lie)?
Or is this somehow supposed to protect the user? If that's the case, how is preventing them from calling your API ever going to protect anyone?
I'm so confused...
Who's same-domain-policy is relevant?
The server receiving the request decides.
... the BROWSER refuses to send out the xhr?
No, the server refuses to respond. To be more exact, in modern browsers it is done by preflighted requests. It means that for each cross-origin request, first an OPTIONS request is sent automatically by the browser whose headers are the exact same as the intended request will have but with no request body. The server responds also with headers only. Access-Control headers in the response will let the client browser know whether the request would be fulfilled according to the server's policies. In a sense the browser is preventing the request, but only because it already exchanged a request/response pair with the server and knows that there would be no point to attempt the request. If you forge a request in such a case, the server will still deny serving it.
The idea is that you don't want to access server b from server A via Javascript. If you're interacting with an API, you would use javascript to make a call to your own server's backend code, which would then make a call to the other server.
I know its violates the Same origin policy, and that is why it is not possible through simple ajax request. I could use JSONP. But using JSONP for login doesn't sound secure ( no post only get ).
So is there a more secure way of implementing login into https through ajax ?
Not only does it violate the same origin policy, but since the page you are calling from is insecure it has the potential to be interfered with and leak all the data you are trying to keep secure.
Use HTTPS for the entire process.
Better yet, keep using HTTPS while people are logged in, otherwise you will have the Firesheep problem.
As we've discussed in the comments below, this is what Facebook does for their registration page, although there are some vulnerabilities to this method. While it won't appear secure to the user (no lock icon), the actual request is done over HTTPS. If you controlled the entirety of the receiving page, there would be nothing less secure about doing a JSONP request over GET. However, a man-in-the-middle attack could modify the receiving page on load, and cause the returned credentials to be sent to an attacker.
On the plus side though, no one that's just sniffing packets is going to be able to get the credentials: an attack would have to be fairly targeted.
Regarding cookies, technically, JSONP could "return" cookies; you'd just return name-value pairs of the cookies you wanted to set, and have a function on the receiving page set them.
But unless the browser treats <script>s differently, and it might, you should be able to set a cookie in the normal way using the Response Headers of your JSONP response.