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