GnuDeveloper.com

Secure Coding Guidelines for Content Security Policy

The CSP is the key concept for protecting the Cross-site scripting (XSS) from the browser side. Since XSS is the top most vulenerable injection attack. The content means the web page resource as javascript, images etc.. For browser side security we need to understand the same-origin policy, cross- origin policy (COP).In Firefox the Script Security Manager(nsScriptSecurityManager.cpp) will do the Security Checks for each statement execution if no violation then statement will be executed else it will be report in console

Why we need Content Security Policy:

The Server needs to clearly mention the trusted origin for the resources like javascript,images etc.. so that client will take the action accordingly. Since The browser(client) and server are disconnected the server needs to mention the security policy for each page as part of HTTP header response

Secure coding guidelines for CSP:

1. Always use JavaScript in separate js file.
2. Always use javascript for binding the HTML elements with Event Handlers( like onclick) so that clear separation of HTML & JavaScript can be maintained. Javascript MVC framework like jQuery supports this feature .
example for button click event in jquery : $("#btnClick").click(function() { }
3. If legacy project already had inline JavaScript add script nonce with it, but browser compatibility issue will come since chrome wont support nonce.
4. Avoid use eval statement in JavaScript code.
5. Avoid using setTimeout methods since it internally the eval statement for its parameter.
6. Always have separate css file means don't use inline styles.

Same- origin policy (SOP):

The browser will decide the same -origin policy based on 3 parts of
URL
http://www.gnudeveloper.com:80/
Protocol: HTTP
Domain name: www.gnudeveloper.com
Port number: 80
Based on the URL information browser will consider the web page belongs to same- origin policy or cross-origin policy
Self: it represents same-origin policy
   script-src 'self'  ;

Cross- origin policy (COP) or Cross-Origin Resource Sharing (CORS):

It represents content belongs to different origin, opposed to same-origin policy. By default Firefox browser won't allow cross-origin policy for the web pages since it will create chance for Cross-site scripting (XSS). To allow all host specify as asterisk character *
   script-src *  ;

The CSP Violation message can be viewed in the console.

self DIRECTIVE value  enforce the source domain(gnudeveloper.com) and image src,script src should be same hence error message as below 
 
Content Security Policy: The page's settings blocked the loading of a resource at infotree.in/themes/bartik/logo.png ("img-src gnudeveloper.com").
Content Security Policy: The page's settings blocked the loading of a resource at code.jquery.com/jquery-1.9.1.js ("script-src gnudeveloper.com 'unsafe-inline'").

Since eval-script is missing http header response, browser blocked the eval method 
call to eval() or related function blocked by CSP
Note: setTimeout will be allowed since it is indirect eval statement


The Firefox default settings as below

	default-src *; script-src 'self'; object-src 'none'; style-src 'self'	'unsafe-inline'

Output: HTTP header Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Security-Policy: default-src 'none'; options inline-script eval-script; xhr-src 'self'; 
object-src 'self'; style-src 'self'; img-src 'self'; form-action 'self'; connect-src 'self'; 
plugin-types application/pdf application/x-shockwave-flash; reflected-xss block; frame-src 'self'; 
sandbox;frame-ancestors 'self';script-src 'self' 'unsafe-eval'  'nonce-02ba6e3d2d02a67a4babf4f63cac0ca17914aa91'
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 924
Date: Sun, 08 Nov 2015 01:32:04 GMT

ContentSecurityPolicyFilter.java
package com.gnudeveloper.CSP;
 
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.commons.codec.binary.Hex;
 
@WebFilter("/*")  
public class ContentSecurityPolicyFilter implements Filter {
 
	String selfOriginRef = "'self'";
 
	/** Configuration member to specify if web app use web fonts */
	public static final boolean APP_USE_WEBFONTS = false;
 
	/** Configuration member to specify if web app use videos or audios */
	public static final boolean APP_USE_AUDIOS_OR_VIDEOS = false;
 
	/**
	 * Configuration member to specify if filter must add CSP directive used by
	 * Mozilla (Firefox)
	 */
	public static final boolean INCLUDE_MOZILLA_CSP_DIRECTIVES = true;
 
	/** Filter configuration */
	@SuppressWarnings("unused")
	private FilterConfig filterConfig = null;
 
	/** List CSP HTTP Headers */
	private List<String> cspHeaders = new ArrayList<String>();
 
	/** Collection of CSP polcies that will be applied */
	private String policies = null;
 
	/** Used for Script Nonce */
	private SecureRandom prng = null;
 
	/**
	 * Used to prepare (one time for all) set of CSP policies that will be
	 * applied on each HTTP response.
	 * 
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	@Override
	public void init(FilterConfig fConfig) throws ServletException {
		// Get filter configuration
		this.filterConfig = fConfig;
 
		// Init secure random
		try {
			this.prng = SecureRandom.getInstance("SHA1PRNG");
		} catch (NoSuchAlgorithmException e) {
			throw new ServletException(e);
		}
 
		// Define list of CSP HTTP Headers
		this.cspHeaders.add("Content-Security-Policy");
 
		// Define CSP policies
		// Loading policies for Frame and Sandboxing will be dynamically defined
		// : We need to know if context use Frame
		List<String> cspPolicies = new ArrayList<String>();
 
		// --Disable default source in order to avoid browser fallback loading
		// using 'default-src' locations
		cspPolicies.add("default-src 'none'");
		// --Define loading policies for Scripts
 
		if (INCLUDE_MOZILLA_CSP_DIRECTIVES) {
			cspPolicies.add("options inline-script eval-script");
			cspPolicies.add("xhr-src 'self'");
		}
		// --Define loading policies for Plugins
		cspPolicies.add("object-src " + selfOriginRef);
		// --Define loading policies for Styles (CSS)
		cspPolicies.add("style-src " + selfOriginRef);
		// --Define loading policies for Images
		cspPolicies.add("img-src " + selfOriginRef);
		// --Define loading policies for Form
		cspPolicies.add("form-action " + selfOriginRef);
		// --Define loading policies for Audios/Videos
		if (APP_USE_AUDIOS_OR_VIDEOS) {
			cspPolicies.add("media-src " + selfOriginRef);
		}
		// --Define loading policies for Fonts
		if (APP_USE_WEBFONTS) {
			cspPolicies.add("font-src " + selfOriginRef);
		}
		// --Define loading policies for Connection
		cspPolicies.add("connect-src " + selfOriginRef);
		// --Define loading policies for Plugins Types
		cspPolicies
				.add("plugin-types application/pdf application/x-shockwave-flash");
		// --Define browser XSS filtering feature running mode
		cspPolicies.add("reflected-xss block");
 
		// Target formating
		this.policies = cspPolicies.toString().replaceAll("(\\[|\\])", "")
				.replaceAll(",", ";").trim();
	}
 
	/**
	 * Add CSP policies on each HTTP response.
	 * 
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
	 *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain fchain) throws IOException, ServletException {
		HttpServletRequest httpRequest = ((HttpServletRequest) request);
		HttpServletResponse httpResponse = ((HttpServletResponse) response);
 
		/* Step 1 : Detect if target resource is a Frame */
		// Customize here according to your context...
		boolean isFrame = true;
 
		/* Step 2 : Add CSP policies to HTTP response */
		StringBuilder policiesBuffer = new StringBuilder(this.policies);
 
		// If resource is a frame add Frame/Sandbox CSP policy
		if (isFrame) {
			// Frame + Sandbox : Here sandbox allow nothing, customize sandbox
			// options depending on your app....
			policiesBuffer.append(";").append("frame-src 'self';sandbox");
			if (INCLUDE_MOZILLA_CSP_DIRECTIVES) {
				policiesBuffer.append(";").append("frame-ancestors 'self'");
			}
		}
 
		// Add Script Nonce CSP Policy
		// --Generate a random number
		String randomNum = new Integer(this.prng.nextInt()).toString();
		// --Get its digest
		MessageDigest sha;
		try {
			sha = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			throw new ServletException(e);
		}
		byte[] digest = sha.digest(randomNum.getBytes());
		// --Encode it into HEXA
		String scriptNonce = Hex.encodeHexString(digest);
		policiesBuffer.append(";").append("script-src ").append(selfOriginRef)
				.append(" 'unsafe-eval'").append(" 'nonce-")
				.append(scriptNonce).append("'");
 
		// --Made available script nonce in view app layer
		httpRequest.setAttribute("CSP_SCRIPT_NONCE", scriptNonce);
 
		// Add policies to all HTTP headers
		for (String header : this.cspHeaders) {
			httpResponse.setHeader(header, policiesBuffer.toString());
		}
 
		/* Step 3 : Let request continue chain filter */
		fchain.doFilter(request, response);
	}
 
	/**
	 * {@inheritDoc}
	 * 
	 * @see javax.servlet.Filter#destroy()
	 */
	@Override
	public void destroy() {
		// Not used
	}
}

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 
<meta http-equiv="Content-Security-Policy"
	content="script-nonce noncynonce;">
 
<title>Content Security Policy</title>
<!-- 
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
 -->
<script src="js/jquery-1.9.1.js"></script>
<script src="js/homepage.js"></script>
 
</head>
<body>
 
	<script nonce='<%=request.getAttribute("CSP_SCRIPT_NONCE")%>'>
		alert("This is inline js with nonce attribute. Free from XSS attack"); 
	</script> 
 
	<script> 
		alert("This is inline js, XSS vulnerable is possible");
	</script>
 
 
	This is Content Security Policy Examples
	<br>
 
	<form method="post" action="index.jsp">
 
		Username: <input type="text" name="txt_username" id="txt_username">
 
		<input type="button" id="btn_submit" value="Submit">
 
	</form>
 
</body>

Downloads
Groups: