Chapter 10: Keeping Your Windows Server Secure – Mastering Windows Security and Hardening

Chapter 10: Keeping Your Windows Server Secure

Throughout this chapter, you will learn about the best practices and tools that you can use to keep your Windows server secure. As mentioned in Chapter 9, Keeping Your Windows Client Secure, this chapter will cover the core of what this book is about but for your Windows servers. Directly securing and hardening your Windows server OSes where your data, services, and applications live is a very important task. A breach of a server could lead to significant damage to your organization.

Your Windows servers serve as the core of your data and the applications for your users and customers. Protecting them requires well-defined standards and ongoing maintenance to ensure they stay protected. With Windows server, there are many built-in roles and features that allow additional functionality for your environment. Ensuring these are hardened is also just as critical. As a standard rule, none of your servers should be web-facing unless they are specifically providing a public web service, in which case those servers should be given extra attention and hardening.

This chapter will cover server protection through onboarding with Microsoft Defender ATP and delivering security updates with WSUS and Azure Update Management. Ensuring that your servers have the latest security updates and virus definition updates is a must. These two technologies are foundational for server security.

The Hardening Windows Server section will cover the technologies and configurations needed to round off Windows server security. This includes referencing back to pre-defined baselines, as shown in Chapter 2, Building a Baseline, enforcing these settings using Group Policy, and enabling disk encryption with Azure Disk Encryption. Finally, we will cover advanced application control by deploying Windows Defender Application Control polices. This chapter includes the following topics:

  • Windows server versions
  • Installing Windows server roles and features
  • Configuring Windows updates
  • Connecting to Microsoft Defender ATP
  • Hardening Windows server
  • Deploying Windows Defender Application Control

Technical requirements

This chapter will provide instructions that will allow you to enable security features in Windows server and configure Group Policy. In order to follow along, you will need basic knowledge of PowerShell, access to server roles that need to be installed, and be able to modify Group Policy in your domain environment and deploy resources in Azure. The following products and tools will be referenced:

Check out the following video to see the Code in Action:

Windows Server versions

This book focuses on Windows Server 2016 and 2019. Most versions of Windows Server 2012 are under support until 2023, and support for Windows Server 2008 versions has ended. It is important to be familiar with the Microsoft life cycle of your server's OSes. The following URL provides the most current Window server release information:

To view the life cycle for a specific Windows server version, go to this link:

Important note

Microsoft also has a Semi-Annual Channel (SAC) option, in addition to a Long-Term Servicing Channel (LTSC). The SAC version releases feature updates twice a year to allow customers to adopt changes faster. The latest SAC version, at the time of writing, is Windows server version 1909.

Windows Server 2019 has Standard and Datacenter versions. The Datacenter version provides additional enhancements over the Standard version. In addition to the available editions, there are a few different installation options available:

  • Desktop Experience is the traditional deployment of Windows server and includes a Graphical User Interface (GUI). This option is only available in the LTSC version.
  • Server Core only includes the required server role and doesn't include the GUI. This option is available for both the SAC and LTSC versions.
  • Nano Server was introduced in Server 2016, has an even smaller footprint than Server Core, and can only be administered remotely. It only supports 64-bit applications, tools, and agents. A couple of examples include using Nano Server for Internet Information Services (IIS) or a DNS server. This option is only available in the SAC version.

As a best practice, we recommend using the most minimal installation option to reduce the footprint of the server and minimize the attack surface. Deploying a server without a GUI and limiting logon types to remote administration is a significant security improvement and should be considered where possible.

Windows Server 2019 includes the following new security highlights:

  • Windows Defender ATP
  • Windows Defender ATP Exploit Guard
  • Security with Software-Defined Networking (SDN)
  • Improvements with Shielded Virtual Machines (VMs)
  • HTTP/2 to provide a safer web experience and faster browsing
  • Encrypted networks

The following URL provides a list of all the new features of Windows Server 2019:

In Chapter 2, Building a Baseline, we provided a minimum set of policy recommendations within the Policies sub-section of the Policies, Standards, Procedures, and Guidelines section. By completing this chapter, you will be able to cross-reference back to those policy items to see where there are gaps. The importance of building your policy to reference against it is critical to hardening your servers throughout your environment.

Next, will we review Windows server's roles and features and highlight the security-specific roles available that will help you secure your environment.

Installing Windows Server roles and features

Roles and features add additional functionality to your environment. As you add roles, it is critical that hardening is also taken into consideration and understood. For example, hardening a Domain Controller (DC) will be different to that of an IIS web server. There will be some base similarities, but you need to understand what each of these roles and features provide and how to best secure them if they are to be enabled. Any mishandling could provide an opportunity for a hacker to exploit or infiltrate your environment.

The following roles are features in Windows Server 2019 that are available to help with securing and hardening your environment:

  • Active Directory Certificate Services
  • Active Directory Domain Services
  • Active Directory Federation Services
  • Active Directory Rights Management Services
  • Device Health Attestation
  • Host Guardian Service
  • Network Policy and Access Services
  • Remote Access
  • Remote Desktop Services
  • Windows Server Update Services
  • BitLocker Drive Encryption
  • BitLocker Network Unlock
  • Group Policy Management
  • Remote Server Administration Tools (RSAT)
  • Windows Defender Features (installed by default)
  • Windows PowerShell (installed by default)

The following URL provides a complete list of all Windows Server 2019 roles and features available for deployment:

Reducing the Windows Server footprint

Any opportunity where unnecessary roles and features can be reduced, or actions that can be enforced to limit the amount of direct interaction with the server, should be taken. For example, if Windows Server Core has a role for Active Directory Domain Services, it is recommended to deploy it using Server Core. Once deployed as a Core version, this role can be fully managed through remote tools such as PowerShell, RSAT or Windows Admin Center. This significantly reduces your threat footprint. Most of the roles and features included with the Desktop Experience are also supported by Server Core.

The following URL provides a complete list of all Windows Server Core roles and features available for deployment:

Installing Nano Server 2019

Nano Server is the newest installation option and has fewer roles to choose from but is the most secure option. Nano Server can only be managed remotely using tools such as PowerShell, Windows Remote Management (WinRM), and Windows Management Instrumentation (WMI).

The following URL provides a complete list of all Nano Server roles and features available for deployment:

Hardening server roles and features should be included in your baselines and will differ, depending on the roles you have installed. These differences are provided in the CIS Benchmarks and Windows Security baselines that we covered in Chapter 2, Building a Baseline. CIS provides specific benchmarks that include specifics for Microsoft IIS Server and Microsoft SQL Server, in addition to many others. The Windows Security baselines provide hardening recommendations for domain controllers, in addition to the foundational Windows server baseline. Each server will have unique use cases with different datasets that need to be identified and protected correctly.

Let's walk through the installation of the Windows Server Update Services (WSUS) on a Windows Server 2019 Core edition. To install it, complete the following steps:

  1. Create your Windows Server 2019 Core machine with your defined baseline and configure it with your standard build document; for example, domain join and apply updates.
  2. Log in to your Windows Core machine. You will be presented with the command prompt. Type PowerShell to open PowerShell.
  3. Type Install-WindowsFeature UpdateServices and hit Enter.
  4. The installation will take a few minutes. Once complete, you will see the following screen:

Figure 10.1 – Installing the WSUS Windows feature in Server Core

That completes the base installation of the WSUS feature on the Windows Core server, which wasn't difficult at all. We will complete the configuration in the next section, Configuring Windows updates.

We have just provided an overview of the Windows server roles and features and the importance of reducing the footprint by using Server Core or Nano Server where applicable. Next, we will look at configuring Windows updates using Windows Server Update Services and Azure Update Management.

Configuring Windows updates

To manage Windows updates for your servers, Microsoft has a well-known tool named Windows Server Update Services (WSUS). For your traditional and IaaS environments, WSUS provides the tools needed to deploy and update your servers as updates are released. Due to moving into the cloud world with Azure, Microsoft now has an Update Management solution as part of Azure Automation. Update Management allows you to manage your servers, both Windows and Linux, within your cloud and on-premises environments. An overview of WSUS was provided in Chapter 3, Server Infrastructure Management within the Using Windows Server Update Services subsection of the Understanding Windows Server management tools section.

Implementing Windows Server Update Services (WSUS)

First, we will review WSUS and how to use it as a follow-up from installing the feature within Windows Server Core earlier in this chapter. Before we access the management console, we will need to run through a few tasks to complete its setup. Let's get started:

  1. Log back in to your Windows Core WSUS server and type PowerShell to open PowerShell.
  2. Type each of the following commands one at a time to complete the setup process:

    New-Item -Path "c:\" -Name "WSUS" -ItemType "directory"

    CD "C:\Program Files\Update Services\Tools"

    .\wsusutil.exe postinstall CONTENT_DIR=C:\  "WSUS"


The following guide provides instructions on how to configure and enable SSL for your WSUS environment:

To configure WSUS on the Windows Server Core server, we will need to access a Windows client or server to install the WSUS management tools. To install the WSUS management tools on a Windows 2019 Server, complete the following steps:

  1. Log on to a Windows server used for management and open Server Manager.
  2. Click on Manage and then click Add Roles and Features.
  3. Click Next, click Next, click Next, and finally, click Next (leave everything with the default settings until you get to Features).
  4. Scroll down to Remote Server Administration Tools and expand the menu, expand the Role Administration Tools menu, and then select Windows Server Updates Services Tools.
  5. Click Next, click Install, and then click Close once complete.

Next, we will connect to the Windows Server Core WSUS server and configure it:

  1. On the management server, search for and open Windows Server Update Services.
  2. Click Connect to Server to open the dialog box, as shown in the following screenshot:

    Figure 10.2 – Connecting to the WSUS server

  3. Enter the Windows Server Core name or IP that was configured, leave the port as 8530 if SSL is not set up (it is recommended to set up SSL), and then click Connect.
  4. In the WSUS Configuration Wizard, click Next, and then Next again. If this is your first WSUS server, select Synchronize from Microsoft Update and then click Next.
  5. If you're using a proxy, select Use a Proxy and then enter the required information. If not, leave this unchecked and click Next. Then, click Start Connecting (this step may take a while to complete).
  6. Once complete, click Next, select the Languages needed, and click Next.
  7. Select all the products you need to update and click Next.
  8. Select Classification of Updates to download it. At a minimum, select Critical Updates and Security Updates. Then, click Next.
  9. Select Synchronize automatically and schedule your first sync (Outside of Business hours). Select how many times you wish to sync per day and click Next.
  10. Select Begin initial synchronization and click Next. Click Finish to view the management console. This can be seen in the following screenshot:

Figure 10.3 – WSUS Management Console

Additional configurations, including modifying the configured settings during setup, can be viewed by clicking on Options within the management console.

Next, we will work through the configurations needed to update your clients. First, we will create a computer group that can be used to test updates. You can create as many groups as needed to organize your servers. To create a group, navigate and expand the Computers menu, right-click All Computers, and then click Add Computer Group…. Name your group and then click Add.

Now, we will configure WSUS so that it uses Group Policy in order to efficiently manage the autoconfiguration of the servers. To do this, go to Options within the management console and then click on Computers. Change the option to Use Group Policy or registry settings on computers and then click OK.

