Content Security Policy: What it is, and How to Test It

Content Security Policy: What it is, and How to Test It

Guest Blog by Hassan Mussana

Content Security Policy was introduced to protect from data injection attacks particularly XSS variants. As the web grew more sophisticated and reliant on JavaScript, hackers found increasingly complex ways to exploit the existing browser trust model, i.e. the Same-origin policy (SOP); XSS attacks bypassed the same origin policy by tricking a site into delivering malicious code along with the intended content. Content Security Policy is a declarative mechanism to whitelist sources of content (such as script sources, objects, images) in a web application. Using various directives in CSP, developers can define what content can run on the current site. For example, if JavaScript can be executed inline, or which domains js files can be loaded from.

Sites which want to implement CSP, send a special header value in the http responses with the name Content-Security-Policy. The Content-Security-Policy header value is made up of one or more directivesHere a few common scenarios for setting directives:
Allow everything but only from the same origin
default-src 'self';
Only Allow Scripts from the same origin
script-src 'self';
Allow Google Analytics, Google AJAX CDN and Same Origin
script-src 'self';

Setting up CSP on DVWA

Whether you want to check that CSP is working the way intended (e.g. blocking scripts or imgs from certain domains or loading them only from certain domains etc.) or just want to try bypassing it, it’s pretty straight forward. In this CSP walkthrough, we are going to use a test site DVWA (Damn Vulnerable Web Application) which has been deployed locally for this walkthrough.

DVWA is a vulnerable web application that many security researchers use to sharpen their skills of exploiting web application vulnerabilities. The reason for choosing DVWA for this walkthrough is not that it implemented the CSP (which in fact it doesn’t implement at all) but instead that we could actually see an XSS attack thwarted by CSP. Of course, for that, we must have an XSS vulnerability in an application; and DVWA is just perfect for that.

So I did a little tweak to include CSP header in all http responses from DVWA by including:
Header set Content-Security-Policy "default-src 'self'; script-src 'self';"
to the file: /etc/apache2/apache2.conf (Ubuntu with Apache)
Afterwards just restarted the apache server and there it is, in the response header.

Testing CSP using Chrome

So let’s start our testing! In the video (1) below, I tried to inject javascript both to trigger a Reflective XSS but initially got blocked by Chrome’s own security feature, the XSS-Auditor. So I disabled it by creating a shortcut and appending --args --disable-xss-auditor to the end of Target path of the shortcut and then relaunched Chrome.

After I have started chrome with XSS-Auditor disabled, I first try to inject javascript into the same page to trigger Reflective XSS. Notice that this time however, we don’t get blocked by the XSS-Auditor, instead we see a Hello which means that injection was successful but somehow the javascript still did not get executed. Why is it so? Didn’t we already disable XSS-Auditor? Yes we did, this is Content Security Policy in action. To make sure, I navigated to the XSS(Stored) page which loaded just fine. It already had stored injections which should have popped up alert boxes but didn’t. So I tried injecting javascript once more and it got successfully injected but still, no sign of an alert box.

This is the point where I turned on BugReplay, a tool that I almost always use during my pentesting activities to record whatever is happening within the open tab in my browser, as it records the application requests and responses as well as the visuals within the browser screen. So you can see at what point, which request took place, what was the response and which resource failed to load and the associated logs describing the reason of failure. No need to take screenshots along the way as I can use the same video as a PoC later on. After turning on BugReplay, I used another extension named Disable Content-Security-Policy which makes it easier to test a site for XSS which has CSP enabled. Enabling this extension disabled the chrome’s ability to process CSP header coming from the loaded site. Of course, all of this still being recorded by BugReplay so that we can later take a look at the requests and responses at point of times of our interest. So once the extension got enabled (and CSP header no longer understandable by Chrome), I reinjected the same javascript into the both the vulnerable pages (Reflective and Stored) and tada! We have our alert dialog appearing just fine now, the XSS vulnerability just got verified.

In the video above, as you can see, I am easily able to locate the errors while the injection is being done and no dialog is appearing, instead we can only see Hello. As mentioned earlier, I have used:
Content-Security-Policy "default-src 'self'; script-src 'self';"
So wherever our application tries to use a script which was either loaded in-line (in the case of stored XSS) or was not loaded from the server rather from the user input (in case of Reflective), the CSP policy told Chrome not to execute it, hence the errors are seen in the logs:
Refused to execute inline script because it violates the following Content Security Policy directive: script-src 'self'
But once chrome stops processing the CSP directives in http responses, we can observe the alert dialogs.

We can use Chrome’s developer tools to locate the issue too but it has its limitations. You’ll only be watching the live traffic as it is received by your browser. Tons of resources coming in and requests scroll going up and up, makes it difficult to locate issues in real time. And if you want to observe a resource again, you will have to load the page again to see the request and response, while with BugReplay, all it takes is one recording which can be played, stopped and repeated whenever necessary. Moreover, you don’t have to create a PoC separately so it saves your precious bug hunting time too.

Hope you guys liked it!


Popular posts from this blog

Name Your Poison

Pornhub Bypasses Ad Blockers With WebSockets

Gopher Success: The ins and outs of Golang