You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by pa...@apache.org on 2020/02/21 13:38:30 UTC

[wicket] branch master updated: WICKET-6747: add documentation for CSP

This is an automated email from the ASF dual-hosted git repository.

papegaaij pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/master by this push:
     new 2686ee7  WICKET-6747: add documentation for CSP
2686ee7 is described below

commit 2686ee7b3657becb7ac5a1a202d78ff4f420ae4a
Author: Emond Papegaaij <em...@topicus.nl>
AuthorDate: Fri Feb 21 14:37:57 2020 +0100

    WICKET-6747: add documentation for CSP
---
 .../src/main/asciidoc/introduction.adoc            |   7 +-
 .../src/main/asciidoc/security/security_4_1.adoc   |  21 ----
 .../src/main/asciidoc/security/security_5.adoc     |  49 +++------
 .../src/main/asciidoc/security/security_6.adoc     | 117 +++++++++++++++------
 .../src/main/asciidoc/security/security_7.adoc     |  49 +++++++--
 .../security/{security_6.adoc => security_8.adoc}  |   0
 .../security/{security_7.adoc => security_9.adoc}  |   0
 wicket-user-guide/src/main/asciidoc/single.adoc    |  12 ++-
 8 files changed, 150 insertions(+), 105 deletions(-)

diff --git a/wicket-user-guide/src/main/asciidoc/introduction.adoc b/wicket-user-guide/src/main/asciidoc/introduction.adoc
index 8a5b29e..64a73d2 100644
--- a/wicket-user-guide/src/main/asciidoc/introduction.adoc
+++ b/wicket-user-guide/src/main/asciidoc/introduction.adoc
@@ -23,11 +23,12 @@ Editors: +
 *Christian Kroemer* +
 *Daniel Bartl* +
 *Paul Borș* +
-*Joachim Rohde*
+*Joachim Rohde* +
+*Emond Papegaaij*
 
 
-*PS*: this guide is based on Wicket 8. However if you are using an older version you should find this guide useful as well, but it's likely that the code and the snippets won't work with your version. +
-*PPS*: although I've tried to do my best working on this tutorial, this document is a work in progress and may contain errors and/or omissions. That's why any feedback of any kind is REALLY appreciated!
+*PS*: this guide is based on Wicket 9. However if you are using an older version you should find this guide useful as well, but it's likely that the code and the snippets won't work with your version. +
+*PPS*: although we try to do our best working on this guide, this document is a work in progress and may contain errors and/or omissions. That's why any feedback of any kind is REALLY appreciated!
 
 Project started by 
 
diff --git a/wicket-user-guide/src/main/asciidoc/security/security_4_1.adoc b/wicket-user-guide/src/main/asciidoc/security/security_4_1.adoc
deleted file mode 100644
index 52707b8..0000000
--- a/wicket-user-guide/src/main/asciidoc/security/security_4_1.adoc
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-_CryptoMapper_ helps preventing CSRF attacks by making the urls impossible to be guessed by an attacker but still there is some theoretical chance this to happen.
-
-To further help against this kind of vulnerability Wicket provides _CsrfPreventionRequestCycleListener_ - a _IRequestCycleListener_ that forbids requests made from a different origin. By default only actions are forbidden, i.e. a request coming from different origin cannot execute _Link.onClick()_ or submit forms (_Form.onSubmit()_). Any request to render pages are still allowed so Wicket pages could be easily embedded in other applications.
-
-MyApplication.java
-[source,java]
-----
-  @Override
- protected void init() {
-  super.init();
-  getRequestCycleListeners().add(new CsrfPreventionRequestCycleListener());
-  // ...
- }
-----
-
-_CsrfPreventionRequestCycleListener_ is highly configurable. It allows to define a whitelist of allowed origins via _addAcceptedOrigin(String acceptedOrigin)_, to enable/disable it dynamically by overriding _isEnabled()_, to define different kind of actions when a request is rejected or allowed, to set custom error message and code for the rejected requests.
-
-_CsrfPreventionRequestCycleListener_ is not an alternative to _CryptoMapper_! Both of them could be used separately or in tandem to prevent CSRF attacks depending on the application requirements.
-
diff --git a/wicket-user-guide/src/main/asciidoc/security/security_5.adoc b/wicket-user-guide/src/main/asciidoc/security/security_5.adoc
index 1026edf..52707b8 100644
--- a/wicket-user-guide/src/main/asciidoc/security/security_5.adoc
+++ b/wicket-user-guide/src/main/asciidoc/security/security_5.adoc
@@ -1,44 +1,21 @@
 
 
+_CryptoMapper_ helps preventing CSRF attacks by making the urls impossible to be guessed by an attacker but still there is some theoretical chance this to happen.
 
-Wicket internally uses an entity called package resource guard to protect package resources from external access. This entity is an implementation of interface _org.apache.wicket.markup.html.IPackageResourceGuard_. 
-
-By default Wicket applications use as package resource guard class _SecurePackageResourceGuard_, which allows to access only to the following file extensions (grouped by type):
-
-|===
-|File | Extensions
-|*JavaScript files* |.js
-|*CSS files* |.css
-|*HTML pages* |.html
-|*Textual files* |.txt
-|*Flash files* |.swf
-|*Picture files* |.png, .jpg, .jpeg, .gif, .ico, .cur, .bmp, .svg
-|*Web font files* |.eot, .ttf, .woff
-|===
-
-To modify the set of allowed files formats we can add one or more patterns with method _addPattern(String)_. The rules to write a pattern are the following:
-
-* patterns start with either a "+" or a "-" In the first case the pattern will add one or more file to the set while starting a pattern with a “-” we exclude all the files matching the given pattern. For example pattern “-web.xml” excludes all web.xml files in all directories.
-* wildcard character “\*” is supported as placeholder for zero or more characters. For example  pattern “+\*.mp4” adds all the mp4 files inside all directories.
-* subdirectories are supported as well. For example pattern “+documents/\*.pdf” adds all pdf files under “documents” directory. Character “\*” can be used with directories to specify a nesting level. For example “+documents/\*/\*.pdf” adds all pdf files placed one level below “documents” directory.
-* a double wildcard character “\*\*” indicates zero or more subdirectories. For example pattern “+documents/\*\*/\*.pdf” adds all pdf files placed inside “documents” directory or inside any of its subdirectories.
-
-Patterns that allow to access to every file with a given extensions (such as “+\*.pdf”) should be always avoided in favour of more restrictive expressions that contain a directory structure:
+To further help against this kind of vulnerability Wicket provides _CsrfPreventionRequestCycleListener_ - a _IRequestCycleListener_ that forbids requests made from a different origin. By default only actions are forbidden, i.e. a request coming from different origin cannot execute _Link.onClick()_ or submit forms (_Form.onSubmit()_). Any request to render pages are still allowed so Wicket pages could be easily embedded in other applications.
 
+MyApplication.java
 [source,java]
 ----
-//Application class code...
-@Override
-public void init()   
-{
-      IPackageResourceGuard packageResourceGuard = application.getResourceSettings() 
-                                                   .getPackageResourceGuard();
-      if (packageResourceGuard instanceof SecurePackageResourceGuard)
-      {
-         SecurePackageResourceGuard guard = (SecurePackageResourceGuard) packageResourceGuard;
-         //Allow to access only to pdf files placed in the “public” directory.
-         guard.addPattern("+public/*.pdf");
-      }
-}
+  @Override
+ protected void init() {
+  super.init();
+  getRequestCycleListeners().add(new CsrfPreventionRequestCycleListener());
+  // ...
+ }
 ----
 
+_CsrfPreventionRequestCycleListener_ is highly configurable. It allows to define a whitelist of allowed origins via _addAcceptedOrigin(String acceptedOrigin)_, to enable/disable it dynamically by overriding _isEnabled()_, to define different kind of actions when a request is rejected or allowed, to set custom error message and code for the rejected requests.
+
+_CsrfPreventionRequestCycleListener_ is not an alternative to _CryptoMapper_! Both of them could be used separately or in tandem to prevent CSRF attacks depending on the application requirements.
+
diff --git a/wicket-user-guide/src/main/asciidoc/security/security_6.adoc b/wicket-user-guide/src/main/asciidoc/security/security_6.adoc
index f6db43f..d762384 100644
--- a/wicket-user-guide/src/main/asciidoc/security/security_6.adoc
+++ b/wicket-user-guide/src/main/asciidoc/security/security_6.adoc
@@ -1,45 +1,98 @@
 
