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 <[email protected]>
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
 

Reply via email to