Introducing Jhoose Security Module V2.0

Featured

Version V2.0 of the Jhoose Security module has been released and is available via the Optimizely nuget feed.

This update not only squashes several bugs it also introduces several new features to help secure your website.

Removed support for CMS 11

I have taken this opportunity to remove support for CMS11 as I felt that it was sensible to simplify the solution and focus on targeting the latest version of the CMS.

The module now only supports .NET6, 7 and 8.

User interface to manage Security Response Headers

In the previous versions of the module it is possible to control the Security Response headers by configuration, but I have now introduced a new optional user interface to manage these headers. This gives extra control; allowing administrators to easily change the settings post deployment.

Enable User Interface

services.AddJhooseSecurity(_configuration, (o) =>
{
o.UseHeadersUI = true;
});
User Interface for Security Headers

Adding the user interface is entirely optional, but if you do you will need to review the configuration as the existing settings are not transferred over.

Authentication Policy Overrides

By default any user with the CMSAdmins security role can access the module, but it is possible to change this to an alternate role if required.

services.AddJhooseSecurity(_configuration,
configurePolicy: (p) =>
{
p.RequireRole("CspAdmin");
});

API Access

The security headers can be accessed via a Rest API, this is useful if you are using Optimizely to manage the content, but not presentation.

Access to the Rest API is secured by authentication keys, each consumer must include a valid key in the header. Authentication keys are managed within the module.

Webhooks

Consumers can register a webhook, this will then be called whenever a change is made either the Content Security Policy or the Security Headers.

It is recommended that consumers take this approach as caching the headers and then only refreshing when changes occur will help performance.

Example

POST /api/jhoose/headers HTTP/1.1
Accept: application/json
Content-Type: application/json
X-API-Key: ...
{'nonce': '1234567890' }

Note: Nonce

Each request should include a different nonce value. If you are following the recommendations and caching the response then you should also change the nonce value within the cached value.

Conclusion

More information can be found in my github repo. Any suggestions, comments are greatly appreciated.

Jhoose Security – Updated to support Episerver 11

I have updated the Jhoose security module to support any Episerver 11 site, the only dependency is .Net Framework 4.7.1.

Installation

Install the package directly from the Optimizley Nuget repository. This will install the admin interface along with the middleware to add the CSP header to the response.

Github: https://github.com/andrewmarkham/contentsecuritypolicy

dotnet add package Jhoose.Security.Admin
 --version 1.2.2.148 
Install-Package Jhoose.Security.Admin
 -Version 1.2.2.148 

Configuration

The installation process will add the following nodes to the web.config file within your solution.

<configSections>
	<sectionGroup name="JhooseSecurity" type="Jhoose.Security.Configuration.JhooseSecurityOptionsConfigurationSectionGroup, Jhoose.Security">
		<section name="Headers" type="Jhoose.Security.Configuration.HeadersSection, Jhoose.Security" />
		<section name="Options" type="Jhoose.Security.Configuration.OptionsSection, Jhoose.Security" />
	</sectionGroup>
</configSections>

Register the module with the .Net pipeline

<system.webServer>
	<modules runAllManagedModulesForAllRequests="true">
		<add name="JhooseSecurityModule" type="Jhoose.Security.HttpModules.JhooseSecurityModule, Jhoose.Security" />
	</modules>
</system.webServer>   

Configuration options for the module

