CSP is an extremely powerful tool for mitigating Cross-site Scripting (XSS) vulerabilities. The main challenge that organizations run into is that actual site-wide implementation is a daunting task. As the image on the right indicates, implementing CSP site-wide is a bit like eating an elephant. Where do you start? In this blog post, I will highlight how to use ModSecurity WAF to virtually patch identified XSS vulnerabilities by enforcing targeted CSP policies.
The biggest challenge associated with developing proper CSP policies for resources is the need to remove all inline JS code from the HTML page. When presenting this task to the developers, they might not be that receptive...
Security Reactions: You want to deploy CSP Site-wide?!?!?
In order to implement CSP, there many steps that must be completed (List developed by Colin Watson) -
These are excellent steps to follow. The problem is that this all takes a large investment of time/resouces to complete. Let's focus in on the bolded first item.
What resource(s) should you choose to first implement CSP? How about those resources that have been confirmed to be vulnerable to XSS through some type of penetration test or assessment? Prioritizing these resources has the dual advantage of making CSP deployment consumable and reducing risk for a known vulnerability.
NOTE - although xssed.com lists the vulnerability on the pastebin. mozilla.com as "UNFIXED" it is in fact fixed.
When this page was vulnerable, the issue was that the "goprivate" QUERY_STRING data was populated into a FORM field without proper output encoding/escaping:
Here is the actual HTML with the XSS payload:
The JS code at yourjavascript.com will then over-write DOM elements -
The end result is that the webpage appears to be defaced:
We will now discuss how to mitigate this particular vulnerability using ModSecurity WAF to add CSP policies for this page.
You must review the current construction of the page to see if/when/where/how code is being used within the page. A great tool to aid in this effort is call CSP Bookmarklet by Brandon Sterne. Essentially, you create a bookmark with the supplied code and then when are viewing the webpage of interest, you just click on the bookmarklet. It will then analyze the page elements and issue a JS alert popup box where it will provide a recommended initial CSP policy, as well as, notify you of any current violations.
As you can see from CSP bookmarlet popup, there is a recommended policy as well as an alert for an Inline Script Violation.
When you encounter inline JS code violations, this is when you should consult with the proper Developer to assist with the process of externalizing this code. In this case, the CSP alert identified the "initPastebin()" function call -
This "onload" event is not allowed per CSP and mut be externalized. One method to do this would be to add an "id" element to the <body> block to reference the initPastebin() call. Then in the pastebin.js file, you could add code similar to the following that would still initate the proper function call when the DOM page loads:
// Add event listeners once the DOM has fully loaded by listening for the// `DOMContentLoaded` event on the document, and adding your listeners to// specific elements when it triggers.document.addEventListener('DOMContentLoaded', function () { initPastebin();});
This is there the virtual patching comes in :) You can implement ModSecurity rules to dynamically add in proper CSP enforcement for this resource. The current CSP spec 1.1 allows the use of the "meta" HTML block to add CSP data. With this capability, we could use the following ModSecurity rule which will modify the outbound HTML using the @rsub operator to inject our CSP policy data.
SecContentInjection OnSecStreamOutBodyInspection OnSecRule REQUEST_FILENAME "@streq /" "chain,phase:request,t:none,nolog,pass" SecRule &ARGS "@eg 1" "chain" SecRule STREAM_OUTPUT_BODY "@rsub s/<head>/<head>|00|<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'self'; script-src http:\/\/pastebin.mozilla.org\/; style-src http:\/\/pastebin.mozilla.org\/; report-uri http:\/\/www.modsecurity.org/csp_violation_report\"<\/>/"
The resulting HTML would look like this -
It is also possible to have ModSecurity set Apache environmental variables and conditionally set HTTP Response headers for the CSP policy as well. This may be necessary if you are using older browsers.
This CSP policy would then instruct Chrome browser to block the XSS payload as we are disallowing inline JS. In the Developer console in Chrome, this event would be generated -
One of the features I like best about using CSP enforcement is that you are able to gain insight into violations by using the report-uri directive. Here is a screenshot of the violation report sent from the browser:
In this case, we can alert ModSecurity when a violation occurs by adding the following rule:
## Check the REQUEST_BODY for CSP Violation Report data and generate an Alert#SecRule REQUEST_BODY "({\"csp-report\":{\"document-uri\":\"(.*?)\".*?violated-directive\":\"(.*?)\".*?blocked-uri\":\"(.*?)\")" "chain,phase:2,id:'960001',capture,t:none,log,pass,msg:'Content Security Policy (CSP) Violation for Vulnerable Resource',logdata:'blocked-uri:%{tx.4} violated-directive:%{tx.3}',tag:'OWASP_AppSensor/RP3',tag:'https://www.owasp.org/index.php/AppSensor_DetectionPoints#RP3:_Suspicious_Client-Side_Behavior'" SecRule TX:2 "@streq file://localhost/Users/rbarnett%201/Desktop/XSS%20Defacement%20By%20Atm0n3r.html"
This rule inspects the CSP JSON body content of the request and parses out important data. It then checks to the document-uri element to see if it was our vulnerable resource. If it was, it generates this alert message:
[Mon Jul 15 16:23:57 2013] [error] [client 72.192.214.223] ModSecurity: Warning. String match "file://localhost/Users/rbarnett%201/Desktop/XSS%20Defacement%20By%20Atm0n3r.html" at TX:2. [file "/etc/httpd/modsecurity.d/crs/base_rules/modsecurity_crs_42_csp_enforcement.conf"] [line "33"] [id "960001"] [msg "Content Security Policy (CSP) Violation for Vulnerable Resource"] [data "blocked-uri:http://yourjavascript.com violated-directive:script-src http://pastebin.mozilla.org/"] [tag "OWASP_AppSensor/RP3"] [tag "https://www.owasp.org/index.php/AppSensor_DetectionPoints#RP3:_Suspicious_Client-Side_Behavior"] [hostname "www.modsecurity.org"] [uri "/csp_violation_report"] [unique_id "enUZ5cCo8AoAACw8BQ8AAAAP"]
Hopefully this blog post has provided a pragmatic approach for implementing CSP within your site. By focusing and prioritizing resources that have been identified as vulnerable to XSS, it allows your organization to take a smaller tactical approach vs. the enormous task of site-wide CSP development.
I wanted to thank two people with whom I discussed this CSP use-case and content: