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. ContentSecurity 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 jsfiles 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 ismade up of one or more directives. Here 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' www.google-analytics.com ajax.googleapis.com;
Whether you want to check that CSP is working the way intended (e.g. blocking scripts or imgs from certain domains or loading themonly from certain domains etc.) or just want to try bypassing it, it’s prettystraight forward. In this CSP walkthrough, we are going to use a test site DVWA(Damn Vulnerable Web Application) which has been deployed locally for thiswalkthrough.
DVWA is a vulnerable web application that many security researchers use to sharpen their skills of exploiting web application vulnerabilities. Thereason for choosing DVWA for this walkthrough is not that it implemented theCSP (which in fact it doesn’t implement at all) but instead that we couldactually see an XSS attack thwarted by CSP. Of course, for that, we must havean 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 (Ubuntuwith Apache)
Afterwards just restarted the apache server and there it is, in the response header.
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 blockedby Chrome’s own security feature, the XSS-Auditor.So I disabled it by creating a shortcut and appending --args --disable-xss-auditorto the end of Target path of the shortcut and thenrelaunched 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, insteadwe see a Hello which means that injection wassuccessful 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 SecurityPolicy 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 triedinjecting javascript once more and it got successfully injected but still, nosign of an alert box.
This is the point where I turned on Bug Replay, a tool that I almost always use during my pen testing 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 visualswithin the browser screen. So you can see at what point, which request tookplace, what was the response and which resource failed to load and the associatedlogs describing the reason of failure. No need to take screenshots along theway as I can use the same video as a PoC later on. After turning on BugReplay, Iused another extension named Disable Content-Security-Policy which makes it easier to test a site for XSS which has CSP enabled. Enabling thisextension disabled the chrome’s ability to process CSP header coming from theloaded site. Of course, all of this still being recorded by BugReplay so thatwe can later take a look at the requests and responses at point of times of ourinterest. So once the extension got enabled (and CSP header no longerunderstandable by Chrome), I reinjected the same javascript into the both thevulnerable pages (Reflective and Stored) and tada! We have our alert dialog appearingjust 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 mentionedearlier, 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 theuser input (in case of Reflective), the CSP policy told Chrome not to executeit, 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 oncechrome 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 itdifficult to locate issues in real time. And if you want to observe a resourceagain, 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 aPoC separately so it saves your precious bug hunting time too.
Hope you guys liked it!