<JhooseSecurity>
	<Options httpsRedirect="true">
		<Exclusions>
			<add path="/episerver" />
		</Exclusions>
	</Options>
	<Headers>
		<StrictTransportSecurityHeader enabled="true" maxAge="31536000" />
		<XFrameOptionsHeader enabled="true" mode="Deny|SameOrigin|AllowFrom" domain=""/>
		<XContentTypeOptionsHeader enabled="true" />
		<XPermittedCrossDomainPoliciesHeader enabled="true" mode="None|MasterOnly|ByContentType|All"/>
		<ReferrerPolicyHeader enabled="true" mode="NoReferrer|NoReferrerWhenDownGrade|Origin|OriginWhenCrossOrigin|SameOrigin|StrictOrigin|StrictOriginWhenCrossOrigin|UnsafeUrl"/>
		<CrossOriginEmbedderPolicyHeader enabled="true" mode ="UnSafeNone|RequireCorp"/>
		<CrossOriginOpenerPolicyHeader  enabled="true" mode="UnSafeNone|SameOriginAllowPopups|SameOrigin"/>
		<CrossOriginResourcePolicyHeader enabled="true" mode="SameSite|SameOrigin|CrossOrigin" />
	</Headers>
</JhooseSecurity>

Exclusions: Any request which starts with a path specified in this property will not include the CSP header. 

httpsRedirect: This attribute controls whether all requests should be upgraded to HTTPS.

Nonce HTML helper

It is possible to get a nonce added to your inline <script> and <style> tags.

@using Jhoose.Security.Core.HtmlHelpers;
<script @Html.AddNonce() src="/assets/js/jquery.min.js"></script>

Response Headers

The response headers can be controlled within the web.config

Server Header and X-Powered-By Header

These aren’t removed, the reason being

  1. When hosting within Optimizley DXP, the CDN will obfuscate the server value anyway.
  2. The header cannot be removed programmatically.
IIS 10
<!-- web.config -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <security>
            <requestFiltering removeServerHeader="true" />
        </security>

        <httpProtocol>
            <customHeaders>
                <clear />
                <remove name="X-Powered-By" />
            </customHeaders>
        </httpProtocol>
    </system.webServer>
</configuration>

Jhoose Security – Update to include recommended security headers.

I have updated the module to automatically output the OWASP recommended security headers.

Example response headers

These headers are automatically added to the response but can be configured as required, or even disabled.

Code Configuration

        services.AddJhooseSecurity(_configuration, (securityOptions) => {
            
            // define the XFrame Options mode
            securityOptions.XFrameOptions.Mode = XFrameOptionsEnum.SameOrigin;
            
            // disable HSTS
            securityOptions.StrictTransportSecurity.Enabled = false;
        });

Configuration via appSettings

"JhooseSecurity": {
      "ExclusionPaths": [
        "/episerver"
      ],
      "HttpsRedirection": true,
      "StrictTransportSecurity": {
        "MaxAge": 31536000,
        "IncludeSubDomains": true
      },
      "XFrameOptions": {
        "Enabled": false,
        "Mode": 0,
        "Domain": ""
      },
      "XPermittedCrossDomainPolicies": {
        "Mode": 0
      },
      "ReferrerPolicy": {
        "Mode": 0
      },
      "CrossOriginEmbedderPolicy": {
        "Mode": 1
      },
      "CrossOriginOpenerPolicy": {
        "Mode": 2
      },
      "CrossOriginResourcePolicy": {
        "Mode": 1
      }
    }

Managing the server header

The security module doesn’t remove the ‘server header’, this may seem strange, but the approach differs depending on how you are hosting your site. I have included some examples below.

Another consideration, if you are hosting your solution with Optimizely DXP then the CDN will automatically remove the header.

Kestrel

return Host.CreateDefaultBuilder(args)
  .ConfigureCmsDefaults()
  .ConfigureWebHostDefaults(webBuilder =>
{
   webBuilder.ConfigureKestrel(o => o.AddServerHeader = false);
   webBuilder.UseStartup<Startup>();
});

IIS

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <security>
            <requestFiltering removeServerHeader="true" />
        </security>
    </system.webServer>
</configuration>

Installation

dotnet add package Jhoose.Security.Admin  --version 1.1.1.89

Introducing Jhoose Security – A module to manage your Content Security Policy

It has always been difficult to manage the CSP on a website, this new module for Optimizley aims to make the process easier giving control back to advanced editors.