-Since Mozilla released their site to check if web pages have security issues named https://observatory.mozilla.org[Mozilla Observatory]
-a few things which can be done to get a high grade within this ranking without using further frameworks.
 
-Add a request cycle listener to your web application and adjust the headers to fit your requirements:
+In Wicket 9 support for a Content Security Policy (or CSP) has been added. 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 distribution of malware. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP[MDN] for more information on CSP.
+
+The default CSP set by Wicket is very strict. It requires all scripts and stylesheets to be rendered with a nonce. Wicket will automatically attach the nonce to all header contributions that support this (i.e. subclasses of the _AbstractCspHeaderItem_ class). Images, fonts and (i)frames are allowed from _self_, the current host. All other resources are blocked. This includes any inline styling or Javascript (such as an _onclick_ attribute). The exact CSP is:
+
+----
+Content-Security-Policy: default-src 'none'; script-src 'strict-dynamic' 'nonce-XYZ'; style-src 'nonce-XYZ'; img-src 'self'; connect-src 'self'; font-src 'self'; manifest-src 'self'; child-src 'self'; frame-src 'self'
+----
+
+In developer mode, the CSP is extended with a reporting directive that reports violations at a special endpoint in the application that logs the violation. This is conveniant while developing an application, but care should be taken when this is enabled on production. The _cspviolation_ endpoint must be an open endpoint and all data sent to that URL will end up in the logs. To prevent the server log from filling the disk, make sure the _org.apache.wicket.csp.ReportCSPViolationMapper_ log [...]
+
+=== Configuring the Content Security Policy
+
+The Content Security Policy is managed by the _ContentSecurityPolicyEnforcer_ that can be accessed via _WebApplication.getCSP()_. This class maintains two instances of _CSPHeaderConfiguration_, each of which contains the directives for the CSP HTTP headers _Content-Security-Policy_ and _Content-Security-Policy-Report-Only_. The first header defines the policies that are actually enforced by the browser, whereas the second header defines a policy for which the browser will only report vio [...]
+
+For applications that cannot adhere to a CSP, the CSP can be disabled with the following call in your _Application_ class:
+
 [source,java]
 ----
-@Override
-protected void init()
-{
-   super.init();
+  @Override
+ protected void init() {
+  super.init();
+  getCSP().blocking().disable();
+  // ...
+ }
+----
 
-   getRequestCycleListeners().add(new AbstractRequestCycleListener(){
+As mentioned before, Wicket uses a very strict CSP by default. This preset can be selected with the following code:
 
-      @Override
-      public void onEndRequest(RequestCycle cycle)
-      {
-         WebResponse response = (WebResponse) cycle.getResponse();
-         response.setHeader("X-XSS-Protection", "1; mode=block");
-         response.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload");
-         response.setHeader("X-Content-Type-Options", "nosniff");
-         response.setHeader("X-Frame-Options", "sameorigin");
-         response.setHeader("Content-Security-Policy", "default-src https:");
-      }
-   });
-}
+[source,java]
+----
+  getCSP().blocking().strict();
 ----
 
