Using Content Security Policy to Prevent Cross-Site Scripting (XSS)

简介: On SendSafely.com we make heavy use of many new JavaScript APIs introduced with HTML5.

On SendSafely.com we make heavy use of many new JavaScript APIs introduced with HTML5. We encrypt files, calculate checksums and upload data using pure JavaScript.  Moving logic like this down to the browser, however, makes the threat of Cross-Site Scripting (XSS) even greater than before.  In order to prevent XSS vulnerabilities, our site makes liberal use of pretty aggressive client-side and server-side encoding APIs.  These APIs are based on the OWASP ESAPI library, so we have context-specific encoding methods for pretty much every scenario.   Even so, we recognize that it is very difficult to rule out all possible ways to inject code, including a human error on our part. For this reason we chose to also implement Content Security Policy (CSP) on SendSafely.com.

CSP is a new security mechanism supported by modern browsers. It aims to prevent XSS by white-listing URLs the browser can load and execute JavaScript from. The server can, by specifying specific CSP directives, prevent the browser from executing things like in-line JavaScript, eval(), setTimeout() or any JavaScript that comes from an untrusted URL. The policy works as a white list, only domains listed are allowed to execute, everything else will be blocked.

The Content Security Policy in SendSafely
In SendSafely.com, our Javascript files are all loaded from a dedicated host that doesn’t run any dynamic content (static.sendsafely.com). The exceptions to this are for certain third-party JavaScript APIs that we still load from an external domain, specifically Google Analytics and reCAPTCHA.  Text-to-JavaScript functions like eval() and setTimeout() are blocked across the board, even if the script is loaded from one of our white-listed hosts, as is any in-line JavaScript

Use of a strict CSP makes it significantly harder to inject executable JavaScript into application pages since the code must come from a trusted server.  The typical XSS attack using un-encoded output on one of our pages won’t work when the CSP is enforced.  In fact, any JavaScript embedded on our content pages (even JavaScript we put there) get blocked by the policy.  Pretty cool stuff.  

So you may be asking yourself, does this mean XSS is nothing but a memory? Sadly, this is not the case.  For starters, CSP is still fairly new and only supported by recent versions of Firefox, Safari and Chrome. Internet Explorer 10 (IE10) supports a subset of CSP options, but the ability to white list domains is unfortunately not one of them.  Aside from limited browser support, data dynamically loaded into the page from JavaScript is still potentially vulnerable. A strict content security policy should therefore not be considered the end-all solution to XSS . Think of CSP more like a safety belt, which is nice to have when your car crashes.

Dissecting our Policy
Now let’s take a look at the CSP policy we use on www.sendsafely.com and dissect it a bit.  One of the first things to note is that if you are going to implement CSP, you must realize that there are some browser compatibility nuances to deal with.   The main thing to note is that Safari uses ‘X-WebKit-CSP’ as the header name for implementing CSP, while other browsers have standardized on the ‘X-Content-Security-Policy’.  Another glitch that affects Safari is that a sever bug in the CSP implementation on Version 5.1 essentially blocks authorized content when a valid CSP is specified.  As a result, you’ll want to specifically detect when Safari is used and send either the ‘X-WebKit-CSP’ header or no header at all (if Version 5.1 is used).

To keep our policy as strict as possible, we use two different policies depending on what the page needs to do.  The stricter policy is used for all pages except the ones that handle encryption and decryption (the reason for this will be discussed in a separate follow up post).  For simplicity, the more strict policy will be explained here.

X-Content-Security-Policy: default-src ‘none’; connect-src ‘self’; script-src https://static.sendsafely.com https://www.google.com https://ssl.google-analytics.com; style-src ‘self’ ‘unsafe-inline’ http: https:; img-src ‘self’ https://www.google.com https://ssl.google-analytics.com; report-uri /csp-reports;

The header is divided into different sections that are each separated by a semi-colon. The “default-src” directive defines the security policy for all types of content which are not expressly called out by more specific directives.  We opted to set the default-src value to ‘none’, meaning that by default we allow nothing to load.  If we stopped defining directives here, the site would be completely broken, so now we need to open up the policy and allow specifically what we want to load.  