Features

  • Interface to manage policies.
  • Global ‘report only’ mode, or specify for each policy.
  • Add ‘nonce’ to inline script or style tags.
  • Ability to specify paths that are excluded from outputting the policy header.

Administration

Once the module is installed you will see a new ‘Security’ menu item within the top menu.

Settings

This screen gives you access to the global settings of the module, allowing the module to be enabled/disabled or switched into ‘Report Only’ mode.

It is also possible to specify an endpoint for a reporting service.

Module Settings

View Policies

All security policies are listed, with a summary of the policy configuration. A user is then able to click on a policy to view the policy in greater detail or amend it as required.

List of all policies

Edit Policy

This screen allows for an individual policy to be managed by the user, these will be saved when the ‘OK’ button is pressed.

When changes are made it is recommended that they are tested in ‘Report Only’ mode to ensure that nothing is adversely impacted by the new configuration.

Edit individual policy

Installation

Install the package directly from the Optimizley Nuget repository. This will install the admin interface along with the middleware to add the CSP header to the response.

Github: https://github.com/andrewmarkham/contentsecuritypolicy

dotnet add package Jhoose.Security.Admin

Configuration

Startup.cs

services.AddJhooseSecurity(IConfiguration configuration, Action<SecurityOptions> options = null);

The Action<SecurityOptions> options is optional and if not specified then the default will be used.

  "JhooseSecurity": {
    "ExclusionPaths": [
      "/episerver"
    ]
  }

ExclusionPaths: Any request which starts with a path specified in this property will not include the CSP header.

app.UseJhooseSecurity();

Nonce Tag Helper

It is possible to get a nonce added to your inline <script> and <style> tags.

_ViewImports.cshtml

@addTagHelper *, Jhoose.Security.Core
<script nonce src="/assets/js/jquery.min.js"></script>

Managing the ‘Content Security Policy’ of your site

Introduction

The ‘Content Security Policy’ response header is used to enhance a website’s security. It allows control of how resources are loaded, whitelisting trusted domains.

Any security audit will highlight this as a key recommendation.

Content-Security-Policy: default-src 'self' ; script-src https://www.google-analytics.com https://ssl.google-analytics.com; img-src https://www.google-analytics.com; connect-src https://www.google-analytics.com;

Read More: https://content-security-policy.com/

Why

Content Security Policy is an extra layer of security that protects against certain types of attack vectors (XSS, Click Jacking), anything you can do to protect the end-user is beneficial.

It is common practice these days for developers to draw in 3rd party packages to deliver a feature and these packages will also draw in other packages. This means that malicious code can get drawn into your solution without your knowledge.

Read More : https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610

How

It is possible to be very granular when configuring the security policy. This gives you a high level of control of what can be loaded and where data can be sent.

Although the Content Security Policy can be added at a meta tag, it is typically delivered in a response header, additionally, it is also possible to enable specific inline scripts by adding a nonce value.

Testing your policy

Changes to the policy can inadvertently disable features on your site. YouTube videos can fail to load, analytics stops sending data, javascript components can fail. To help mitigate this you should either make any changes as ‘report only’ and monitor the output or configure the policy to report issues. This means that any issues are either reported within the browser console or are sent to a 3rd party reporting service.

Challenges

You have deployed your policy, it’s been tested and signed off, but then things start to fail. Unfortunately, things do change, a dependency can update the endpoints they use or more typically a new tool is added via Google Tag Manager.

Managing the content security policy can be challenging. A common approach is to create a Url Rewrite outbound rule. This means that when the policy needs to change you have to update your source code and redeploy your site, not very efficient.

Is there an easier way?

Read my next post where I will introduce the new Episerver / Optimizely module that simplifies the management of the Content Security Policy.

Next Post: http://jhoose.co.uk/2021/11/01/introducing-jhoose-security-a-module-to-manage-your-content-security-policy/