Documentation Index
Fetch the complete documentation index at: https://mintlify.com/digininja/DVWA/llms.txt
Use this file to discover all available pages before exploring further.
Content Security Policy (CSP) Bypass
Overview
Content Security Policy (CSP) is a browser security mechanism used to define where scripts and other resources can be loaded or executed from. This module demonstrates common implementation mistakes that allow attackers to bypass CSP protections.
Important: The vulnerabilities demonstrated here are not flaws in CSP itself, but rather mistakes in how developers implement the policy.
Objective
Bypass Content Security Policy protections and execute JavaScript in the page across different security levels.
Security Levels
Low Level
Vulnerable Code
The low level uses a permissive CSP that allows scripts from multiple external domains:
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com www.toptal.com example.com code.jquery.com https://ssl.google-analytics.com unpkg.com cdn.jsdelivr.net digi.ninja ;";
header($headerCSP);
if (isset ($_POST['include'])) {
$page['body'] .= "
<script src='" . $_POST['include'] . "'></script>
";
}
```bash
**Location**: `vulnerabilities/csp/source/low.php:3-16`
#### Exploitation
Examine the CSP policy to identify allowed script sources. The policy permits scripts from several third-party domains, creating multiple bypass opportunities:
**Working Bypass URLs**:
- `https://cdn.jsdelivr.net/gh/digininja/csp_bypass/alert.js` - Using jsDelivr to serve JavaScript from GitHub
- `https://unpkg.com/@digininja/csp_bypass@1.0.0/index.js` - Using UNPKG to access NPM package files
- `https://digi.ninja/dvwa/alert.js` - Direct JavaScript file with correct headers
- `https://digi.ninja/dvwa/cookie.js` - Displays cookies
**Blocked URLs** (for learning purposes):
- `https://digi.ninja/dvwa/alert.txt` - Wrong content type due to file extension
- `https://digi.ninja/dvwa/forced_download.js` - Server sets `Content-Disposition: attachment` header
- `https://digi.ninja/dvwa/wrong_content_type.js` - Server forces `plain/text` content type
#### Key Vulnerability
Allowing too many external script sources creates an attack surface. Services like UNPKG and jsDelivr are designed to serve raw files without restrictive headers, making them ideal for CSP bypass.
---
### Medium Level
#### Vulnerable Code
The medium level attempts to use a nonce to prevent inline script injection:
```php
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';
header($headerCSP);
// Disable XSS protections so that inline alert boxes will work
header ("X-XSS-Protection: 0");
if (isset ($_POST['include'])) {
$page['body'] .= "
" . $_POST['include'] . "
";
}
Location: vulnerabilities/csp/source/medium.php:3-18
Exploitation
The implementation makes critical mistakes:
- Static Nonce: The nonce value
TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA= never changes
- unsafe-inline allowed: This directive defeats the purpose of using a nonce
- Direct output: User input is directly included in the page
Exploit:
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
```bash
Since the nonce is static and predictable, attackers can include it in their malicious scripts.
#### Key Vulnerability
Nonces must be cryptographically random and unique for each request. A static nonce provides no security benefit.
---
### High Level
#### Vulnerable Code
The high level uses a strict CSP with only `'self'` allowed, but makes a JSONP call:
```php
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
if (isset ($_POST['include'])) {
$page['body'] .= "
" . $_POST['include'] . "
";
}
$page['body'] .= '
<form name="csp" method="POST">
<p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
<script src="source/high.js"></script>
';
Location: vulnerabilities/csp/source/high.php:2-21
Exploitation
The page loads source/high.js which makes a JSONP call to jsonp.php with a callback parameter. Since JSONP responses are executed as JavaScript, you can:
- Modify
source/jsonp.php to return malicious code instead of the expected callback
- The code will execute because it comes from the same origin (
'self')
Attack Vector: JSONP endpoints on the same domain can be abused to bypass strict CSP policies.
Key Vulnerability
JSONP is inherently incompatible with strict CSP because it requires dynamic code execution. Any JSONP endpoint becomes a potential CSP bypass.
Impossible Level
Secure Code
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
$page['body'] .= '
<form name="csp" method="POST">
<p>Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.</p>
<p>The CSP settings only allow external JavaScript on the local server and no inline code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
<script src="source/impossible.js"></script>
';
```bash
**Location**: `vulnerabilities/csp/source/impossible.php:2-22`
#### Protection Mechanisms
1. **Strict CSP**: Only allows scripts from `'self'`
2. **No dynamic callbacks**: The JSONP function name is hardcoded, not user-controlled
3. **No inline scripts**: All JavaScript must come from external files on the same origin
---
## CSP Headers Reference
### Common CSP Directives
| Directive | Purpose |
|-----------|--------|
| `script-src 'self'` | Only allow scripts from the same origin |
| `script-src 'unsafe-inline'` | Allow inline `<script>` tags (insecure) |
| `script-src 'nonce-{random}'` | Allow scripts with matching nonce attribute |
| `script-src https://cdn.example.com` | Allow scripts from specific domain |
### Real-World CSP Example
```http
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random}';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' data:;
Best Practices
Do NOT:
- Use static nonces
- Allow
'unsafe-inline' with nonces
- Whitelist CDNs that serve arbitrary user content (UNPKG, jsDelivr)
- Implement JSONP with user-controlled callbacks under strict CSP
DO:
- Generate cryptographically random nonces for each request
- Use
'strict-dynamic' for modern browsers
- Minimize external script sources
- Use subresource integrity (SRI) for third-party scripts
- Implement CSP in report-only mode first, then enforce
References
Module developed by Digininja