Blogs
Background
Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to site defacement, to malware distribution.
Who needed it?
Administrators who care about security.
What problem does it solve?
With a strict policy an added layer of security can be provided on the client side which protects against XSS and data injection attacks. The existence of the Content Security Policy header is often a security audit requirement as well.
How can it be used by the user or developer?
The users will receive the Content Security Policy response header on each HTTP request which will be interpreted and enforced by their browsers.
Features
Our Content Security Policy implementation does two things right now:
-
Adds
Content-Security-Policy
HTTP header to each response. The value of this header can be configured by Administrators. -
Adds a random generated nonce value to each link, script and style tags according to the configured
Content-Security-Policy
HTTP header. The nonce value is freshly generated on each request and its value can be used in the policy.
Steps
Go to “System/Instance/Site Settings > Security > Content Security Policy”. Here the Administrators can enable or disable this feature, specify the policy and add URI paths which they want to be excluded from Content Security Policy modifications.
In the Content Security Policy field if the user writes
[$NONCE$]
it will be replaced by the generated value on
each request.
Right now CSP works best with single-page-applications (a.k.a
SPA) disabled which can be done by adding
javascript.single.page.application.enabled=false
to
portal-ext.properties.
With SPA disabled, for example, the following policy can be
used: default-src 'self'; base-uri 'self' 'strict-dynamic';
connect-src 'self'; img-src data: 'self' w3.org/svg/2000; script-src
'self' 'strict-dynamic' '[$NONCE$]' 'unsafe-eval'; script-src-attr
'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';
Code
All relevant code is under “modules > apps > portal-security > portal-security-content-security-policy” package.
-
ContentSecurityPolicyConfiguration.java
: Configuration class for the module. -
ContentSecurityPolicyConstants.java
: CSP related constants are stored here. -
ContentSecurityPolicyFilter.java
: This class does the main functionality. It’s a Servlet Filter that adds the Content-Security-Policy header to the response and intercepts the response body and rewrites all link, script and style tag to contain a nonce.
Limitations
Due to webpack bundling settings liferay.js
has the
following line Function(\"return this\")()
which won’t work because Refused to evaluate a string as
JavaScript
unless we add 'unsafe-eval'
to our
policy.
How to remove eval and Function constructor from webpack
build to avoid CSP issues · Issue #6461 · webpack/webpack
We have a lot of style
attributes inside HTML
elements as well as some style additions to head part by scripts.
For this reason we need to enable 'unsafe-inline'
for styles.
Sometimes we use inline event listeners which are treated as
scripts from Content Security Policy point of view so to overcome this
we need to add script-src-attr 'self' 'unsafe-inline'
; to
our policy.
CKEditor is causing issues with the provided CSP rule but only
on pages which would use it. Either the rule can be changed to
script-src ‘self' 'unsafe-inline' 'unsafe-eval'
; or add
/group/guest/~/control_panel/manage
as an excluded path
but by default we wouldn’t recommend any of them. Since 7.3 CKEditor
is the only supported WYSIWYG editor but Liferay is using CKEditor 4
which cannot be used without unsafe-inline (https://csplite.com/csp/test347/#nonce_dynamic).
Important notes
Site level configuration panel and common pages (such as 404 page) belong to the instance so an instance level CSP header will be used.
If you remove exclusion of /combo
from config you
can specify a stricter CSP such as: default-src 'self';
base-uri 'self' 'strict-dynamic'; connect-src 'self'; img-src
data: 'self' w3.org/svg/2000; script-src 'self' 'strict-dynamic'
'[$NONCE$]' 'unsafe-eval'; script-src-attr 'self'
'unsafe-inline'; style-src 'self' 'strict-dynamic' '[$NONCE$]';
style-src-attr 'self' 'unsafe-inline'
; however bear in mind
resources at /combo
belong to the instance so instance
CSP config values will be used.
Future plans
This update is only the first part of the CSP implementation, we are going to work on the next components in the near future:
-
Unsafe inline
-
Unsafe hashes
-
Unsafe expressions
-
Managing the
Content-Security-Policy-Report-Only
header with configuration