NelmioSecurityBundle
The NelmioSecurityBundle provides additional security features for your Symfony application.
Installation
Require the nelmio/security-bundle
package in your composer.json and update
your dependencies:
1
$ composer require nelmio/security-bundle
The bundle should be automatically enabled by Symfony Flex. If you don't use
Flex, you'll need to manually enable the bundle by adding the following line in
the config/bundles.php
file of your project:
1 2 3 4 5 6 7 8
<?php
// config/bundles.php
return [
// ...
Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
// ...
];
If you don't have a config/bundles.php
file in your project, chances are that
you're using an older Symfony version. In this case, you should have an
app/AppKernel.php
file instead. Edit such file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<?php
// app/AppKernel.php
// ...
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
// ...
new Nelmio\SecurityBundle\NelmioSecurityBundle(),
];
// ...
}
// ...
}
Features
- Content Security Policy: Cross site scripting attacks (XSS) can be mitigated in modern browsers using a policy which instructs the browser never to execute inline scripts, or never to load content from another domain than the page's domain.
- Signed Cookies: Specify certain cookies to be signed, so that the user cannot modify them. Note that they will not be encrypted, but signed only. The contents will still be visible to the user.
- Clickjacking Protection: X-Frame-Options header is added to all responses to prevent your site from being put in a frame/iframe. This can have serious security implications as it has been demonstrated time and time again with Facebook and others. You can allow framing of your site from itself or from anywhere on a per-URL basis.
- External Redirects Detection: Redirecting from your site to arbitrary URLs based on user input can be exploited to confuse users into clicking links that seemingly point to valid sites while they in fact lead to malicious content. It also may be possible to gain PageRank that way.
- Forced HTTPS/SSL Handling: This forces all requests to go through SSL. It will also send HSTS headers so that modern browsers supporting it can make users use HTTPS even if they enter URLs without https, avoiding attacks on public Wi-Fi.
- Flexible HTTPS/SSL Handling: If you don't want to force all users to use HTTPS, you should at least use secure session cookies and force SSL for logged-in users. But then logged-in users appear logged-out when they access a non-HTTPS resource. This is not really a good solution. This will make the application detect logged-in users and redirect them to a secure URL, without making the session cookie insecure.
- Disable Content Type Sniffing: Require that scripts are loaded using the correct mime type. This disables the feature that some browsers have which uses content sniffing to determine if the response is a valid script file or not.
- (DEPRECATED) XSS Protection: Enables/Disables Microsoft XSS Protection on compatible browsers (IE 8 and newer).
- Referrer Policy:
Referrer-Policy
header is added to all responses to control theReferer
header that is added to requests made from your site, and for navigations away from your site by browsers.
Maximum Security Configuration
This is the configuration that provides maximum security protection, but you should read on the next sections for detailed recommendations:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
# config/packages/nelmio_security.yaml
nelmio_security:
# signs/verifies all cookies
signed_cookie:
names: ['*']
# prevents framing of the entire site
clickjacking:
paths:
'^/.*': DENY
hosts:
- '^foo\.com$'
- '\.example\.org$'
# prevents redirections outside the website's domain
external_redirects:
abort: true
log: true
# prevents inline scripts, unsafe eval, external scripts/images/styles/frames, etc
csp:
hosts: []
content_types: []
enforce:
level1_fallback: false
browser_adaptive:
enabled: false
report-uri: '%router.request_context.base_url%/nelmio/csp/report'
default-src:
- 'none'
script-src:
- 'self'
block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport
# upgrade-insecure-requests: true # defaults to false, upgrades HTTP requests to HTTPS transport
# disables content type sniffing for script resources
content_type:
nosniff: true
# Send a full URL in the ``Referer`` header when performing a same-origin request,
# only send the origin of the document to secure destination (HTTPS->HTTPS),
# and send no header to a less secure destination (HTTPS->HTTP).
# If ``strict-origin-when-cross-origin`` is not supported, use ``no-referrer`` policy,
# no referrer information is sent along with requests.
referrer_policy:
enabled: true
policies:
- 'no-referrer'
- 'strict-origin-when-cross-origin'
# forces HTTPS handling, don't combine with flexible mode
# and make sure you have SSL working on your site before enabling this
# forced_ssl:
# hsts_max_age: 2592000 # 30 days
# hsts_subdomains: true
# redirect_status_code: 302 # default, switch to 301 for permanent redirects
# flexible HTTPS handling, read the detailed config info
# and make sure you have SSL working on your site before enabling this
# flexible_ssl:
# cookie_name: auth
# unsecured_logout: false
Content Security Policy
Using CSP you can set a policy which modern browsers understand and will honor.
The policy contains many different directives; default-src
, script-src
,
object-src
, style-src
, img-src
, media-src
, frame-src
,
font-src
, connect-src
, base-uri
, child-src
, form-action
,
frame-ancestors
, plugin-types
, block-all-mixed-content
,
upgrade-insecure-requests
, report-uri
, manifest-src
.
You can provide an array of directives per content type, except for block-all-mixed-content
and upgrade-insecure-requests
that only accept boolean values. Empty content
types will inherit from default-src
, specified content types will never inherit
from default-src
. Please see the Content Security Policy 1.0 and
Content Security Policy 2.0 specifications for details.
Each directive should be a domain, URI or keyword. The keyword 'self'
will
allow content from the same origin as the page. If you need to allow inline
scripts or eval()
you can use 'unsafe-inline'
and 'unsafe-eval'
.
Caution
By using 'unsafe-inline'
or 'unsafe-eval'
you're effectively
disabling the XSS protection mechanism of CSP.
Apart from content types, the policy also accepts report-uri
which should be
a URI where a browser can POST a JSON payload to whenever a policy directive
is violated. As of v3.5, a report-to
directive can be included as well to configure a
reporting endpoint (see Reporting API), which is intended to replace the deprecated report-uri
directive.
An optional content_types
key lets you restrict the Content Security Policy
headers only on some HTTP response given their content type.
Finally, an optional hosts
key lets you configure which hostnames (e.g. foo.example.org
)
the CSP rule should be enforced on. If the list is empty (it is by default), all
hostnames will use the CSP rule.
If the `content_types` and `hosts` options don’t fit your needs, you can also configure a service implementing `SymfonyComponentHttpFoundationRequestMatcherInterface` as `request_matcher`. Then the `content_types` and `hosts` options are no longer used.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
# config/packages/nelmio_security.yaml
nelmio_security:
csp:
enabled: true
report_logger_service: logger
request_matcher: null
hosts: []
content_types: []
enforce:
# see full description below
level1_fallback: true
# only send directives supported by the browser, defaults to false
# this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
browser_adaptive:
enabled: false
report-uri: '%router.request_context.base_url%/nelmio/csp/report'
default-src: [ 'self' ]
frame-src: [ 'https://www.youtube.com' ]
script-src:
- 'self'
- 'unsafe-inline'
img-src:
- 'self'
- facebook.com
- flickr.com
block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport
# upgrade-insecure-requests: true # defaults to false, upgrades HTTP requests to HTTPS transport
report:
# see full description below
level1_fallback: true
# only send directives supported by the browser, defaults to false
# this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
browser_adaptive:
enabled: true
report-uri: '%router.request_context.base_url%/nelmio/csp/report'
script-src:
- 'self'
The above configuration would enforce the following policy:
- Default is to allow from same origin as the page
- Frames only from secure YouTube connections
- JavaScript from same origin and from inline
<script>
tags - Images from same origin,
facebook.com
andflickr.com
Any violation of the enforced policy would be posted to /nelmio/csp/report
.
In addition, the configuration only reports but doesn't enforce the policy that JavaScript may only be executed when it comes from the same server.
The bundle provides a default reporting implementation that logs violations as notices to the default logger, to enable add the following to your routing.yml:
1 2 3 4 5
# config/routing.yaml
nelmio_security:
path: /nelmio/csp/report
defaults: { _controller: nelmio_security.csp_reporter_controller::indexAction }
methods: [POST]
(Optional) Use report_logger_service to log to the 'security'
channel:
1 2 3 4
# config/packages/nelmio_security.yaml
nelmio_security:
csp:
report_logger_service: monolog.logger.security
(Optional) Disable compat_headers to avoid sending X-Content-Security-Policy (IE10, IE11, Firefox < 23). This will mean those browsers get no CSP instructions.
1 2 3 4
# config/packages/nelmio_security.yaml
nelmio_security:
csp:
compat_headers: false
Using browser adaptive directives
The NelmioSecurityBundle can be configured to only send directives that can be understood by the browser. This reduces noise provided via the report URI. This is a direct port of what has been done in Twitter SecureHeaders library.
Use the enabled
key to enable it:
1 2 3 4 5 6
# config/packages/nelmio_security.yaml
nelmio_security:
csp:
enforce:
browser_adaptive:
enabled: true
Caution
This will parse the user agent and can consume some CPU usage. You can specify a cached parser to avoid consuming too much CPU:
1 2 3 4 5 6 7
# config/packages/nelmio_security.yaml
nelmio_security:
csp:
enforce:
browser_adaptive:
enabled: true
parser: my_own_parser
And declare service my_own_parser
based on one of the cached parser
NelmioSecurityBundle provides or your own one. For instance, using the PsrCacheUAFamilyParser
:
1 2 3 4 5
<service id="my_own_parser" class="Nelmio\SecurityBundle\UserAgent\UAFamilyParser\PsrCacheUAFamilyParser">
<argument type="service" id="app.my_cache.pool"/>
<argument type="service" id="nelmio_security.ua_parser.ua_php"/>
<argument>604800</argument>
</service>
Have a look in the Nelmio\SecurityBundle\UserAgent\UAFamilyParser
for these parsers.
Message digest for inline script handling
If you want to disable 'unsafe-inline'
on script-src
or style-src
(recommended), Nelmio Security Bundle comes out of the box with message digest
functionality. Twig is natively supported.
You can configure the algorithm used for message digest in the configuration.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# config/packages/nelmio_security.yaml
nelmio_security:
csp:
hash:
algorithm: sha512 # default is sha256, available are sha256, sha384 and sha512
enforce:
# Provides compatibility with CSP level 1 (old / non-yet-compatible browsers) when using CSP level 2
# features likes hash and nonce. It adds a 'unsafe-inline' source to a directive whenever a nonce or hash
# is used.
# From RFC: " If 'unsafe-inline' is not in the list of allowed style sources, or if at least one
# nonce-source or hash-source is present in the list of allowed style sources "
# See https://www.w3.org/TR/CSP2/#directive-style-src and https://www.w3.org/TR/CSP2/#directive-script-src
level1_fallback: true
default-src: ['self']
In your Twig template use the cspscript
and cspstyle
tags to automatically
compute the message digest and insert it in your headers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{% cspscript %}
<script>
window.api_key = '{{ api_key }}';
</script>
{% endcspscript %}
{# ... #}
{% cspstyle %}
<style>
body {
background-color: '{{ bgColor }}';
}
</style>
{% endcspstyle %}
If you're not using Twig, you can use message digest with the
ContentSecurityPolicyListener
, it will automatically compute the message
digest and add it to the response CSP header:
1 2 3 4 5 6 7 8 9 10
$listener->addScript("<script>
window.api_key = '{{ api_key }}';
</script>");
$listener->addStyle("<style>
body {
background-color: '{{ bgColor }}';
}
</style>");
Nonce for inline script handling
Content-Security-Policy specification also proposes a nonce implementation for inlining. Nelmio Security Bundle comes out of the box with nonce functionality. Twig is natively supported.
In your Twig template use the csp_nonce
function to access the nonce for the
current request and add it to the response CSP header. If you do not request a
nonce, nonce will not be generated.
1 2 3 4 5 6 7 8 9 10 11
<script nonce="{{ csp_nonce('script') }}">
window.api_key = '{{ api_key }}';
</script>
{# ... #}
<style nonce="{{ csp_nonce('style') }}">
body {
background-color: '{{ bgColor }}';
}
</style>
If you're not using Twig, you can use nonce functionality with the ContentSecurityPolicyListener
:
1 2 3 4
// generates a nonce at first time, returns the same nonce once generated
$listener->getNonce('script');
// or
$listener->getNonce('style');
Reporting
Using the report-uri
you can easily collect violation using the ContentSecurityPolicyController
.
Here's an configuration example using routing.yml
:
1 2 3 4 5
# config/routes.yaml
csp_report:
path: /csp/report
methods: [POST]
defaults: { _controller: nelmio_security.csp_reporter_controller::indexAction }
This part of the configuration helps to filter noise collected by this endpoint:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
# config/packages/nelmio_security.yaml
nelmio_security:
csp:
report_endpoint:
log_level: "notice" # Use the appropriate log_level
log_formatter: ~ # Declare a service name that must implement Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Log\LogFormatterInterface
log_channel: ~ # Declare the channel to use with the logger
filters:
# Filter false positive reports given a domain list
domains: true
# Filter false positive reports given a scheme list
schemes: true
# Filter false positive reports given known browser bugs
browser_bugs: true
# Filter false positive reports given known injected scripts
injected_scripts: true
# You can add you custom filter rules by implementing Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Filter\NoiseDetectorInterface
# and tag the service with "nelmio_security.csp_report_filter"
dismiss:
# A list of key-values that should be dismissed
# A key is either a domain or a regular expression
# A value is a source or an array of source. The '*' wilcard is accepted
'/^data:/': 'script-src'
'/^https?:\/\/\d+\.\d+\.\d+\.\d+(:\d+)*/': '*'
'maxcdn.bootstrapcdn.com': '*'
'www.gstatic.com': ['media-src', 'img-src']
Signed Cookies
Ideally you should explicitly specify which cookies to sign. The reason for this is simple. Cookies are sent with each request. Signatures are often longer than the cookie values themselves, so signing everything would just needlessly slow down your app and increase bandwidth usage for your users.
1 2 3 4
# config/packages/nelmio_security.yaml
nelmio_security:
signed_cookie:
names: [test1, test2]
However, for simplicity reasons, and to start with a high security and optimize
later, you can specify *
as a cookie name to have all cookies signed automatically.
1 2 3 4
# config/packages/nelmio_security.yaml
nelmio_security:
signed_cookie:
names: ['*']
Additional, optional configuration settings:
1 2 3 4 5
# config/packages/nelmio_security.yaml
nelmio_security:
signed_cookie:
secret: this_is_very_secret # defaults to global %secret% parameter
hash_algo: sha512 # defaults to sha256, see ``hash_algos()`` for available algorithms
Upgrading the Hash Algorithm
With advancements in computational power and security research, upgrading to more secure hashing algorithms is essential for maintaining application security. However, simply changing the `hash_algo` value could break existing cookies. To facilitate a smooth transition, this bundle offers a `legacy_hash_algo` option. If your application currently uses `sha-256` and you wish to upgrade to the more secure `sha3-256` algorithm, set `legacy_hash_algo` to `sha256` and `hash_algo` to `sha3-256`.
1 2 3 4 5
# config/packages/nelmio_security.yaml
nelmio_security:
signed_cookie:
hash_algo: sha3-256
legacy_hash_algo: sha256
Caution
The `legacy_hash_algo` option can expose your application to downgrade attacks and should only be used temporarily for backward compatibility.
Clickjacking Protection
Most websites do not use frames and do not need to be frame-able. This is a common attack vector for which all current browsers (IE8+, Opera10.5+, Safari4+, Chrome4+ and Firefox3.7+) have a solution. An extra header sent by your site will tell the browser that it can not be displayed in a frame. Browsers react by showing a short explanation instead of the content, or a blank page.
The valid values for the X-Frame-Options
header are DENY
(prevent framing
from all pages) and SAMEORIGIN
(prevent framing from all pages not on the
same domain). Additionally this bundle supports the ALLOW
option which
skips the creation of the header for the matched URLs, if you want to allow a
few URLs and then DENY everything else.
One more option, as of yet not well supported, is to use ALLOW-FROM uri
where uri
can be any origin URL, from example.org
to
https://example.org:123/sub/path
. This lets you specify exactly which domain
can embed your site, in case you have a multi-domain setup.
Default configuration (deny everything):
1 2 3 4 5 6 7
# config/packages/nelmio_security.yaml
nelmio_security:
clickjacking:
paths:
'^/.*': DENY
content_types: []
hosts: []
Allow list configuration (deny all but a few URLs):
1 2 3 4 5 6 7 8 9 10
# config/packages/nelmio_security.yaml
nelmio_security:
clickjacking:
paths:
'^/iframes/': ALLOW
'^/business/': 'ALLOW-FROM https://biz.example.org'
'^/local/': SAMEORIGIN
'^/.*': DENY
content_types: []
hosts: []
Apply to certain hosts:
1 2 3 4 5 6 7 8 9 10
# config/packages/nelmio_security.yaml
nelmio_security:
clickjacking:
paths:
'^/iframes/': ALLOW
'^/.*': DENY
content_types: []
hosts:
- '^foo\.com$'
- '\.example\.org$'
You can also of course only deny a few critical URLs, while leaving the rest alone:
1 2 3 4 5 6 7
# config/packages/nelmio_security.yaml
nelmio_security:
clickjacking:
paths:
'^/message/write': DENY
content_types: []
hosts: []
An optional content_types
key lets you restrict the X-Frame-Options header
only on some HTTP response given their content type.
External Redirects Detection
This feature helps you detect and prevent redirects to external sites. This can easily happen by accident if you carelessly take query parameters as redirection target.
You can log those (it's logged at warning level) by turning on logging:
1 2 3 4
# config/packages/nelmio_security.yaml
nelmio_security:
external_redirects:
log: true
You can abort (they are replaced by a 403 response) the redirects:
1 2 3 4
# config/packages/nelmio_security.yaml
nelmio_security:
external_redirects:
abort: true
Or you can override them, replacing the redirect's Location
header by a
route name or another URL:
1 2 3 4 5 6 7
# config/packages/nelmio_security.yaml
nelmio_security:
external_redirects:
# redirect to the 'home' route
override: home
# use this to redirect to another URL
# override: /foo
If you want to display the URL that was blocked on the overriding page you can
specify the forward_as
parameter, which defines which query parameter will
receive the URL. For example using the config below, doing a redirect to
http://example.org/
will be overridden to /external-redirect?redirUrl=http://example.org/
.
1 2 3 4 5 6
# config/packages/nelmio_security.yaml
nelmio_security:
external_redirects:
# redirect and forward the overridden URL
override: /external-redirect
forward_as: redirUrl
Since it's quite common to have to redirect outside the website for legit reasons, typically OAuth logins and such, you can allow a few domain names. All their subdomains will be allowed as well, so you can allow your own website's subdomains if needed.
1 2 3 4 5 6 7
# config/packages/nelmio_security.yaml
nelmio_security:
external_redirects:
abort: true
allow_list:
- twitter.com
- facebook.com
If you have a controller that can redirect to another host, you can also use `ExternalRedirectResponse` to allow the redirect without having to configure the hosts globally. Any hosts passed to `ExternalRedirectResponse` are in addition to those already configured globally.
1 2 3 4 5 6
# config/packages/nelmio_security.yaml
nelmio_security:
external_redirects:
abort: true
allow_list:
- bar.com
1 2 3 4 5 6 7 8 9 10
use Nelmio\SecurityBundle\ExternalRedirect\ExternalRedirectResponse;
// Will be allowed even though "foo.com" is not allowed globally through the config.
return new ExternalRedirectResponse('https://foo.com', ['foo.com', 'auth-provider.test']);
// Will not be allowed.
return new ExternalRedirectResponse('https://not-allowed.com', ['foo.com', 'auth-provider.test']);
// Will be allowed because "bar.com" is allowed globally through the config.
return new ExternalRedirectResponse('https://bar.com', ['foo.com', 'auth-provider.test']);
Forced HTTPS/SSL Handling
By default, this option forces your entire site to use SSL, always. It redirect all users reaching the site with a http:// URL to a https:// URL with a 302 response.
The base configuration for this is the following:
1 2 3
# config/packages/nelmio_security.yaml
nelmio_security:
forced_ssl: ~
If you turn this option on, it's recommended to also set your session cookie to be secure, and all other cookies you send for that matter. You can do the former using:
1 2 3 4
# config/packages/framework.yaml
framework:
session:
cookie_secure: true
To keep a few URLs from being force-redirected to SSL you can define an allowed list of regular expressions:
1 2 3 4 5 6
# config/packages/nelmio_security.yaml
nelmio_security:
forced_ssl:
enabled: true
allow_list:
- ^/unsecure/
To restrict the force-redirects to some hostnames only you can define a list of hostnames as regular expressions:
1 2 3 4 5 6
# config/packages/nelmio_security.yaml
nelmio_security:
forced_ssl:
enabled: true
hosts:
- ^\.example\.org$
To change the way the redirect is done to a permanent redirect for example, you can set:
1 2 3 4 5
# config/packages/nelmio_security.yaml
nelmio_security:
forced_ssl:
enabled: true
redirect_status_code: 301
Then if you want to push it further, you can enable HTTP Strict Transport Security (HSTS).
This is basically sending a header to tell the browser that your site must always
be accessed using SSL. If a user enters a http://
URL, the browser will convert
it to https://
automatically, and will do so before making any request, which
prevents man-in-the-middle attacks.
The browser will cache the value for as long as the specified hsts_max_age
(in seconds), and if you turn on the hsts_subdomains
option, the behavior
will be applied to all subdomains as well.
1 2 3 4 5
# config/packages/nelmio_security.yaml
nelmio_security:
forced_ssl:
hsts_max_age: 2592000 # 30 days
hsts_subdomains: true
You can also tell the browser to add your site to the list of known HSTS sites,
by enabling hsts_preload
. Once your site has appeared in the Chrome and
Firefox preload lists, then new users who come to your site will already be
redirected to HTTPS URLs.
1 2 3 4 5
# config/packages/nelmio_security.yaml
nelmio_security:
forced_ssl:
hsts_max_age: 31536000 # 1 year
hsts_preload: true
Note
A value of at least 1 year is currently required by Chrome and
also required by Firefox. hsts_subdomains
must also be enabled for
preloading to work.
You can speed up the inclusion process by submitting your site to the HSTS Preload List.
A small word of caution: While HSTS is great for security, it means that if the browser can not establish your SSL certificate is valid, it will not allow the user to query your site. That just means you should be careful and renew your certificate in due time.
Tip
Check Can I use HSTS? for the full information about its support in browsers.
Flexible HTTPS/SSL Handling
The best way to handle SSL securely is to enable it for your entire site.
However in some cases this is not desirable, be it for caching or performance reasons, or simply because most visitors of your site are anonymous and don't benefit much from the added privacy and security of SSL.
If you don't want to enable SSL across the board, you need to avoid that people on insecure networks (typically open Wi-Fi) get their session cookie stolen by sending it non-encrypted. The way to achieve this is to set your session cookie to be secure as such - but don't do it just yet, keep reading to the end.
1 2 3 4
# config/packages/framework.yaml
framework:
session:
cookie_secure: true
If you use the remember-me functionality, you would also mark that one as secure:
1 2 3 4 5 6
# config/packages/security.yaml
security:
firewalls:
somename:
remember_me:
secure: true
Now if you do this, you have two problems. First, insecure pages will not be
able to use the session anymore, which can be inconvenient. Second, if a logged
in user gets to a non-HTTPS page of your site, it is seen as anonymous since
his browser will not send the session cookie. To fix this, this bundle sets a
new insecure cookie(flexible_ssl.cookie_name
, defaults to auth
) once a
user logs in. That way, if any page is accessed insecurely by a logged in user,
he is redirected to the secure version of the page, and his session is then
visible to the framework.
Enabling the flexible_ssl
option of the NelmioSecurityBundle will make sure
that logged-in users are always seeing secure pages, and it will make sure
their session cookie is secure, but anonymous users will still be able to have
an insecure session, if you need to use it to store non critical data like
language settings and whatnot. The remember-me cookie will also be made always
secure, even if you leave the setting to false.
1 2 3 4 5
# config/packages/nelmio_security.yaml
nelmio_security:
flexible_ssl:
cookie_name: auth
unsecured_logout: false
You have to configure one more thing in your security configuration though:
every firewall should have our logout listener added, so that the special
auth
cookie can be cleared when users log out. You can do it as such:
1 2 3 4 5 6 7 8
# config/packages/security.yaml
security:
firewalls:
somename:
# ...
logout:
handlers:
- nelmio_security.flexible_ssl_listener
On logout, if you would like users to be redirected to an unsecure page set
unsecured_logout
to true.
Content Type Sniffing
Disables the content type sniffing for script resources. Forces the browser to only execute script files with valid content type headers. This requires using a non-standard nosniff header from Microsoft.
1 2 3 4
# config/packages/nelmio_security.yaml
nelmio_security:
content_type:
nosniff: true
XSS Protection (DEPRECATED)
Caution
This feature is non-standard and deprecated. It is recommended to use CSP instead : https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
Enables or disables Microsoft XSS Protection on compatible browsers. This requires using a non-standard X-XSS-Protection header from Microsoft.
1 2 3 4 5 6
# config/packages/nelmio_security.yaml
nelmio_security:
xss_protection:
enabled: true
mode_block: true
report_uri: '%router.request_context.base_url%/nelmio/xss/report'
Referrer Policy
Adds Referrer-Policy
header to control the Referer
header that is added
to requests made from your site, and for navigations away from your site by browsers.
You can specify multiple referrer policies. The order of the policies is
important. Browser will choose only the last policy they understand. For
example older browsers don't understand the strict-origin-when-cross-origin
policy. A site can specify a no-referrer
policy followed by a
strict-origin-when-cross-origin
policy: older browsers will ignore the
unknown strict-origin-when-cross-origin
value and use no-referrer
,
while newer browsers will use strict-origin-when-cross-origin
because it is
the last to be processed.
These are the valid referrer policies:
- no-referrer
- no-referrer-when-downgrade
- same-origin
- origin
- strict-origin
- origin-when-cross-origin
- strict-origin-when-cross-origin
- unsafe-url
- an empty string
For better security of your site please use no-referrer
, same-origin
,
strict-origin
or strict-origin-when-cross-origin
.
1 2 3 4 5 6 7
# config/packages/nelmio_security.yaml
nelmio_security:
referrer_policy:
enabled: true
policies:
- 'no-referrer'
- 'strict-origin-when-cross-origin'