-Add this configuration to your web.xml (or let your server redirect to https):
-[source,xml]
+A thrid preset is available that allows unsafe inline Javascript and styling and the use of unsafe _eval_. As can be inferred from the names, use of _unsafe_ is not recommended. It removes the most important protection offered by CSP. However, older applications may not be ready to apply a strict CSP. For those applications, _CSPHeaderConfiguration.unsafeInline()_ can be a starting point for the path to a strict CSP.
+
+_CSPHeaderConfiguration_ defines several methods to tune the Content Security Policy for your application. Additional sources can be whitelisted for certain via the _add(CSPDirective, ...)_ methods. For example, the code below whitelists images rendered via a _data:_ url, fonts loaded from _https://maxcdn.bootstrapcdn.com_ and a single CSS file.
+
+[source,java]
+----
+  getCSP().blocking()
+      .add(CSPDirective.IMG_SRC, "data:")
+      .add(CSPDirective.FONT_SRC, "https://maxcdn.bootstrapcdn.com")
+      .add(CSPDirective.STYLE_SRC,
+           "https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css");
+----
+
+=== Guidelines for strict CSP support
+
+To comply to the strict CSP set by default, you'll need to follow a few rules. Most importantly, you cannot use inline styling or Javascript. This includes:
+
+* _style_ attributes in the markup or via an _AttributeModifier_.
+* Inline event handlers, such as _onclick_ or _onsubmit_, in the markup or via an _AttributeModifier_.
+* Including stylesheets directly from the markup without whitelisting them.
+* Including Javascript directly from the markup. Whitelisting is not possible due to the _strict-dynamic_ rule.
+* Rendering _style_ attributes from Javascript in dynamically generated markup. Modifying the _style_ DOM property is still possible.
+* Load other resources from external domains without whitelisting them.
+
+For most of these restrictions Wicket provides alternative solutions that do work with a strict CSP. First of all, replace all inline styling with proper stylesheets and use CSS selectors to target the elements in the DOM. Replace the _AttributeModifier_ with a _style_ attribute for one with the _class_ attribute. For Javascripts that manipulate the _style_ attribute, you may have to update the script to use the DOM property instead.
+
+When a component includes a stylesheet directly from the markup as seen below, there are two possible solutions:
+
+[source,html]
 ----
 <?xml version="1.0" encoding="UTF-8"?>
-<security-constraint>
-    <web-resource-collection>
-        <web-resource-name>Entire Application</web-resource-name>
-        <url-pattern>/*</url-pattern>
-    </web-resource-collection>
-    <user-data-constraint>
-        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
-    </user-data-constraint>
-</security-constraint>
+<html xmlns:wicket="http://wicket.apache.org">
+<head>
+  <link rel="stylesheet"
+    href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" />
+</head>
+<body>...</body>
+</html>
 ----
 
-After this changes you have to check if your web application continues to work because it fits the requirements given with these headers. For example that resources could not be requested from other domains anymore.
+The first solution is to whitelist the stylesheet, as seen above. The second solution is to move the stylesheet to a header contribution in _renderHead_. This will allow Wicket to render the required _nonce_ attribute. For Javascript resources, this is the only possible solution:
 
+[source,java]
+----
+ @Override
+ public void renderHead(IHeaderResponse response) {
+   super.renderHead(response);
+   response.render(CssHeaderItem.forReference(
+       new CssResourceReference(MyComponent.class, "mycomponent.css")));
+ }
+----
+
+When your component relies on inline event handlers, such as _onclick_ or _onsubmit_, you can convert these to an _OnEventHeaderItem_. Again, this will allow Wicket to add the required _nonce_ attribute.
+
+[source,java]
+----
+ @Override
+ public void renderHead(IHeaderResponse response) {
+   super.renderHead(response);
+   response.render(OnEventHeaderItem.forComponent(this, "submit",
+       "return confirm('Do you really want to submit?')"));
+ }
+----
diff --git a/wicket-user-guide/src/main/asciidoc/security/security_7.adoc b/wicket-user-guide/src/main/asciidoc/security/security_7.adoc
index d9b77c3..1026edf 100644
--- a/wicket-user-guide/src/main/asciidoc/security/security_7.adoc
+++ b/wicket-user-guide/src/main/asciidoc/security/security_7.adoc
@@ -1,13 +1,44 @@
-In this chapter we have seen the components and the mechanisms that allow us to implement security policies in our Wicket-based applications. Wicket comes with an out of the box support for both authorization and authentication.
-
-The central element of authorization mechanism is the interface _IAuthorizationStrategy_ which decouples our components from any detail about security strategy. The implementations of this interface must decide if a user is allowed to instantiate a given page or component and if she/he can perform a given action on it. 
-
-Wicket natively supports role-based authorizations with strategies _MetaDataRoleAuthorizationStrategy_ and _AnnotationsRoleAuthorizationStrategy_. The difference between these two strategies is that the first offers a programmatic approach for role handling while the second promotes a declarative approach using built-in annotations. 
-
-After having explored how Wicket internally implements authentication and authorization, in the last part of the chapter we have learnt how to configure our applications to support HTTPS and how to specify which pages must be served over this protocol.
-
-In the last paragraph we have seen how Wicket protects package resources with a guard entity that allows us to decide which package resources can be accessed from users.
 
 
 
+Wicket internally uses an entity called package resource guard to protect package resources from external access. This entity is an implementation of interface _org.apache.wicket.markup.html.IPackageResourceGuard_. 
+
+By default Wicket applications use as package resource guard class _SecurePackageResourceGuard_, which allows to access only to the following file extensions (grouped by type):
+
+|===
+|File | Extensions
+|*JavaScript files* |.js
+|*CSS files* |.css
+|*HTML pages* |.html
+|*Textual files* |.txt
+|*Flash files* |.swf
+|*Picture files* |.png, .jpg, .jpeg, .gif, .ico, .cur, .bmp, .svg
+|*Web font files* |.eot, .ttf, .woff
+|===
+
+To modify the set of allowed files formats we can add one or more patterns with method _addPattern(String)_. The rules to write a pattern are the following:
+
+* patterns start with either a "+" or a "-" In the first case the pattern will add one or more file to the set while starting a pattern with a “-” we exclude all the files matching the given pattern. For example pattern “-web.xml” excludes all web.xml files in all directories.
+* wildcard character “\*” is supported as placeholder for zero or more characters. For example  pattern “+\*.mp4” adds all the mp4 files inside all directories.
+* subdirectories are supported as well. For example pattern “+documents/\*.pdf” adds all pdf files under “documents” directory. Character “\*” can be used with directories to specify a nesting level. For example “+documents/\*/\*.pdf” adds all pdf files placed one level below “documents” directory.
+* a double wildcard character “\*\*” indicates zero or more subdirectories. For example pattern “+documents/\*\*/\*.pdf” adds all pdf files placed inside “documents” directory or inside any of its subdirectories.
+
+Patterns that allow to access to every file with a given extensions (such as “+\*.pdf”) should be always avoided in favour of more restrictive expressions that contain a directory structure:
+
+[source,java]
+----
+//Application class code...
+@Override
+public void init()   
+{
+      IPackageResourceGuard packageResourceGuard = application.getResourceSettings() 
+                                                   .getPackageResourceGuard();
+      if (packageResourceGuard instanceof SecurePackageResourceGuard)
+      {
+         SecurePackageResourceGuard guard = (SecurePackageResourceGuard) packageResourceGuard;
+         //Allow to access only to pdf files placed in the “public” directory.
+         guard.addPattern("+public/*.pdf");
+      }
+}
+----
 