Now that we explicitly denied everything as the default, we need to add back the specific content policy options our site needs.  On SendSafely, we have a hand full of resource categories that we need to add policy settings for.  Each of these are outlined below, along with the CSP directives for each.

  • Ajax Requests - Several pages within our site use the browser’s XMLHttpRequest (XHR) object to make HTTP requests from within our JavaScript code.  In order for us to make these request’s we set the “connect-src” attribute to “self”, so scripts on our site can make XHR requests back the server but nowhere else. This attribute is another place where we run into compatibility issues across different browsers.  Specifically, FireFox decided to name this directive “xhr-src” instead of “connect-src”.  To account for this, our CSP code does some basic browser detection and if we detect that FireFox is being used, we change the directive name accordingly.  

  • JavaScript - As mentioned previously, we load all of our internal static JavaScript from a dedicated host (static.sendsafely.com). Additionally, we’ve chosen to load the Google Analytics and ReCaptcha JavaScript files from their origin domains on google.com.  Unfortunately the ability to allow just a sub-path of a host (like /scripts/) is not supported. Since ReCaptcha script files get loaded directly off of the main www.google.com site, our “script-src” directive includes https://static.sendsafely.com, https://www.google.com and https://ssl.google-analytics.com

    Having such a large site like www.google.com in our CSP whitelist is understandably something we are not thrilled about.  The ability to allow sub-paths of a host is slated to be introduced in CSP 1.1, however, but until then we’ll have to live with it.  The good news is that Google takes security very seriously, and they take great care to avoid script injection bugs on their website.
      
  • CSS - Our site design makes heavy use of in-line CSS for styling various UI attributes.  As such, the style-src directive includes a value of “self” (that allows us to load CSS files from the same host) and a value of “unsafe-inline”, meaning that we can use in-line CSS from within our HTML pages.  We recognize that by allowing in-line CSS within our pages, there is a minimal increased security risk since someone could potentially be mischievous if they found a way to inject markup into one of our pages.  Given the cost/benefit of refactoring the UI to completely avoid any in-line CSS, however, we decided this is a tolerable risk that we can live with.  

  • Images - Our img-src directive specifies both “self” and the two previously mentioned google hosts (https://www.google.com and https://ssl.google-analytics.com)  as the authorized origin hosts for all image content  For the most part, our site only loads images from the same host.  The exception to this is reCaptcha, however, since reCaptcha loads various images from www.google.com domain.  

  • The final part of our CSP header is the ‘report-uri’ directive.  This directive tells the browser to send us a report of pages that violate the Content Security Policy. The  violation reports consist of JSON documents sent via an HTTP POST request to the specified URI.  Using this option, we can monitor for events that trigger CSP exceptions and quickly take action if we think there may be a problem with our site.  The reports are also great to use during testing and development in order to debug CSP issues you might encounter.

Final Notes
A few final notes; CSP is a great tool to add an additional layer of protection against Cross-Site Scripting. If you’re building a new application, CSP should be considered as a solid defense in depth security control against the never-ending battle against cross-site scripting. Writing client-side code which is designed to use CSP will save precious developer cycles in the future, if code must be migrated to work with CSP.

Implementing CSP on our site proved to be a very interesting exercize.  We’ll provide more details on some other aspects of our Content Security Policy implementation in a follow up post here on our blog. 


目录
相关文章
|
JavaScript 安全 前端开发
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞(下)
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞
210 0
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞(下)
|
存储 JavaScript 安全
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞(中)
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞
200 0
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞(中)
|
存储 安全 JavaScript
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞(上)
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞
216 0
[PiKaChu靶场通关]Cross-Site Scripting XSS漏洞(上)
|
Web App开发 安全 Java
YEAR OF SECURITY FOR JAVA – WEEK 11 – X-XSS-PROTECTION
What is it and why should I care? X-XSS-Protection is a Microsoft IE technology used to help prevent reflected XSS attacks in IE.
1012 0
|
JavaScript 数据安全/隐私保护
【WebGoat笔记】--- Cross-Site Scripting(XSS)
  目标: 伪造一个登陆界面,要求用户输入用户名和密码,将数据提交到http://localhost/WebGoat/capture/PROPERTY=yes&ADD_CREDENTIALS_HERE   解决步骤: 首先:随意输入搜索内容,如:123. 打开源代码,检测是否有未关闭的标签。
1009 0
|
Web App开发 存储 安全
Cross-Site Scripting(XSS): 跨站脚本攻击介绍
一、XSS攻击简介          作为一种HTML注入攻击,XSS攻击的核心思想就是在HTML页面中注入恶意代码,而XSS采用的注入方式是非常巧妙的。         在XSS攻击中,一般有三个角色参与:攻击者、目标服务器、受害者的浏览器。
1208 0
|
2月前
|
JavaScript 安全 前端开发
js开发:请解释什么是XSS攻击和CSRF攻击,并说明如何防范这些攻击。
XSS和CSRF是两种常见的Web安全威胁。XSS攻击通过注入恶意脚本盗取用户信息或控制账户,防范措施包括输入验证、内容编码、HTTPOnly Cookie和CSP。CSRF攻击则诱使用户执行未经授权操作,防范手段有CSRF Tokens、双重验证、Referer检查和SameSite Cookie属性。开发者应采取这些防御措施并定期进行安全审计以增强应用安全性。
25 0
|
4月前
|
存储 JSON 前端开发
【面试题】XSS攻击是什么?
【面试题】XSS攻击是什么?
|
4月前
|
存储 开发框架 安全
如何处理预防XSS漏洞攻击问题
防止XSS攻击需要从多个方面入手,包括输入验证和过滤、输出编码、设置正确的HTTP头部、使用最新的安全框架和库、定期进行安全审计和漏洞扫描以及培训和意识提升等。只有综合运用这些措施,才能有效地防止XSS攻击,保护网站和用户的安全。
|
21天前
|
缓存 安全 JavaScript
前端安全:Vue应用中防范XSS和CSRF攻击
【4月更文挑战第23天】本文探讨了在Vue应用中防范XSS和CSRF攻击的重要性。XSS攻击通过注入恶意脚本威胁用户数据,而CSRF则利用用户身份发起非授权请求。防范措施包括:对输入内容转义、使用CSP、选择安全的库;采用Anti-CSRF令牌、同源策略和POST请求对抗CSRF;并实施代码审查、更新依赖及教育团队成员。通过这些实践,可提升Vue应用的安全性,抵御潜在攻击。