The Sitecore Security Hardening Guide recommends that you change the hash algorithm for password encryption from SHA1 to SHA512. A few years ago, my friend Marshall Sorenson showed how to do this with the Sitecore Install Framework (SIF), and fellow Sitecore MVP Bas Lijten showed how to do it with MSDeploy. In this article, I'll show how Matthew Wolfman and I implemented this for a Sitecore solution running on Docker.

Call to Action

Please take a moment to reach out to Sitecore Support and make a feature request for this to be default behavior in Sitecore. This is one task we should no longer have to implement ourselves.

TL;DR

All code for this blog post can be found on GitHub: https://github.com/coreyasmith/sitecore-docker-sha512-hash-algorithm.

Enable SHA512 for Identity Server

The first step is the easiest. The password hash algorithm is set for Identity Server in the \sitecore\Sitecore.Plugin.IdentityServer\Config\identityserver.xml config:

<?xml version="1.0" encoding="utf-8"?>
<Settings>
  <Sitecore>
    <IdentityServer>
      <SitecoreMembershipOptions>
        <!-- Supported algorithms: SHA1, SHA256, SHA384, SHA512, HMACSHA1, HMACSHA256, HMACSHA384, HMACSHA512. -->
        <PasswordHashAlgorithm>SHA1</PasswordHashAlgorithm>
      </SitecoreMembershipOptions>
    </IdentityServer>
  </Sitecore>
</Settings>

Almost all settings in configuration files on Sitecore Host applications can be overridden with environment variables, so to use SHA512 on your Identity Server container, just add this to the Identity Server service in your docker-compose.yml (or docker-compose.override.yml):

services:
  id:
    environment:
      Sitecore_Sitecore__IdentityServer__SitecoreMembershipOptions__PasswordHashAlgorithm: SHA512

This covers login scenarios through Identity Server; next, the CM and CD services must be patched so that passwords created and changed through the User Manager in Sitecore are hashed with SHA512.

Enable SHA512 for Sitecore CM and CD

To set the password hash algorithm for the Sitecore CM and CD, the Web.config needs to be transformed. Add a transforms folder alongside the Dockerfiles for the CM and CD services, and create a Web.config.xdt transform in that folder with these contents (e.g., \docker\build\cm\tranforms\Web.config.xdt and \docker\build\cd\tranforms\Web.config.xdt in your repository):

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.web>
    <membership hashAlgorithmType="SHA512"
                xdt:Transform="SetAttributes" />
  </system.web>
</configuration>

Update the Dockerfiles to apply transforms from the transform folder during image build:

# escape=`

ARG BASE_IMAGE
ARG TOOLING_IMAGE

FROM ${TOOLING_IMAGE} as tooling
FROM ${BASE_IMAGE}

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

# Copy development tools and entrypoint
COPY --from=tooling \tools\ \tools\

# Copy role transforms
COPY .\transforms\ \transforms\role\

# Perform role transforms
RUN C:\tools\scripts\Invoke-XdtTransform.ps1 -Path .\ -XdtPath C:\transforms\role

Now when you create users or change passwords through the User Manager in Sitecore, they will be hashed using SHA512. Last, we will patch the mssql service to hash the Sitecore Admin user password with SHA512 when Sitecore is first run.

Hash Sitecore Admin Password with SHA512

When Sitecore starts up for the first time in Docker, it uses a script in the mssql service to create the Sitecore Admin user (sitecore\admin) with the password specified in the SITECORE_ADMIN_PASSWORD environment variable. This script uses SHA1 to hash the password, so if you make the changes above to your Sitecore instance after the Sitecore Admin has been created, you won't be able to login since the password is hashed with SHA1 in the database, but Identity Server is expecting it to be hashed with SHA512.

To fix this issue, create a script called UseSha512ForSitecoreAdminPassword.ps1 alongside the Dockerfile for your mssql service:

[CmdletBinding()]
param (
    [Parameter(Mandatory)]
    [ValidateScript({ Test-Path $_ -PathType Leaf })]
    [string]$Path
)

(Get-Content $Path).
    Replace(
        "declare @HashAlgorithm nvarchar(10) = 'SHA1'",
        "declare @HashAlgorithm nvarchar(10) = 'SHA2_512'").
    Replace(
        "declare @HashedPassword varbinary(20)",
        "declare @HashedPassword varbinary(512)") |
    Set-Content $Path

Update the Dockerfile for your mssql service to run this script against the script that sets the Sitecore Admin password when the databases are first initialized:

# escape=`

ARG BASE_IMAGE

FROM ${BASE_IMAGE}

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

COPY UseSha512ForSitecoreAdminPassword.ps1 .
RUN C:\UseSha512ForSitecoreAdminPassword.ps1 -Path C:\resources\SetSitecoreAdminPassword.sql; `
    Remove-Item C:\UseSha512ForSitecoreAdminPassword.ps1

This script applies the changes that Marshall Sorensen outlined in his blog post about using the SHA512 password algorithm with SIF.

Now when you start up a fresh instance of Sitecore, the Sitecore Admin password will be hashed using SHA512 and will be compatible with the changes made above to Identity Server, CM, and CD.

Update Existing Users

As Sitecore mentions on the Security Hardening Guide, existing users are unable to log into Sitecore after changing the password hash algorithm:

The Microsoft ASP.NET membership provider does not provide a facility for upgrading to a different hash algorithm after you have created some user accounts. If you change the hash algorithm, existing users can no longer log into the system and must create new passwords.

There are a couple of ways to update the password for existing users after changing the hash algorithm:

First, if you have federated authentication setup, you can login with an admin account through federated authentication, and reset passwords through the User Manager. Federated account passwords are not stored in the Sitecore membership tables and are not affected by a hash algorithm change.

Second, see Sitecore MVP Łukasz Skowroński's answer on Stack Overflow for an approach to reset a user's password with an admin page.

Also heed Sitecore's note about changing passwords in the User Manager after changing the hash algorithm:

After you have changed the hash algorithm, you are no longer able to type a new admin password when you want to change it. Instead, to get a new hashed admin password, click Generate.