diff --git a/wicket-user-guide/src/main/asciidoc/security/security_6.adoc b/wicket-user-guide/src/main/asciidoc/security/security_8.adoc
similarity index 100%
copy from wicket-user-guide/src/main/asciidoc/security/security_6.adoc
copy to wicket-user-guide/src/main/asciidoc/security/security_8.adoc
diff --git a/wicket-user-guide/src/main/asciidoc/security/security_7.adoc b/wicket-user-guide/src/main/asciidoc/security/security_9.adoc
similarity index 100%
copy from wicket-user-guide/src/main/asciidoc/security/security_7.adoc
copy to wicket-user-guide/src/main/asciidoc/security/security_9.adoc
diff --git a/wicket-user-guide/src/main/asciidoc/single.adoc b/wicket-user-guide/src/main/asciidoc/single.adoc
index 418cc65..2f53eb5 100644
--- a/wicket-user-guide/src/main/asciidoc/single.adoc
+++ b/wicket-user-guide/src/main/asciidoc/single.adoc
@@ -657,19 +657,23 @@ include::security/security_4.adoc[leveloffset=+1]
 
 === CSRF protection
 
-include::security/security_4_1.adoc[leveloffset=+1]
+include::security/security_5.adoc[leveloffset=+1]
+
+=== Content Security Policy (CSP)
+
+include::security/security_6.adoc[leveloffset=+1]
 
 === Package Resource Guard
 
-include::security/security_5.adoc[leveloffset=+1]
+include::security/security_7.adoc[leveloffset=+1]
 
 === External Security Checks
 
-include::security/security_6.adoc[leveloffset=+1]
+include::security/security_8.adoc[leveloffset=+1]
 
 === Summary
 
-include::security/security_7.adoc[leveloffset=+1]
+include::security/security_9.adoc[leveloffset=+1]
 
 == Test Driven Development with Wicket