Able to make request with credentials include when the response server contains Access-Control-Allow-Origin: *
Categories
(Core :: DOM: Core & HTML, defect)
Tracking
()
People
(Reporter: tarunkant05, Unassigned)
Details
Attachments
(1 file)
|
2.32 MB,
video/mp4
|
Details |
User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Steps to reproduce:
As it is prohibited to use credentials include when the server has this Access-Control-Allow-Origin: * header. (I am saying everywhere credentials include because I was using fetch, but if you are thinking of XHR then think that withCredentials is True).
I have read a lot of docs and that says the request gets fail if you use credentials include but actually the request goes but the response fails.
So yes the attacker won't be able to receive the response but will be able to make the request. What attacker can do from this? The attacker can do one-click operations for which he doesn't need the response like updating the profile, deleting the account.
You will see in the console log where it says the request failed, like this:
POST http://example.com/login.php net::ERR_FAILED
But actually again response fails, request gets succeeds.
Steps to reproduce:
- Create an app which has functionality to update the profile
- The server should have these header set:
- Access-Control-Allow-Origin: *
- Access-Control-Allow-Credentials: true
-
Now as an attacker create a page with this content and host in your server
<script>
fetch('http://exmple.com/login.php', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'email=abc@gmail.com'
})
.then(response => response.text())
.then(result => {
console.log('Success:', result);
});
</script> -
Now if the victim visits the attacker page his profile will get changed.
Actual results:
Request going without any blockage and header checking
Expected results:
The request should get blocked because the client should not able to make the request with credentials include if the server had set is header to Access-Control-Allow-Origin: *
| Reporter | ||
Comment 1•5 years ago
|
||
It can be seen that the request should fail, check in the documentation:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS, in the section, "Credentialed requests and wildcards"
The request would fail if the value of the Access-Control-Allow-Origin header was "*". But it does not fail: Because the value of the Access-Control-Allow-Origin header is "http://foo.example" (an actual origin) rather than the "*" wildcard, the credential-cognizant content is returned to the invoking web content.
But actually request is not failing, it is successfully going but the response fails but the failing response does not matter for one-click operations.
Comment 2•5 years ago
|
||
(In reply to Tarunkant Gupta from comment #0)
The request should get blocked because the client should not able to make the request with credentials include if the server had set is header to
Access-Control-Allow-Origin: *
How do you propose the browser should not make the request, and yet still know what response headers were going to be present if the request were made?
You appear to misunderstand how CORS works. For GET, HEAD and POST requests with some content types for the submitted content in the case of POST, the request will always be made. They are "simple requests" and do not get a preflight request. Without the preflight request, there is no way to know whether credentials will be allowed. The documentation is explicit about this:
Since this is a simple GET request, it is not preflighted, but the browser will reject any response that does not have the Access-Control-Allow-Credentials: true header, and not make the response available to the invoking web content.
This is exactly the behaviour you're seeing.
Even without all this, a similar request could be made by e.g. creating an iframe with a <form> and calling .submit() on the form: the caller would not have access to the response, but the request would be made (even without the relevant CORS headers!). If the request being made is problematic then you should secure your web application against this kind of thing by e.g. using CSRF tokens, checking Origin and/or Referer headers, and other well-documented techniques (this is not a complete list; you're posting on a bug tracker, not a help forum).
| Reporter | ||
Comment 3•5 years ago
|
||
(In reply to :Gijs (he/him) from comment #2)
Since this is a simple GET request, it is not preflighted, but the browser will reject any response that does not have the Access-Control-Allow-Credentials: true header, and not make the response available to the invoking web content.
Just a question, I am using POST request in my PoC, not a GET request. And it seems GET requests are used for identifying the response headers.
It can be seen that the request should fail, check in the documentation:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS, in the section, "Credentialed requests and wildcards"
The request would fail if the value of the Access-Control-Allow-Origin header was "*". But it does not fail: Because the value of the Access-Control-Allow-Origin header is "http://foo.example" (an actual origin) rather than the "*" wildcard, the credential-cognizant content is returned to the invoking web content.
But actually request is not failing, it is successfully going but the response fails but the failing response does not matter for one-click operations.
Anything on this?
| Reporter | ||
Comment 4•5 years ago
|
||
If you see this example of a preflight request from here https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests that also used the POST method.
Comment 5•5 years ago
|
||
But what you are sending is a simple request, not a preflighted request.
Description
•