Now, we are ready to configure Group Policy so that it instructs your Windows servers where to connect to (WSUS server) for Windows updates, along with additional configuration for the servers:

  1. Access your Group Policy Management Console and create a new GPO or use a current one.
  2. Edit the GPO, browse to Computer Configuration, Policies, Administrative Templates, Windows Components, and select Windows Updates.
  3. Enable the following three settings:

    Configure Automatic Updates: Configure this to the preference of your organization.

    Specify intranet Microsoft update service location: Add your WSUS server to (in the format of http://servername:8530 for HTTP and :8531 for HTTPS) both the Set the intranet update service for detecting updates and Set the intranet statistics server fields.

    Enable client-side targeting: This is the group name you created within the WSUS management console for testing or to organize your clients if needed.

    The following screenshot shows the three settings you need to configure within GPO to force WSUS to be the update server for your Windows servers:

    Figure 10.4 – Group Policy configuration

    Now that the servers have been configured to connect to the WSUS server, the last step is to approve and push the updates to the clients.

  4. From the WSUS management console, browse to Updates and click Updates needed by computers on the main screen. Select all the available updates that need to be deployed, right-click, and then click Approve to open the Approve Updates dialog box, as follows:

    Figure 10.5 – Approving WSUS updates for installation

  5. Click the group you would like to deploy to (your test group, if it's the first time you're installing the patch), select Approved for Install, and click OK. The updates will be installed at the scheduled time you configured within Group Policy.

Automatic approval rules can be specified if desired. Different automatic approval rules can be configured based on your groups, and deadlines can be applied to force the installation according to a specific time period. Automatic approval rules can reduce the administrative overhead of managing a WSUS environment and ultimately save time. Good candidates for automatic approval rules include critical security updates or antivirus definition updates. When creating a rule, you can specify the properties and conditions for an update to determine whether it passes the approval rule. These properties include the specific classification (such as critical updates, drivers, feature packs, and definition updates), a specific product, and the ability to set a deadline for installation following approval.

A good use case for automatic approval rules would be to deploy critical updates automatically to a group of servers to validate the fact that updates don't break business processes and then manually deploy them to the rest of your systems.

To set up automatic approvals, browse to Options within the WSUS management console and click on Automatic Approvals to set up and configure your automatic rules.

Next, we will review the Azure Update Management solution. Azure Update Management can be used to expand WSUS capabilities to the cloud and includes support for Linux servers and Windows, both on-premises and in Azure. In addition, Azure Update Management is provided as a service within Azure and can eliminate the need for additional server infrastructure to run WSUS.

Deploying Azure Update Management

In order to use Azure Update Management, you are going to need the following:

  • Log Analytics Workspace, to collect and analyze the data.
  • Azure Automation Account, to be able to configure Azure Update Management.

To get started, you'll need to create a Log Analytics and Azure Automation Account, if you don't already have one:

  1. Log in to and search for Automation Accounts.
  2. Click Add and enter Name, Subscription and Resource Group, and Location.
  3. Choose Yes to create an Azure Run As account and click Create, as shown in the following screenshot:

    Figure 10.6 – Adding an automation account in Azure

  4. Once the automation account has been created, click on it to access it.
  5. Click on Update Management within the Log Analytics Workspace section, click the drop-down menu, select Create New Workspace if you don't already have one to use, and click Enable.
  6. Once complete, click back on Update Management in the blade column to get to the management screen, as follows:

Figure 10.7 – Azure Update Management console

Now that Update Management is set up, we can enable a VM. To enable a VM within Azure, you have two options:

  • From within the VM settings in Azure, click on Update Management and then click Enable.
  • From within the Update Management console, click on Add Azure VMs. Select the VMs you would like to enable and then click Enable.

Once enabled, it can take up to 6 hours for the data to become available. Once available, you will see the updates that have been installed, those that are missing, and so on, as shown here:

Figure 10.8 – Azure Update Management console with statistics


The following article provides troubleshooting advice for Update Management:

To add non-Azure VMs, you will need to install an agent on the machines. This will allow them to connect to Azure Log Analytics so they can be managed for updates. To do this, complete the following steps:

  1. Open the Log Analytics workspace connected to your Automation Account.
  2. In the Overview section, click Windows, Linux and other sources under Connect a data source.
  3. Within Connected Sources, Windows Servers, download the 32- or 64-bit Windows agent and make note of the Workspace ID and Key:

    Figure 10.9 – Log Analytics agent download

  4. Log on to Windows Server and install the downloaded agent.
  5. Once Windows Server checks into Azure, you may need to enable Update Management. To do this, browse back to the Update Management console within your Automation Account and click Manage Machines.

    To deploy updates to your servers, you will need to set up a Deployment Schedule. To set up a Deployment Schedule, complete the following steps:

  6. Open Update Management from Automation Accounts and click on Schedule update deployment.
  7. Complete the set up by providing the required information to create your new update deployment, as shown in the following screenshot:

    Figure 10.10 – Creating a new update deployment in Update Management

  8. Click Create once you're finished.

Once your schedule has been deployed, updates will deploy to the clients, and the Update Management console will inform you once your servers are compliant. This can be seen in the following screenshot:

Figure 10.11 – Azure Update Management console with a compliant server


You will want to schedule a frequent update deployment schedule for definition updates if you have Windows Defender deployed.

To learn more about Update Management and understand the additional options, take a look at this document repository:

We have just provided two different options for deploying security updates using WSUS and Azure Update Management. Next, we will look at onboarding servers to Microsoft Defender ATP to take advantage of the advanced threat protection services.

Connecting to Microsoft Defender ATP

Microsoft Defender ATP was initially designed to support the Windows 10 OS, but now has extended support to include versions of Windows server. This includes servers that use Windows Defender Antivirus, as well as System Center Endpoint Protection. The following servers support onboarding to the Microsoft Defender ATP service:

  • Windows Server 2008 R2 SP1
  • Windows Server 2012 R2
  • Windows Server 2016
  • Windows Server, version 1803
  • Windows Server 2019

The official Microsoft documentation for Microsoft Defender ATP, including an overview of its features, can be found at this link:

There are two methods supported that allow you to onboard Windows Server 2016 and lower. You can automatically onboard with Azure Security Center (ASC) using an Azure VM extension or deploy and configure the Microsoft Monitoring Agent to report data to Microsoft Defender ATP. If you use the Azure Security Center option, there will be additional cost considerations as the Log Analytics workspace you configure must be using the Security Center Standard tier. Azure Security Center is a great automated option if your VMs are hosted in Azure and if auto provisioning is enabled to enroll VMs to ASC.

Now, let's look at how to onboard Windows Server 2019 with Group Policy, as well as Configuration Manager.

Onboarding with Group Policy

In order to use Group Policy to onboard Windows Server 2019, download the onboarding package from the Microsoft Defender Security Center portal. Follow these steps to create the GPO to onboard machines:

  1. Log in to the Microsoft Defender Security Center portal at
  2. Choose Settings and select Onboarding from the Machine management section.
  3. Choose Windows Server 1803 and 2019 for your OS and select Group Policy from the Deployment Method. Then, click Download Package.

    Create a network share somewhere in the domain that has been given read-only access by the machines being targeted for ATP onboarding and extract the package's content. Inside the ZIP file will be a .cmd file named WindowsDefenderATPOnboardingScript.cmd, as shown in the following screenshot:

    Figure 10.12 – Windows Defender ATP onboarding package extracted

  4. Open Group Policy Management Editor, create a new policy, and link it to the OU where the Windows server objects in the scope reside. Give it a friendly name, such as Windows Server – Defender ATP Onboarding.
  5. Go to Computer Configuration >Preferences > Control Panel Settings and right-click Scheduled Tasks. Select New and choose Immediate Task (At least Windows 7). Give it a friendly name such as Defender ATP Onboarding.
  6. Under Security Options, select Change User or Group and type in SYSTEM. Click Check Names and choose OK.
  7. Select the radio button next to Run whether user is logged on or not.
  8. Choose Run with highest privileges, as shown in the following screenshot:


    Figure 10.13 – Creating a scheduled task with Group Policy

  9. In the Actions tab, click New and validate that Start a program is selected.
  10. Go to the path where you extracted the WindowsDefenderATPOnboardingScript.cmd file. Hold Shift, right-click, and choose copy as path. Paste the path into the Program/Script field and click OK. Click OK again to commit the change.

    The New Action settings should appear as follows:


    Figure 10.14 – Configuring a new action for a scheduled task

    Once the scheduled task has been configured, you will see it appear in the Scheduled Tasks section of the GPO:

    Figure 10.15 – Scheduled Tasks section configured to run in a Group Policy object

  11. Close any open GMPC windows.

There is no method available for monitoring deployments using Group Policy for your machines. Typically, machines onboard within 24 hours, but it can take several days for telemetry data to flow. To view the machine's status, go to the Microsoft Defender Security Center portal at, click Machines from the navigation panel list and search for the hostname of a recently onboarded machine in the search bar, as follows:


Figure 10.16 – Windows Server machines reporting to Defender Security Center

Next, let's look at how to use Microsoft Defender ATP policies in Configuration Manager to onboard Windows Server.

Onboarding with Configuration Manager

As mentioned previously in the Onboarding with Group Policy section, you will need to download and extract the Configuration Manager-specific package from the Microsoft Defender Security Center portal. To deploy the onboarding package, you will need to use the Microsoft Defender ATP policies node of Assets and Compliance by following these steps:

  1. Log in to the Microsoft Defender Security Center portal at
  2. Choose Settings and select Onboarding in the Machine management section.
  3. Choose Windows Server 1803 and 2019 for the OS and select System Center Configuration Manager from the Deployment Method section. Choose Download Package.
  4. Extract the ZIP package to a deployment share used by SCCM to deploy apps and packages and open the System Center Configuration Manager console on the Site server. In these instructions, we are using version 1906.
  5. Go to Assets and Compliance, expand Endpoint Protection, choose Microsoft Defender ATP Policies, and click Create Microsoft Defender ATP Policy. The Create Microsoft Defender ATP Policy Wizard window will open, as shown in the following screenshot:

    Figure 10.17 – Creating a Defender ATP policy in Configuration Manager

  6. Enter a friendly Name, Description, and choose Onboarding as the policy type. Then, click Next.
  7. Select Browse and select the extracted WindowsDefenderATP.onboarding file you extracted earlier. Notice that the Organization ID of your Microsoft Defender ATP subscription auto-fills. Click Next, as follows:


    Figure 10.18 – Importing the Defender ATP configuration file

  8. Leave the defaults configured on the Agent Configuration menu. Click Next.
  9. Click Next again to finish the Microsoft Defender ATP Policy Wizard and click Close.
  10. Right-click the policy and click Deploy. Choose a collection that will target your Windows 2019 servers.

We just covered how to onboard Windows servers to the Microsoft Defender ATP service using both Group Policy and Configuration Manager. Next, we will review the Windows server hardening configurations that are available and cover how to use Azure Disk Encryption to encrypt VMs.

Hardening Windows Server

Ensuring your Windows servers are properly hardened is critical to maintaining a good security posture and minimizing the attack surface. A best practice for Windows server is to only enable the roles and services required to perform necessary functions and to lock down the network to only allow the required ports and sources to communicate. Next, we will look at implementing a security baseline. We will cover how to implement the Microsoft Security and Compliance toolkit recommended baseline for member servers, discuss network access controls and the various logon types used to access servers, configure inactivity timeouts for interactive sessions, and configure account lockout policies. Finally, we will discuss implementing a fine-grained password policy in order to enforce strict requirements to highly privileged accounts and securing the logon process before learning about how to use Azure Disk Encryption to encrypt data on VMs that live in Azure.

Implementing a security baseline

With any good security program, it's important to have a foundation that consists of clearly defined policies, standards, procedures, and guidelines and ensure they are in place and enforced. Security baselines are more than just a set of configurations that apply to devices. They can encompass an entire program that includes collaboration with many teams, as well as support and backing from leadership stakeholders. In Chapter 2, Building a Baseline, we covered these concepts and discussed their importance, and provided an overview of the different frameworks seen today. We also discussed using baseline controls from Center for Internet Security (CIS) and Microsoft to build the specific configurations that apply to your Windows servers.

Next, we will look at implementing the Windows Server 2019 Member server baseline from the Security and Compliance Toolkit and apply it with Group Policy. In addition, we will cover enforcing additional recommendations, as specified in the CIS benchmarks. To download the CIS benchmark for Windows Server 2019, visit this link:


We strongly recommend downloading and reviewing the CIS Windows server benchmarks and comparing them to the Microsoft recommendations.

To download the Microsoft Security and Compliance Toolkit baselines, visit this link and choose the Windows 10 Version 1909 and Window server Version 1909 Security files:

On a workstation that has access to modify Group Policy, extract the downloaded ZIP file. To import the Member server baseline, follow these steps:

  1. Open Group Policy Management Editor. Create a GPO that is linked to an OU that contains Member servers. Give it a friendly name such as Tier 0 W2019 Member Server.
  2. Click on the Group Policy Objects folder and find the GPO you created previously. Right-click and choose Import Settings.
  3. Click Next twice and choose Browse. Navigate to the GPO folder of the extracted ZIP file and click OK. Then, click Next.
  4. Select the MSFT Windows Server 1909 – Member Server policy and click Next. Click Next again. Click Next on Migrating References to copy them identically from the source. Then, click Finish.
  5. Click OK to finish importing the policy settings.

The documentation folder from the extracted ZIP file contains an Excel spreadsheet of all the policy settings and descriptions of them. The GP reports folder contains HTML extracts of the GPO if you need to review them in a reader-friendly format.

In order to report compliance on the security baseline, you can use a management tool such as Configuration Manager and monitor the settings. We covered how to do this in Chapter 8, Administration and Remote Management, in the Creating a configuration baseline from a GPO section.

Microsoft used to support a tool called Security Compliance Manager (SCM). It was used to compare GPO-based security configurations and provide recommendations for baselines on Windows servers. Unfortunately, this tool has been retired and many organizations have started using other means to manage these configurations. One popular option is Windows PowerShell Desired State Configuration (DSC). DSC is useful for maintaining a configuration base for resources to help ensure that systems remain in the state outlined in the configuration. For more information about PowerShell DSC, visit this link:

If your servers are running in Azure, there is a VM extension that supports Azure Desired State Configuration (DSC). More information about Azure DSC can be found here:

Next, let's look at enforcing and modifying some of the preconfigured Microsoft recommended baselines, as outlined by the CIS benchmarks.

Controlling User Rights Assignment

User Rights Assignment policies define the ways a user or service can log on and interact with a server. They apply locally to each server and include authorizing a user to log on, as well as the permissions that they can control access to. User Rights Assignment policies can be found under Computer Configuration > Windows Settings > Security Settings > Local Policies > User Rights Assignment. According to the CIS benchmark for Windows Server 2019, the policy configurations in the following table are recommended in addition to the default Microsoft Security Baseline:

Figure 10.19 – Recommended User Rights Assignment settings

Once the User Rights Assignment policies have been set, the built-in local security groups can be managed by using Restricted Groups. This will allow you to specify what domain-based security groups will be members of the built-in local security groups on each server. To modify a Restricted Groups Group Policy and add a domain group called T0-Operators to the Administrators group, follow these steps. You will need to be editing a Group Policy object to do so:

  1. Go to Computer Configuration > Windows Settings > Security Settings > Restricted Groups. Then, right-click and choose Add Group.
  2. Click on Browse and search for the T0-Operators group. Click Check Names. Once the group is found, click OK. Click OK again on the Add Group menu.
  3. On the Properties menu, click Add next to the "This group is a member of" selection. Click Browse, type in Administrators, and choose Check Names. Click OK.
  4. Click OK on the Properties menu to commit the changes, as shown in the following screenshot:

Figure 10.20 – Modifying a Restricted Groups Group Policy

After Group policy has had a chance to process, you will see that the group has been added to the Built-in Administrators group in Local Users and Groups on the server, as shown in the following screenshot:

Figure 10.21 – Administrators Group on a server


If a user is added manually to a built-in group and is not a member of the domain group or added through the Restricted Groups policy, they will be removed on the next policy sync.

Next, we'll look at configuring Accounts security settings.

Configuring Accounts settings

It's important for a good security and access strategy to implement policies around the types of accounts that are available to log in to your servers. Identity and Access Management is a critical piece to the overall security framework, and we want to ensure that this is locked down in the local policy settings. Accounts policies can be found under Computer Configuration > Windows Settings > Security Settings > Local Policies, Security Options. We recommend setting the following policies compared to the Microsoft baselines:

Figure 10.22 – Recommended Accounts policy settings for local policies


Be mindful when disabling the Administrator account. If the member server and domain controller lose the connection to authenticate securely, there may be no local account available to log in with.

Next, we'll look at configuring Interactive Logon security settings.

Configuring Interactive Logon

An interactive logon is when a user logs into a server using a Local or Domain account by supplying credentials or using a smart card or form of biometrics. In an interactive logon scenario, the user may have physical access to the server or remotely through terminal services and Remote Desktop Services (RDS). The latter is known as remote interactive. Interactive Logon policies can be set under Computer Configuration > Windows Settings > Security Settings > Local Policies > Security Options. The settings shown in the following table are additional recommendations compared to the Microsoft baselines:

Figure 10.23 – Recommended settings for Interactive Logon scenarios

Next, we'll look at configuring a Remote Desktop Protocol timeout limit. This will help ensure that any idle account will be disconnected from your servers, thus increasing security as well as freeing up system resources.

Setting Remote Desktop Protocol session time limits

Setting the Remote Desktop Protocol (RDP) session time limits keeps idle users from tying up resources. This helps prevent password lockouts, especially if a Privileged Access Management (PAM) solution has been deployed with password rotation functionality. It can also free up available sessions for servers not configured with an RDS license that can only handle a few concurrent sessions. Remote desktop session time limits can be set under Computer Configuration > Policies > Administrative Templates > Windows Component > Remote Desktop Services > Remote Desktop Session Host > Session Time Limits. The recommendations shown in the following table are in addition to the Microsoft baseline:

Figure 10.24 – Session time limits for Remote Desktop Protocol

Additionally, you can force users' sessions to log off instead of disconnecting. To do this, set the End session when time limits are reached policy to Enabled.

Next, we'll look at configuring account policies such as an account lockout policy and a password policy for the domain.

Configuring account policies

Typically, account policies are applied at the domain level in the default domain policy. There can only be one account policy defined in each domain. If any other policy is created in a down level OU and not linked to the root of the domain, it will only affect the local accounts on the member servers. When deploying Active Directory Domain Services, there are default values that are configured in the default domain policy. Let's look at the default values, as well as additional recommendations not set in the default domain policy.

The following screenshot shows the recommendations for a Password Policy:

Figure 10.25 – Default domain policy – Password Policy

From the preceding screenshot, we can see the following:

  • Maximum password age: 365 days
  • Minimum password length: 14 characters


    Based on recent research, data, and recommendations from NIST, Microsoft, and others, the latest password recommendations are to remove periodic password change requirements and to only change a password in case of potential threat or compromise.

Now, let's look at modifying the Account Lockout Policy. The recommended settings can be seen in the following screenshot:

Figure 10.26 – Recommended Account Lockout Policy

From the preceding screenshot, we can see the following:

  • Account lockout duration: 15 minutes

Leaving this setting as 0 will require an administrator to manually unlock an account if it's locked out, leading to increased calls to the support desk. Setting a duration can also help mitigate a potential denial of service (DoS) attack.

  • Account lockout threshold: 10 invalid logon attempts

Setting a lockout threshold helps to prevent successful brute-force attacks by triggering an account lockout. The account will remain locked out for the duration set.

  • Reset account lockout counter after: 15 minutes

This setting determines how long before the threshold resets back to 0. Keep this setting aligned with the lockout duration. The default settings could be vulnerable to DoS attacks and can lock out users in your environment permanently until they're manually unlocked by an administrator.

If setting one password policy for your domain isn't enough to meet your compliance needs, domain administrators can use fine-grained password policies or Password Settings Object (PSOs) to more granularly apply a password policy. Let's look at implementing PSOs.

Implementing fine-grained password policies

In addition to the default domain policy, if there is a requirement to deploy additional password polices, then a fine-grained password policy can be configured. Examples of this would be to enable stronger password requirements for your privileged accounts compared to your standard user accounts, in addition to a separate one for your service accounts. FGPPs are set in PSOs and not Group Policy. Unlike the default domain policy, PSOs are applied directly to users or security groups. We covered how to implement PSOs in detail in Chapter 7, Identity and Access Management, in the Securing your passwords section.

To configure a PSO, open Active Directory Administrative Center and click on Tree view. Expand the domain, go to System container, and find Password Settings Container. Click New, Password Settings under Tasks to create a new PSO. The following screenshot shows a password policy targeted at the Domain Admin security group:

Figure 10.27 – Fine-grained password policy in Active Directory

We just covered how to implement security settings related to account policies, interactive logons, and password settings. Next, we'll look at how to secure the logon process and lock screen for Windows Server.

Securing the logon process

Securing the logon process can help to reduce risk by limiting the amount of information that is available when logging on. Securing these settings will eliminate the enumeration of users, hide account details, and limit interaction with networks on the login screen. The following table shows the additional recommendations not enforced in the Microsoft baseline:

Figure 10.28 – Recommended login processes

Important note

When using picture password sign-in or a convenience PIN, the domain password is cached in the system vault.

Many of these settings are disabled by default and not configured in Group Policy. It's best to enforce them to ensure that a user with administrative access does not modify the default settings. Next, we will discuss how to encrypt server disks using Azure Disk Encryption and how to store keys in Azure Key Vault for recovery key management.

Using Azure Disk Encryption

Historically, both Windows PCs and Windows servers have leveraged BitLocker Drive Encryption and on-premises management solutions such as Microsoft BitLocker Administration and Monitoring (MBAM) to handle the storage and administration of recovery keys. BitLocker settings are typically configured and managed with Group Policy and PowerShell. For Windows Server 2012 and later, BitLocker Drive Encryption can also be enabled through the Add Roles and Features Wizard of Server Manager. Recently, Microsoft has announced that MBAM will no longer be developed and has offered extended support up until 2024. Due to the end of life of MBAM, it is strongly recommended to move your BitLocker administration workloads to Azure.

For Windows server virtual machines in Azure, disk encryption can be accomplished by using Azure Disk Encryption. Azure Disk Encryption is for Windows VMs and provides BitLocker encryption for both OS and data disks. It uses Azure Key Vault to store secrets and keys and securely wraps encryption secrets using a key encryption key (KEK). For Windows Server 2012 version 1511 or later, the XTS-AES 256-bit encryption method is used. Let's look at how to create an Azure Key Vault. Then, we can use it to hold BitLocker Encryption Keys (BEK) for drive recovery.

Creating an Azure Key Vault

To create an Azure Key Vault, we will be using the Azure PowerShell Az module. Information about the Az module, including installation instructions, can be found at this link:

Open PowerShell as an administrator and install and import the Azure Az module by following these steps:

  1. Type Connect-AzAccount, press Enter, and input your username and password. Then, accept the MFA challenge.

    We will be using an existing resource group called RG-Identity-Prod to create the Key Vault. If you do not have a resource group, you will need to create one.

  2. Use the following cmdlet to create a Key Vault named Prod-KeyVault-USE2 and set the -EnabledForDiskEncryption flag:

    New-AzKeyvault -name "Prod-KeyVault-USE2" -ResourceGroupName "RG-Identity-Prod" -Location "eastus2" -EnabledForDiskEncryption

If the command completed successfully, the Key Vault can be viewed inside the g from the Azure portal, as shown in the following screenshot:

Figure 10.29 – Resources inside a resource group from the Azure portal

Next, we'll create a KEK. This key will be used to wrap encryption secrets before writing them to the vault. This adds an additional layer of protection for encryption keys.

Creating a key encryption key (KEK)

Using the same PowerShell Az module, create a new KEK by following these steps when using the Add-AzKeyVaultKey cmdlet.

Type in the following cmdlet to create a KEK named IdentityKEK for the Key Vault we created previously:

Add-AzKeyVaultKey -name "IdentityKEK" -VaultName "Prod-KeyVault-USE2" -Destination "Software"


Azure Key Vault supports RSA encryption. Currently, Hardware Security Modules (HSMs) are only supported in the premium pricing tier for Azure Key Vault.

Next, we'll enable the virtual machine disk encryption extension on a VM named WSHUSE2DC01 in the RG-Identity-Prod resource group using the KEK and Key Vault we created previously.

Enabling Azure Disk Encryption on a virtual machine

To enable Azure Disk Encryption, we will be leveraging the same PowerShell Az module that we used previously. To follow along with these steps, open PowerShell ISE as an administrator and connect to Azure using the Connect-AzAccount cmdlet:

  1. First, let's define the variables for the resource group, Key Vault, KEK, and VM name. Then, we will run Set-AzVMDiskEncryptionExtension to encrypt all disks, sign the secret with the KEK, and store it in the Key Vault:

    $Rg = "RG-Identity-Prod"

    $KeyVault = Get-AzKeyVault -VaultName "Prod-KeyVault-USE2" -ResourceGroupName $Rg

    $VaultKEK = Get-AzKeyVaultKey -VaultName "Prod-KeyVault-USE2" -Name "IdentityKEK"

    $WinVM = "WSHUSE2DC01"

  2. Next, run the Set-AzVMDiskEncryptionExtension cmdlet with the following flags and variables:

    Set-AzVMDiskEncryptionExtension -ResourceGroupName $Rg -VMName $WinVM -DiskEncryptionKeyVaultUrl $KeyVault.VaultUri -DiskEncryptionKeyVaultId $KeyVault.ResourceId -KeyEncryptionKeyVaultId $KeyVault.ResourceId -KeyEncryptionKeyUrl $vaultKEK.Id -SkipVmBackup -VolumeType All

  3. Click Yes if prompted by the Enable AzureDiskEncryption on the VM prompt warning stating that encryption may take 10-15 minutes and may prompt the virtual machine to reboot:

    Figure 10.30 – Enable AzureDiskEncryption on the VM warning prompt

  4. Once the process is complete, an output will be returned with an IsSuccessStatusCode that should read True. This can be seen in the following screenshot:

Figure 10.31 – PowerShell output showing Success status code

To validate the fact that encryption has been enabled, log in to the Azure portal and open the VM overview pane. In the Extensions blade, the AzureDiskEncryption extension will have a status of Provisioning Succeeded. If you click on the Disks option under Settings, encryption should be Enabled.

Finally, if you open the Key Vault, the BitLocker Encryption Key (BEK) will be stored under the Secrets blade, under Settings, as shown in the following screenshot:

Figure 10.32 – Encryption secret stored in Azure Key Vault

For more information about Azure Disk Encryption, visit this link:

Now that we have covered enabling Azure Disk Encryption and using Key Vault to store recovery keys, we'll look at creating a code integrity policy. Using Windows Defender Application Control (WDAC), you can deploy a code integrity policy whitelist that controls what applications can run on your servers. This greatly reduces the attack surface by denying unknown processes.

Deploying Windows Defender Application Control

WDAC adheres to a zero-trust model and only allows whitelisted, digitally signed software to run on Windows systems. WDAC uses a Configurable Code Integrity (CCI) policy to act as the whitelist configuration. When combining WDAC with virtualization-based security hypervisor isolation and UEFI Secure Boot, the technology is collectively known as Device Guard. Windows Defender Application Control can be managed with Group Policy, Configuration Manager, and Intune and can be configured with PowerShell. The Audit-only enforcement mode logs events to Event Viewer for analysis before enforcing the policy on endpoints.


It's extremely important to understand the effects of deploying a WDAC policy in your environment. We strongly encourage you to read the Microsoft Policy Design guide and build a strategy that fits your environment's needs before deploying a policy. Information about designing a policy can be found at this link:

When creating a WDAC policy, the whitelisting rules that can be defined are based on the following conditions:

  • Attributes of a code-signing certificate
  • Attributes of an app's binaries that come from metadata (original filename, version, or hash)
  • The apps' reputation, as defined by Microsoft Intelligent Security Graph
  • The process that launched the app or the path where the process or file is located

If your organization has customized line-of-business applications, Microsoft recommends signing the application and avoiding using the hash from the app's binaries. Otherwise, the CCI policy will need to be updated each time the app receives updates.

Application and catalog signing can be accomplished using the following methods:

  • An internal digital certificate or Public Key Infrastructure (PKI)
  • Employing a third-party signing authority such as Entrust, DigiCert, or GlobalSign
  • The Windows Defender Device Guard signing portal through the Microsoft Store for Business

In a well-controlled environment with good application management, a reference system can be used to build a WDAC template policy. Once the policy has been built and tested on the referenced system, it can be deployed to other systems in audit mode and analyzed further. After this discovery has taken place, all the audited policies can be merged, set to enforced, and deployed to the environment.

Now, let's look at how to build a reference policy from a clean Windows server source. We will deploy the default Windows base policy in audit mode. Follow these steps:

  1. In File Explorer, create a new directory on the root of the OS drive called WDAC.
  2. Go to C:\Windows\schemas\CodeIntegrity\ExamplePolicies. Copy the DefaultWindows_Audit.xml policy and paste it into the C:\WDAC directory. Rename it something friendly such as WSHMemberSVR_CIPolicy.xml.
  3. Open PowerShell ISE as an administrator. Next, we are going to create a variable for the policy file called $PolicyFile, as follows:

    $PolicyFile = "C:\WDAC\WSHMemberSVR_CIPolicy.xml"

  4. For version control, we need to assign a unique ID, name, and version using the Set-CIPolicyIDInfo and Set-CIPolicyVersion cmdlets. Then, we will run the following command:

    $PolicyFile = "C:\WDAC\WSHMemberSVR_CIPolicy.xml"

    Set-CIPolicyIDInfo -FilePath $PolicyFile -PolicyName "WSHMemberSVR_CIPolicy"

    Set-CIPolicyVersion -FilePath $PolicyFIle -Version "1.0.0"

    Open the XML file. The version number you set previously will be under <VersionEx>, while the policy name will be under the PolicyInfo setting provider. Toward the top of the XML policy is where the enforcement rules are defined. Let's set a few additional rules to enable the Microsoft Intelligent Security Graph and managed installer options. Information about the WDAC policy rules options can be found at this link:

  5. Run the following command using the Set-RuleOption cmdlet to enable the option 13 and 14 rules:

    $PolicyFile = "C:\WDAC\WSHMemberSVR_CIPolicy.xml"

    Set-RuleOption -FilePath $PolicyFile -Option 13

    Set-RuleOption -FilePath $PolicyFile -Option 14

  6. Next, convert the policy file into a binary file using the ConvertFrom-CIPolicy cmdlet:

    ConvertFrom-CIPolicy $PolicyFile "C:\WDAC\WSHMemberSVR_CIPolicy.bin"

    In order to apply the policy, the .bin file will need to be placed on a network share that servers can access. Since we are building a reference WDAC policy, we can leave it in the path from the ConvertFrom-CIPolicy cmdlet.

  7. Open Local Group Policy Editor, go to Administrative Templates > System > Device Guard, and select the Deploy Windows Defender Application Control policy.
  8. Select Enabled and enter the C:\WDAC\WSHMemberSVR_CIPolicy.bin path. Click OK. Then, restart the server.

    To see whether the .bin file has been applied, open Event Viewer and go to Applications and Services > Microsoft > Windows > Device Guard > Operational. Event ID 7010 will display if the policy was applied correctly, as shown in the following screenshot:

    Figure 10.33 – Device Guard policy applied in Event Viewer

    To view the audit events generated by the WDAC policies, go to CodeIntegrity > Operational under Applications and Services. This log file will show all the processes that tried to execute that were not specified in the WDAC policy. The AppLocker logs under Applications and Services will audit Windows Installer and script files:

    Figure 10.34 – CodeIntegrity Operational logs from Event Viewer

    Once the policy has run in audit mode for some time, the audit logs can be reviewed, exported, and merged with the base policy. Now let's look at how to create a CI policy from the Event Viewer logs and merge it with the base policy using the New-CIPolicy cmdlet.

  9. Run the following cmdlet to export the Event Viewer audit logs to a new CI policy:

    New-CIPolicy -Audit -Level Hash -FilePath "C:\WDAC\EventLog_Audit.xml" -UserPEs

  10. Next, we will set a few variables to specify the policy paths and run the Merge-CIPolicy cmdlet to combine both the original and audit log policies:

    $BasePolicy = "C:\WDAC\WSHMemberSVR_CIPolicy.XML"

    $AuditCI = "C:\WDAC\EventLog_Audit.xml"

    $CombinedCI = "C:\WDAC\WSHMemberSVR_CIPolicy_v2.xml"

    Merge-CIPolicy -PolicyPaths $BasePolicy,$AuditCI -OutputFilePath $CombinedCI

  11. Update the policy rule and version number in the XML file:

    $CombinedCI = "C:\WDAC\WSHMemberSVR_CIPolicy_v2.xml"

    Set-CIPolicyIDInfo -FilePath $CombinedCI -PolicyName "WSHMemberSVR_CIPolicy_v2"

    Set-CIPolicyVersion -FilePath $CombinedCI -Version "1.1.0"

  12. Use the ConvertFrom-CIPolicy cmdlet to convert the merged policy into a binary file:

    $CombinedCI = "C:\WDAC\WSHMemberSVR_CIPolicy_v2.xml"

    $CombinedBIN = "C:\WDAC\WSHMemberSVR_CIPolicy_v2.bin"

    ConvertFrom-CIPolicy $CombinedCI "C:\WDAC\WSHMemberSVR_CIPolicy_v2.bin"

  13. If you wish to audit the new policy before enforcing it, update the local Group Policy setting to the new .bin file. Restart the server.

    Depending on how strict you need the policy to be in order to lock down servers, a policy rule of the FilePublisher level and a fallback of the hash can be created for the entire OS drive. To do this, run the following cmdlet (assuming the OS disk is the drive letter C):

    $OSPolicyCI = "C:\WDAC\OSDrive_CI.xml"

    New-CIPolicy -ScanPath "C:\" -Level FilePublisher -Fallback Hash -UserPEs -FilePath $OSPolicyCI


    Running the New-CIPolicy cmdlet on the OS drive to complete the scan will take some time.

  14. Merge the policy rules and increment the version by following steps 10-12.

    Before enforcing the policy, it's recommended to set rule options 9, Advanced Boot Options Menu, and 10, Boot Audit on Failure. This way, if the WDAC policy blocks a driver during startup, Windows will continue to boot.

  15. To enable the Advanced Boot Options Menu and Boot Audit on Failure rule options, run the following command:

    $CIPolicyPath = "C:\WDAC\WSHMemberSVR_CiPolicy_v3.xml"

    Set-RuleOption -FilePath $CIPolicyPath -Option 9

    Set-RuleOption -FilePath $CIPolicyPath -Option 10

  16. Let's make a copy of the policy a backup and append Enforced to the end of the filename by running the following command. This will help us differentiate between the XML files:

    Copy $CIPolicyPath "C:\WDAC\WSHMemberSVR_CIEnforced.xml"

  17. To set the policy to Enforced mode, run the following command:

    $EnforcedCI = "C:\WDAC\WSHMemberSVR_CIEnforced.xml"

    Set-RuleOption -FilePath $EnforcedCI -Option 3 -Delete

  18. Convert the policy into binary format and increment the filename to keep the labeling consistent by following the steps in number 12. Make sure you rename the variable so that it points to the copied XML file where we appended Enforced in the filename. For example, the .bin file could be WSHMemberSVR_CIEnforced.bin.

    Now, we are ready to test drive the WDAC policy in Enforced mode. It is recommended to slowly roll out the policy if possible or test it thoroughly before deploying it to live production systems. When comfortable, rule options 9 and 10 can be deleted to add additional protection.

  19. To deploy the policy domain wide, copy the .bin file to a deployment share where your servers have access, such as an SCCM share.
  20. Create a GPO and link it to an OU that contains the server systems you wish to scope. Follow steps 7-8 again and replace the local path with the UNC path to the file on the deployment share.

Once the policy is enabled, you can verify that it has been read by opening Event Viewer and going to DeviceGuard > Operational under Applications and Services. Event ID 7010 will show the .bin file and Configurable Code Integrity policy = Enabled, as shown in the following screenshot:

Figure 10.35 – Device Guard Operational logs in Event Viewer

The AppLocker logs under Applications and Services will show us whether applications have been blocked as a result of the WDAC policy:

Figure 10.36 – AppLocker logs in Event Viewer

For more information regarding the full list of rules, system requirements, and tips for deployment planning, visit this link:


In this chapter, we covered how to secure Windows Server. First, we reviewed different installation options for Windows Server and looked at security enhancements with Windows Server 2019. In the next section, we discussed different server roles and features and highlighted specific roles that could be used as part of your security strategy. Then, we moved on and look at the installation of WSUS on a Windows Server Core installation.

In the next section, we covered Windows updates and how to manage and deploy them using WSUS and Azure Update Management. Then, we reviewed threat protection with Microsoft Defender ATP – specifically, how to onboard your Windows server machines to the ATP service. Afterward, we discussed hardening Windows server and walked through implementing a baseline, reviewed CIS benchmark configurations for Microsoft defaults, and discussed enabling Azure Disk Encryption. Finally, we covered how to deploy a Windows Defender Application Control policy.

In the next chapter, we will cover security monitoring and reporting. Here, we will discuss the various features of the Windows Defender ATP solution, configure alerts with Azure Monitor, review Activity Logs, and cover how to onboard servers to Log Analytics workspaces and add protection with Azure Security Center.