Managing Windows CLAT (WinCLAT) with Intune Remediations

Microsoft Intune icon

Windows CLAT (WinCLAT) allows IPv4 applications to reach IPv4 destinations on IPv6-only and IPv6-mostly networks. Windows does not permit WinCLAT on Wi-Fi or Ethernet by default, and Microsoft Intune does not currently expose a setting to permit it. This post explains how to deploy the permit setting with Intune Remediations, verify that WinCLAT is translating, and maintain connectivity to Intune when removing the setting.

WinCLAT Configuration Options in Intune

At the time of this writing, Intune does not expose WinCLAT configuration settings in the Settings Catalog or through a CSP. The corresponding Group Policy settings are defined in the built-in Windows template tcpip.admx. However, Intune’s custom ADMX import feature is intended for third-party and custom templates. Microsoft explicitly advises against importing built-in Windows ADMX files when the goal is to configure those settings, recommending the Settings Catalog or a custom profile instead.

Configuring WinCLAT with Remediations

An Intune Remediation can write the same registry value that Group Policy uses to permit WinCLAT on non-cellular interfaces. Windows reads that value as policy and gives it precedence over the local permit setting. If Group Policy already configures the setting on a device, continue managing it through Group Policy, since a policy refresh can overwrite the value written by the remediation script.

Deployment Requirements

Before deploying the Remediation, confirm that clients meet the following connectivity, platform, and licensing requirements.

Intune Connectivity Before WinCLAT Starts

The Intune Management Extension must be able to reach the endpoints it uses to retrieve the script package before WinCLAT starts. Native IPv4 provides that path on dual-stack networks and on IPv6-mostly networks where Windows still has a DHCPv4 lease. On an IPv6-only network, DNS64 and NAT64 can provide access to IPv4-only Intune endpoints by name. If the target network has no working path to the required endpoints before WinCLAT starts, deploy the package from a network that does. After deployment, verify that the device can still check in with Intune from the target network.

NetworkPath to Intune before WinCLAT is enabledExpected delivery path available?
Dual-stackNative IPv4Yes
IPv6-mostly (DHCPv4 option 108)Native IPv4. While WinCLAT is not permitted, Windows does not honor option 108 and takes a DHCPv4 leaseYes
IPv6-only with DNS64/NAT64DNS64 and NAT64Yes
IPv6-only without DNS64/NAT64No path to required IPv4-only endpoints in this scenarioNo

Windows and Intune Prerequisites

Devices must run Windows 11 version 25H2 build 26200.9550 or later, be Microsoft Entra joined or Microsoft Entra hybrid joined, and be enrolled in Intune or co-managed. Verify that device users have a qualifying license, such as Windows Enterprise E3 or E5, and that the Intune Management Extension is installed before running the package on demand.

WinCLAT Policy Settings

The WinCLAT Group Policy settings are in tcpip.admx under Computer Configuration > Policies > Administrative Templates > Network > TCPIP Settings > IPv6 Transition Technologies, and they are stored as DWORD values in the following location.

HKLM\SOFTWARE\Policies\Microsoft\Windows\TCPIP\v6Transition\IPxlatCfgSvc
Registry valuenetsh.exe settingModule propertyPurpose
PermitNonCellularCLATpermitPermitPermits WinCLAT on non-cellular interfaces
GetPrefixInfoFromRApref64fromraPref64FromRADiscovers the NAT64 prefix from the PREF64 option in router advertisements
GetPrefixInfoFromDNSpref64fromdnsPref64FromDnsDiscovers the NAT64 prefix by querying ipv4only.arpa against a DNS64 server

Interpreting WinCLAT Policy Values

Each policy value is a REG_DWORD. A value of 1 enables the setting, and a value of 0 disables it. Deleting the value returns control to the local setting. Windows allows NAT64 prefix discovery through both router advertisements and DNS by default, so the scripts in this post manage only PermitNonCellularCLAT.

Deploying the WinCLAT Remediation

Detect-WinClatPermitPolicy.ps1 compares PermitNonCellularCLAT with the desired registry state. It returns exit code 0 when the state matches and 1 when a change is needed. When detection returns 1, Intune runs Remediate-WinClatPermitPolicy.ps1 to write or remove the policy value.

Setting the Desired Policy State

Both scripts begin with a $DesiredState variable that corresponds to the three states of the Group Policy setting. Remediations do not accept parameters, so set the variable to the same value in both scripts before uploading them and create a separate Remediation for each state that is needed, such as Enable WinCLAT and Remove WinCLAT Policy.

# Enabled, Disabled, or NotConfigured. Must match the remediation script.
$DesiredState = 'Enabled'
Desired stateRegistry valueResult
Enabled1WinCLAT is permitted, and the setting is under policy control
Disabled0WinCLAT is not permitted, and the setting is under policy control
NotConfiguredDeleted, along with the IPxlatCfgSvc key if it is then emptyThe setting returns to the local configuration

Creating and Assigning the Package

Perform the following steps to create the Remediation in the Microsoft Intune admin center.

  1. Go to Devices > Manage devices > Scripts and remediations, then select Create script package.
  2. Enter a name, such as Enable WinCLAT, and upload the detection and remediation scripts with $DesiredState set to Enabled.
  3. Configure the following settings:
    1. Run this script using the logged-on credentials: No. The scripts write to HKLM and must run as SYSTEM.
    2. Enforce script signature check: No, unless the scripts are signed.
    3. Run script in 64-bit PowerShell: Yes.
  4. Assign the Remediation to a group of devices and choose a schedule. An hourly or daily schedule keeps the value in place if it is removed.
Intune Remediation script package settings

Intune Remediation script configuration settings.

Testing the Remediation on a Single Device

To test the package, open the device’s Overview page in the Intune admin center, select Run remediation, and choose the WinCLAT script package. You can run the package on demand without assigning it to the device. The device must be online, have the Intune Management Extension installed, and be able to communicate with Intune and the Windows Push Notification Service (WNS).

Run remediation action on an Intune device page

Run Remediation interactively on a specific endpoint.

Reviewing Remediation Results in Intune

On the device page in the Intune admin center, select Remediations to review the script package results. In the example below, With issues indicates that the registry state differed from the desired state, and Issue fixed indicates that the script corrected it. Verify the effective permit setting and translation state separately on the client.

Intune device Remediations results showing With issues and Issue fixed

Remediation results.

WinCLAT Activation After Remediation

Applying the permit policy allows Windows to start WinCLAT automatically on eligible interfaces. What happens next depends on whether the interface already has a native IPv4 address and whether Windows can discover a NAT64 prefix.

IPv6-Only Networks

On an IPv6-only test network, WinCLAT begins translating about a minute after the script writes the permit value, without a reboot, Group Policy refresh, or service restart. The instance uses an address from the IPv4 Service Continuity Prefix (RFC 7335), typically 192.0.0.1. Automatic activation requires an eligible interface with a Stateless Address Autoconfiguration (SLAAC) address, a discoverable NAT64 prefix, and autoenable enabled. The policy value persists across reboots.

IPv6-Mostly Networks

On an IPv6-mostly network, Windows already has a DHCPv4 lease when the remediation runs. Neither applying the permit policy nor running ipconfig /renew releases the existing lease. After the adapter restarts, Windows honors DHCPv4 option 108 (IPv6-Only Preferred), comes up without a native IPv4 address, and starts translating within seconds. For a production rollout, let devices reconnect normally or restart the target adapter during a maintenance window. Restarting it interrupts connectivity.

WinCLAT Activation Events

Use the Microsoft-Windows-IPxlatCfg/Operational log to verify that WinCLAT started. Event 1106 (Instance enabled) records why Windows enabled the instance, and Get-WinClatInstance reports that reason in TriggerSource when the event is available. When a new instance starts translating, event 1106 is typically followed by event 1108 (Remote prefix discovered) and event 1109 (Translation started). For more on event 1106 and how to identify the associated network adapter, see Understanding Windows CLAT (WinCLAT) Event Logging.

Event 1109 in the IPxlatCfg Operational log showing that WinCLAT translation started

Event 1109 shows that WinCLAT began translating.

Verifying Policy and Translation

Verify the effective permit setting first, then check whether WinCLAT is translating on the target interface. Use netsh.exe or the WinCLAT PowerShell module for both checks.

Verifying the Effective Permit Setting

Run netsh.exe interface clat show global store=both or Get-WinClatConfiguration -Store Both to compare the active and persistent stores. The active store shows the effective configuration, and the persistent store shows the saved local configuration. In this example, policy enables permit in the active store while the local setting remains disabled. Use the module’s PolicyControlled property to confirm that policy controls Permit, even when both stores report the same value.

Output of netsh interface clat show global store=both

Output of netsh.exe interface clat show global store=both.

Get-WinClatConfiguration -Store Both | Format-List
Output of Get-WinClatConfiguration -Store Both

Output of Get-WinClatConfiguration -Store Both.

Verifying Translation on an Interface

From an elevated command window, run netsh.exe interface clat show instance interface=<index> using the interface index from Get-NetAdapter, and look for Is translating : yes. Alternatively, run Get-WinClatInstance and look for IsTranslating : True on the target interface. The module lists active adapters with IPv6 enabled, so you can run it without supplying an interface index. To verify end-to-end connectivity, test an IPv4-only application or connect to a literal IPv4 address from the target network.

Output of netsh interface clat show instance

Output of netsh.exe interface clat show instance.

Output of Get-WinClatInstance

Output of Get-WinClatInstance.

Removing the WinCLAT Policy

Unassigning the enablement package leaves the policy value in the registry. To restore local control, create a removal package using the same scripts with $DesiredState set to NotConfigured. Use Disabled when you want policy to enforce a disabled permit setting.

Maintaining Intune Connectivity During Removal

Before removing the policy, confirm that the device will still be able to reach Intune if automatic WinCLAT translation stops. A device that relies on WinCLAT to reach IPv4-only Intune endpoints can lose its ability to report the result or receive a recovery package. Use a network with a working path to Intune through native IPv4 or DNS64 and NAT64. On an IPv6-mostly network, check whether the device has a native IPv4 address after removal. Reconnect the adapter if it needs to obtain a new DHCPv4 lease.

Replacing the Enablement Assignment

Before assigning the Remove WinCLAT Policy package, remove the target devices from the enablement assignment. Use a pilot device to confirm that it has received the assignment change and that the enablement package no longer runs on it. After the target devices report successful removal, you can assign the removal package more broadly.

Verifying Policy Removal

Run Get-WinClatConfiguration and confirm that PolicyControlled no longer lists Permit. The effective Permit value should now match the local setting, which is disabled by default. If removal stops an automatically enabled instance, Get-WinClatInstance should report IsTranslating : False for that interface. The operational log may also show event 1110 (Translation stopped) and event 1107 (Instance disabled).

Event 1107 showing that Windows disabled the WinCLAT instance

Event 1107 shows that Windows disabled the WinCLAT instance on the interface.

Get-WinClatConfiguration output showing Permit False and an empty PolicyControlled field

Get-WinClatConfiguration shows Permit=False and an empty PolicyControlled field.

Get-WinClatInstance output showing IsTranslating False

Get-WinClatInstance shows IsTranslating=False.

Limits of Registry-Based Management

The script packages manage the WinCLAT permit policy. Automatic activation, manually enabled instances, and local changes to policy-controlled settings require separate checks.

Automatic Activation

The autoenable setting is enabled by default and has no corresponding WinCLAT Group Policy setting. If an administrator has disabled it, setting PermitNonCellularCLAT to 1 permits WinCLAT but leaves automatic activation disabled. To restore automatic activation, use netsh.exe interface clat set global autoenable=enabled or Set-WinClatConfiguration -AutoEnable Enabled.

Manually Enabled Instances

Disabling Permit stops automatically enabled instances. A manually enabled instance can continue translating until you disable it explicitly or the device reboots. Check the instance state on the target interface if your objective is to stop translation.

Local Changes to Policy-Controlled Settings

When policy controls a WinCLAT setting, netsh.exe interface clat set global can report success and update the local value in the persistent store while the active value continues to follow policy. Use netsh.exe interface clat show global store=active to verify the effective value. If you use Set-WinClatConfiguration to request a value that differs from the effective policy value, the cmdlet reports PolicyOverride.

Using netsh.exe in a Remediation

A Remediation can also run netsh.exe to configure WinCLAT, and this is the only way to enforce autoenable. However, netsh.exe changes the local configuration rather than policy, and reliable detection requires parsing localized command output, so this approach is outside the scope of this post.

Summary

Intune Remediations can deploy and remove the WinCLAT permit policy on Windows 11. Make sure devices can reach Intune before deployment, then verify the effective policy and translation state on the target interface. On IPv6-mostly networks, devices with an existing DHCPv4 lease may need to reconnect before Windows uses WinCLAT. Before removing the policy, confirm that devices will still have a working path to Intune.

Additional Information

WinCLAT resources on directaccess.richardhicks.com

Introducing the WinCLAT PowerShell Module

Windows CLAT (WinCLAT) is now generally available, and many organizations are beginning to evaluate it in their IPv6-mostly and IPv6-only environments. I’ve written extensively about WinCLAT recently, including how it works, when to use it, and how it discovers the NAT64 prefix. Today, I’m pleased to announce the release of the WinCLAT PowerShell module, a free, open-source tool that makes managing, reporting on, and troubleshooting WinCLAT much easier, especially at scale.

Background

Today, WinCLAT is configured and managed using the netsh.exe.exe interface clat command context. While netsh.exe works well enough on a single computer, it has some notable limitations. Its output is plain text, which is difficult to filter, sort, or export. It also provides no built-in way to collect information from many computers at once. And, in some cases, netsh.exe reports success even when Group Policy overrides the change, which can be misleading.

The WinCLAT PowerShell module addresses these challenges. It wraps netsh.exe and returns structured objects to the pipeline, so administrators can work with WinCLAT the same way they work with any other PowerShell command. Every function runs against the local computer or against many remote computers in parallel using WinRM.

Key Features

Version 1.0 of the WinCLAT PowerShell module includes the following capabilities.

  • Fleet-wide reporting. Every function accepts computer names directly, from a text file using Get-Content, or from Get-ADComputer. Results include one row for every computer, including those that are offline, do not have the feature, or are not elevated. It detects unreachable computers in about two seconds rather than waiting for a WinRM timeout.
  • Health checks with remediation. Test-WinClat checks the global configuration and every IPv6-enabled interface, explains each warning and failure, and optionally validates the CLAT path end to end.
  • Safe configuration changes. Set-WinClatConfiguration refuses changes that would prevent CLAT from ever activating, reads back every change to detect Group Policy overrides, and prompts for confirmation before any change that stops CLAT.
  • Baselines. Export and import the WinCLAT configuration or reset computers to the Windows defaults.
  • Structured output. Every function returns flat objects that can be filtered, sorted, and exported to CSV.

Every result includes a Status property (Success, Unreachable, FeatureNotAvailable, NotSupported, ElevationRequired, PolicyOverride, or Failed) and a Message property that explains anything other than Success.

Requirements

The WinCLAT PowerShell module has the following requirements.

  • Windows PowerShell 5.1 or PowerShell 7 on the computer running the commands.
  • Windows 11 25H2 build 26200.9550 or later on target computers. WinCLAT is not available on Windows Server.
  • WinRM enabled on remote target computers.
  • Administrative privileges on target computers for Get-WinClatInstance, the Set, Import, and Reset functions, and the interface checks performed by Test-WinClat. Get-WinClatConfiguration and Export-WinClatConfiguration do not require elevation.
  • English (en-US) netsh.exe output on target computers.

Installation

The WinCLAT module is available in the PowerShell Gallery. To install it, open an elevated PowerShell window and run the following command.

Install-Module -Name WinCLAT

The module needs to be installed only on the computer where the commands are run. It is not required on target computers. To update to the latest release, run the following command.

Update-Module -Name WinCLAT

Once installed, run the following command to view the available functions.

Get-Command -Module WinCLAT

The source code is also available on GitHub.

Functions

The WinCLAT PowerShell module includes the following functions.

FunctionDescription
Get-WinClatConfigurationReturns the global WinCLAT configuration
Get-WinClatInstanceReturns the WinCLAT state of each network interface
Test-WinClatDiagnoses WinCLAT readiness and operation
Set-WinClatConfigurationChanges the global WinCLAT configuration
Set-WinClatInstanceManually enables or disables WinCLAT on an interface
Export-WinClatConfigurationSaves the WinCLAT configuration to a file
Import-WinClatConfigurationApplies a saved WinCLAT configuration
Reset-WinClatConfigurationReturns the WinCLAT configuration to the Windows defaults

Every function accepts the -ComputerName, -Credential, and -ThrottleLimit parameters. The -ComputerName parameter accepts pipeline input, including output from Get-Content and Get-ADComputer. Blank lines and lines beginning with # are ignored, so a simple text file of computer names works without modification. The default -ThrottleLimit is 32 concurrent connections.

Get-WinClatConfiguration

The Get-WinClatConfiguration function returns the global WinCLAT settings: Permit, Pref64FromDns, Pref64FromRA, and AutoEnable. By default, it returns the active (effective) configuration. Use the -Store parameter to view the persistent (local) configuration, or both. Comparing the two is helpful for identifying settings controlled by Group Policy. The output also includes the OS build number, which is useful for tracking which computers have received the feature.

Get-WinClatConfiguration -Store Both

Get-WinClatInstance

The Get-WinClatInstance function returns the WinCLAT state for each active network interface with IPv6 enabled. The output shows whether the interface is translating, the NAT64 prefix and its remaining lifetime, and the CLAT addresses assigned. It also reports whether the instance was enabled automatically or manually (Mode and TriggerSource), which the module reads from the Microsoft-Windows-IPxlatCfg/Operational event log.

Get-WinClatInstance

To identify every interface actively translating across a group of computers, run the following command.

Get-Content -Path .\clients.txt | Get-WinClatInstance | Where-Object IsTranslating

Note: Get-WinClatInstance requires administrative privileges on the target computer.

Test-WinClat

Test-WinClat is the function I expect administrators will use most often. It performs a series of health checks on the global configuration and on each IPv6-enabled interface. By default, it returns a single summary per computer with an overall result of Pass, Warning, Fail, or NotApplicable, along with a list of the checks that failed or returned a warning.

Test-WinClat

Use the -Detailed switch to return one result per check. Each warning and failure includes a Detail explaining what was found and a Remediation describing how to correct it.

Test-WinClat -Detailed | Format-List

Note: The screen capture above contains additional information. It has been truncated for brevity.

Global checks include whether the feature is present, whether CLAT is permitted, whether NAT64 prefix discovery is enabled, and whether Group Policy overrides the local configuration. These do not require elevation. Interface checks include a SLAAC address, an IPv6 default route, the presence of native IPv4, an active CLAT instance, a CLAT address, and prefix consistency. Interface checks require administrative privileges and are skipped when the function is not run elevated.

Functional Test

Test-WinClat can also validate the CLAT path end to end. When the -IPv4Target parameter is specified, and an interface is translating, the function sends up to three ICMP echo requests to the target. Optionally, include the -IPv4Port parameter to test with a TCP connection instead. The results show which interface and source address the traffic used.

Test-WinClat -IPv4Target 192.0.2.10 -IPv4Port 443 -Detailed | Select-Object Check, Result, Detail

Important: Always specify an IPv4 address, not a hostname, for -IPv4Target. A hostname can be reached using DNS64 and NAT64 without CLAT, which defeats the purpose of the test. Also, Windows prefers a native IPv4 route over CLAT. If the computer has native IPv4 connectivity on another interface, the functional test reports Info rather than testing CLAT.

To test many computers and return only failures and warnings, run the following command.

Get-Content -Path .\clients.txt | Test-WinClat -Detailed | Select-Object ComputerName, Check, Result, Detail

Set-WinClatConfiguration

The Set-WinClatConfiguration function changes the global WinCLAT settings. Only the settings specified are changed. Before making any change, the function reads the current configuration and refuses any change that would leave both Pref64FromRA and Pref64FromDns disabled, since CLAT would never activate in that state. To enable WinCLAT, run the following command.

Set-WinClatConfiguration -Permit Enabled

Note: In the example above, the WinCLAT configuration is managed by group policy, which overrides the locally configured settings.

As I mentioned earlier, netsh.exe reports success even when Group Policy overrides a setting. To address this, Set-WinClatConfiguration reads back every change after it is made. If policy enforces a different value, the result is reported with a Status of PolicyOverride, as shown here.

The function supports -WhatIf. Disabling Permit or AutoEnable prompts for confirmation by default, because doing so stops CLAT on every interface where it was enabled automatically.

Set-WinClatInstance

The Set-WinClatInstance function manually enables or disables WinCLAT on a single interface, specified by name or interface index. This is primarily useful for testing and troubleshooting. Because netsh.exe refuses manual changes while AutoEnable is enabled, the function disables AutoEnable first, under a single confirmation prompt.

Set-WinClatInstance -InterfaceAlias 'Ethernet' -State Enabled

Please note that a Manual instance state does not survive a reboot, but the AutoEnable setting remains disabled. After a reboot, WinCLAT will not activate until AutoEnable is enabled again using Set-WinClatConfiguration -AutoEnable Enabled.

Reset-WinClatConfiguration

The Reset-WinClatConfiguration function returns the WinCLAT global configuration to the Windows defaults without requiring an export file. It sets Pref64FromDns, Pref64FromRA, and AutoEnable to enabled. Only settings that differ from the defaults are changed. To reset the WinCLAT configuration, run the following command.

Reset-WinClatConfiguration

Crucially, the Permit setting is changed only when the -Permit parameter is specified. This means a basic reset never stops CLAT. For a full reset to the current Windows defaults, including Permit, specify -Permit Disabled. Since this stops CLAT, the function prompts for confirmation by default.

Reset-WinClatConfiguration -Permit Disabled

Export and Import

The Export-WinClatConfiguration function saves the WinCLAT global configuration of one or more computers to the local computer, one file per computer. Files are named WinCLAT-<ComputerName>-<yyyyMMdd-HHmmss>.txt and are never overwritten, so repeated runs maintain a history of baselines. Export the WinCLAT configuration by running the following command.

Export-WinClatConfiguration -Path <folder name>

The Import-WinClatConfiguration function applies those files. Importantly, the files are never executed. Each file is parsed strictly, and any file containing content other than what netsh.exe writes is rejected before any computer is contacted. Only settings that differ from the file are changed.

Known Issues

During testing, I encountered the following issues. These are Windows behaviors, not issues with the module. They were observed on builds 26200.9711 and 26300.9711.

  • Stale CLAT address. After a network change, CLAT may retain its IPv6 address on the previous network’s prefix, causing IPv4 traffic through CLAT to fail. Test-WinClat reports a CLAT address failure in this scenario. Restarting the network adapter resolves the issue.
  • DNS registration. CLAT registers its IPv4 address (192.0.0.x) in DNS, which is unnecessary and may have negative side effects.
  • ICMP errors. ICMP error messages returned by NAT64 for IPv4 destinations do not reach IPv4 applications. As a result, ping to an unreachable IPv4 address times out rather than reporting that the destination is unreachable.

Summary

The WinCLAT PowerShell module makes it easier for administrators to configure, report on, and troubleshoot Windows CLAT across their environment. Whether you’re evaluating WinCLAT on a handful of test machines or preparing for a broad IPv6-only deployment, the module provides structured output, fleet-wide reporting, and built-in health checks that netsh.exe alone does not. Download it today from the PowerShell Gallery and let me know what you think. Feedback, issues, and feature requests are always welcome on GitHub.

Additional Information

WinCLAT PowerShell Module on the PowerShell Gallery

WinCLAT PowerShell Module on GitHub

Windows CLAT (WinCLAT): IPv4 Application Support on IPv6 Networks

Windows CLAT Overview and Configuration

When Windows CLAT (WinCLAT) Is Used on IPv6-Mostly and IPv6-Only Networks

How Windows CLAT (WinCLAT) Discovers the NAT64 Prefix

Windows CLAT Is Now Generally Available (Microsoft)

90 DAYS LEFT: Windows Server 2016 End of Life January 2027 – Plan Your AD CS Migration Now

Heads up, fellow Windows Server administrators! There are now just THREE MONTHS remaining before Windows Server 2016 reaches end of support, so now is the time to finalize any migrations for workloads hosted on this platform. Mainstream support ended on January 11, 2022, and Windows Server 2016 has since remained in extended support. However, extended support ends on January 12, 2027. After that date, Microsoft will no longer provide security updates or technical support, increasing the risk of running production workloads due to exposure to newly discovered vulnerabilities and exploits.

Active Directory Certificate Services

Many organizations are still running critical infrastructure on Windows Server 2016. Administrators often delay upgrading Microsoft Active Directory Certificate Services (AD CS) due to its complexity. However, a well-planned AD CS migration not only reduces risk but also provides an opportunity to modernize cryptography, certificate templates, and operational practices.

Certificate Authorities

Administrators must carefully migrate Certificate Authorities (CAs) running on Windows Server 2016 to minimize downtime. In environments where ongoing CA maintenance has been limited, migrating the CA database can be especially challenging. If the CA is installed on a domain controller, now is a good time to consider separating these services to ensure reliable operation. Also, it’s a good idea to evaluate the CA’s configuration and security posture during migration to enhance security and improve service resilience.

NDES Servers

Microsoft Network Device Enrollment Services (NDES) servers, commonly deployed to facilitate certificate enrollment via Microsoft Intune, pose a unique challenge during migration. Unfortunately, configuring NDES is exceedingly complex and error-prone. NDES relies on a delicate combination of specialized IIS configuration, AD service accounts, custom certificate templates, and CA permissions, making even minor changes risky without proper planning. Not surprisingly, administrators are often hesitant to touch these systems as they are notoriously difficult to troubleshoot when problems arise.

Pro Tip: We spend an entire day covering NDES configuration in the Mastering Enterprise PKI Certificates with Microsoft Intune training course. The next session is February 3-5, 2027. Register now!

Intune Certificate Connectors

Don’t overlook Windows Server 2016 servers with the Intune Certificate Connector installed. Fortunately, this is one of the more manageable workloads to migrate. All that’s required is to install new connectors on supported servers and delete the old ones.

Summary

With extended support for Windows Server 2016 ending on January 12, 2027, organizations running production workloads—especially critical infrastructure such as Active Directory Certificate Services (AD CS), Certificate Authorities (CAs), and NDES servers—face significant security risks from unpatched vulnerabilities once the OS reaches end-of-life. Careful migration planning to newer versions such as Windows Server 2022 or 2025 is essential to minimize downtime, improve security posture, and ensure long-term resilience.

Start Planning Now

Don’t risk running unsupported workloads in 2027! Complete your migration today. If you’d like expert guidance, I have many years of experience migrating these workloads. I have developed specialized tools and techniques to ensure a smooth, secure, and successful transition. Fill out the form below to schedule a free one-hour consultation to assess your Windows Server 2016 AD CS workloads, identify migration risks, and outline next steps.

Additional Information

Windows Server 2016 Lifecycle Policy

PKI Fundamentals with Microsoft Active Directory Certificate Services (AD CS) Online Training Course

Mastering Enterprise PKI Certificates with Microsoft Intune Online Training Course

Microsoft Intune Certificate Connector Configuration Failed – String Cannot Be of Zero Length

When deploying on-premises enterprise PKI certificates using Microsoft Intune with Simple Certificate Enrollment Protocol (SCEP) certificate profiles, administrators must deploy a Windows Server with the Network Device Enrollment Service (NDES) role installed. Once configured, the Microsoft Intune Certificate Connector can be installed and configured to allow administrators to issue and manage certificates for their Intune-managed endpoints.

Configuration Failed

After configuring NDES, administrators may encounter an error message when installing the Microsoft Intune Certificate Connector. The message states:

Configuration Failed

Configuring Microsoft Intune Certificate Connector failed. No changes were made to Feature or Proxy settings. Please try again.

Unexpected Failure. Error: System.ArgumentException: String cannot be of zero length.
Parameter name: name
at System.Security. PrincipaI.NTAccount..ctor(String name)
at Microsoft.lntune.Connectors.ConfigUlScep.SetServiceUserPermissions(String username)
at Microsoft.lntune.Connectors.ConfigUlScep.SetNdesUserPermissions(String username)
at Microsoft.lntune.Connectors.ConfigUlScep.Enable()
at Microsoft.Intune.Connectors.ConfigUI.ApplyConfiguration.<ApplyChanges>d__10.MoveNext()

Missing Service Account

This error occurs because the administrator configured the NDES role using the default application pool identity, which the Intune Certificate connector does not support.

Resolution

To resolve this issue, configure the SCEP application pool to run as a Group Managed Service Account (gMSA), which is a security best practice. Alternatively, you can configure the SCEP application pool to run as a regular domain service account (not recommended).

SCEP Application Pool Configuration

To update the SCEP application pool to run as a gMSA or domain service account, add the service account to the IIS_IUSRS group. If running as a domain service account and not a gMSA, be sure to also grant the service account the Logon as a Service right.

Next, open Internet Information Services (IIS) Manager (inetmgr.exe) and follow the steps below.

  1. Expand the NDES server in the navigation tree.
  2. Highlight Application Pools.
  3. Right-click the SCEP application pool and choose Advanced Settings.
  4. In the Process Model section, highlight Identity.
  5. Click the ellipses next to ApplicationPoolIdentity.
  6. Select Custom account.
  7. Click Set.
  8. Enter the service account using the domain\username format. Be sure to include the trailing $ when specifying a gMSA.
  9. If using a standard domain service account, enter and confirm the password.
  10. Click Ok three times.
  11. Finally, stop and start the application pool for the changes to take effect.

Note: Using a gMSA requires additional configuration in the domain. Details here.

Once complete, be sure to assign the Request Certificates permission to the gMSA or domain service account on the issuing certification authority (CA) server. In addition, assign Enroll permission to the service account on the NDES certificate template in Active Directory (AD).

Intune Certificate Connector

The Intune Certificate Connector does not support running under a gMSA. However, when using NDES/SCEP, it’s acceptable to run the connector service under the SYSTEM account. Ensure the connector server’s computer account is granted Issue and Manage Certificates permissions on the issuing CA server.

Summary

For NDES used with Intune SCEP certificate profiles, a group Managed Service Account (gMSA) is the preferred service account. A standard domain user account is supported if a gMSA is not an option. Specify the account when you configure the NDES role or leave the default ApplicationPoolIdentity and replace it with the gMSA before installing the Intune Certificate Connector.

Additional Information

Microsoft NDES Information Disclosure: Detection and Remediation

Microsoft NDES Security Hardening: Protecting and Monitoring the SCEP Registry Configuration

Troubleshooting NDES Error 0x80070003 Path Not Found on Windows Server 2025

Troubleshooting NDES Error 0x80094800 Unsupported Cert Type on Windows Server 2025

Training: Mastering Enterprise PKI Certificates with Microsoft Intune

Entra Global Secure Access (GSA) Client Intune Deployment PowerShell Script

The Microsoft Entra Global Secure Access (GSA) client is commonly deployed using Microsoft Intune. To deploy the client as an Intune Win32 app, administrators package the installer and a PowerShell installation script into an .intunewin file. Microsoft provides a sample PowerShell script that creates a log, configures Windows to prefer IPv4 over IPv6, and launches the installer. However, the sample has several limitations that can make it unreliable in production environments. To address these shortcomings, I’ve refactored the code to make it more robust and better aligned with enterprise deployment best practices.

Script Improvements

Microsoft’s PowerShell script for installing the GSA client has several significant limitations. My refactored version includes the following improvements.

  1. Preserved the existing DisabledComponents setting. Microsoft’s example overwrites the entire registry value, potentially removing previously configured settings. My version sets the 0x20 bit to prefer IPv4 while preserving any other flags already present.
  2. Validates the installer’s Authenticode signature. My revised script verifies that the installer has a valid Authenticode signature and that the signing certificate identifies Microsoft Corporation as the publisher.
  3. Preserves the pending reboot state. My script records when the registry setting was changed and compares that timestamp with the device’s last boot time. If the device has not restarted, subsequent runs continue to return exit code 3010, even if an earlier installation attempt failed.
  4. Expanded exit-code handling. The script writes a timestamped PowerShell transcript to the Intune Management Extension log directory, allowing it to be included with collected Intune diagnostics. Logging failures do not prevent the installation from continuing.
  5. Intune-integrated logging. I’ve updated the script’s logging to use the Intune Management Extensions logs folder, so logs are captured by Intune’s diagnostics collection. Each run of the script generates its own timestamped log file, making troubleshooting easier. Also, logging failures never block installation.
  6. Best practice alignment. I’ve added comment-based help, culture-invariant timestamps, and a $PSScriptRoot guard with a clean error to handle script execution issues. In addition, the script is digitally signed to support environments that enforce signed-script execution policies.

GitHub

I’ve published my refactored GSA client installation script on GitHub. You can download the script here:

https://github.com/richardhicks/gsa/blob/main/Install-GSAClient.ps1

Note: The script expects the installer to be named GlobalSecureAccessInstaller.exe. However, downloaded installers typically include the version number in the filename, such as GlobalSecureAccessInstaller_<version>.exe. Before creating the .intunewin package, either rename the installer or update the $InstallerName variable in the script.

Contribute

Suggestions and contributions are welcome. If you have ideas for making the GSA client deployment more robust or reliable, please submit a pull request on GitHub.

Summary

Microsoft provides a PowerShell script to deploy the Entra GSA client via Intune, but it has several limitations. This refactored version preserves existing registry settings, validates the installer, improves reboot and exit-code handling, integrates logging with Intune diagnostics, and better aligns with enterprise deployment best practices.

Additional Information

Install-GSAClient.ps1 PowerShell Script on GitHub

Prepare Win32 App Content for Upload to Microsoft Intune

Install the Global Secure Access Client for Microsoft Windows

NDES Security Hardening: Protecting and Monitoring the SCEP Registry Configuration

The Active Directory Certificate Services (AD CS) Network Device Enrollment Service (NDES) is widely deployed to support the issuance and management of enterprise PKI certificates via Microsoft Intune and the Intune Certificate Connector. NDES relies on registry settings to identify its issuing CA, certificate templates, and other SCEP configuration parameters. An attacker with sufficient access to an NDES server could alter these settings and redirect enrollment to another template published on the issuing CA and accessible to the NDES service account. Because enrollment might continue without an obvious service failure, administrators could overlook the change. This article explains how to restrict access to the MSCEP registry key, audit modifications, and use Sysmon to collect additional investigative context.

Understanding the MSCEP Registry Configuration

NDES stores its core SCEP configuration under the HKLM\SOFTWARE\Microsoft\Cryptography\MSCEP registry key. These settings identify the issuing CA and certificate templates used for enrollment and control other aspects of NDES operation. Because they directly influence how certificate requests are processed, unauthorized changes could alter enrollment behavior without modifying the NDES application itself.

Enrollment Templates

NDES uses the following registry values to identify the certificate templates used for SCEP enrollment.

HKLM\SOFTWARE\Microsoft\Cryptography\MSCEP\EncryptionTemplate
HKLM\SOFTWARE\Microsoft\Cryptography\MSCEP\GeneralPurposeTemplate
HKLM\SOFTWARE\Microsoft\Cryptography\MSCEP\SignatureTemplate

In many deployments, all three values reference the same template. If the environment supports distinct signature, encryption, or general-purpose enrollment scenarios, each value can reference a template designed for that specific purpose.

Additional MSCEP Settings

The MSCEP key contains more than certificate template assignments. Its CAInfo and CAType subkeys identify the CA to which NDES submits requests, while other subkeys control settings such as the hash algorithm and capabilities advertised to SCEP clients.

Information Disclosure and Reconnaissance

The default permissions for the MSCEP registry key are inherited from HKLM\SOFTWARE, which grants the local Users group read access. This allows locally authenticated users, as well as users granted remote registry access, to read the template names and CA configuration. Template names can aid reconnaissance, as an attacker can query Active Directory for the corresponding template definitions and evaluate their configurations against known AD CS escalation techniques. The CAInfo subkey can also disclose the internal fully qualified domain name of the issuing CA. Restricting access to the MSCEP key reduces unnecessary exposure of this information.

Why the MSCEP Key Is an Effective Monitoring Target

After NDES is deployed to production, these values should change only during planned reconfiguration. This makes the MSCEP key a high-value, low-noise monitoring target. Legitimate modifications should be rare and documented, while any unexpected change warrants immediate investigation.

Before You Begin

The changes described in this article modify access permissions and configure auditing for registry settings that NDES requires. An incorrect service identity, incomplete allowlist, or unsupported environmental assumption can prevent certificate enrollment. Test these changes in a nonproduction environment first, confirm that you have a working backup and rollback procedure, and validate successful enrollment before applying them broadly. Adapt the examples to your environment and follow your organization’s change management and security review processes.

In addition, be sure to back up the configuration before making any changes. A full server backup or a virtual machine snapshot is helpful. However, administrators can perform additional steps to save information before altering the default settings.

Determine the NDES Service Account

The permissions applied below grant access to the account used by the SCEP application pool. Confirm this account before proceeding by opening IIS Manager (inetmgr.exe), expanding the IIS server, and selecting Application Pools. Highlight the SCEP application pool and note the account shown in the Identity column.

Back Up the Current Permissions

A registry export with reg.exe captures data but not the security descriptor, so it is not a rollback for this change. Run the following PowerShell commands to capture the descriptor in SDDL format instead.

$Key = 'HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP'
(Get-Acl -Path $Key -Audit).Sddl | Out-File -FilePath .\mscep-acl-backup.txt -Encoding utf8

The rollback process is covered later in this post.

Restricting Access to the MSCEP Key

For a dedicated NDES server, restrict the MSCEP key to SYSTEM, the local Administrators group, and the identity used by the SCEP application pool. All other access entries should be removed, including the inherited Read permission for the local Users group. If another service identity requires access in your environment, such as a domain service account used by the Intune Certificate Connector, account for it in both the explicit access rules and the allowlist before applying the changes.

Administrators must retain full control. Even if the Administrators entry were removed, a local administrator could exercise the necessary privileges to take ownership of the key and rewrite its permissions. The ACL therefore reduces unnecessary access but does not provide a security boundary against a local administrator or an attacker with equivalent privileges. This is why the auditing described in the next section is an important complementary control.

Important Note: Registry values do not carry their own security descriptors, so the permissions applied here govern the MSCEP key, every value in it, and every subkey beneath it. The service identity is granted full control rather than read because NDES writes to this key during normal operation, and read-only access will break it.

Removing Inheritance

The inherited entries from HKLM\SOFTWARE are where the broad access comes from, so they must be removed first. On the NDES server, open an elevated PowerShell command window and run the following commands.

$Acl = Get-Acl -Path $Key -Audit
$Acl.SetAccessRuleProtection($True, $False)

The -Audit parameter reads the system access control list (SACL) and the discretionary access control list (DACL), so both can be updated and committed in a single write later. The second parameter of SetAccessRuleProtection is set to false, which discards the inherited entries rather than converting them to explicit copies. This approach is intentional. Inherited entries cannot be removed with PurgeAccessRules method, so preserving them would leave the broad grants in place and defeat the entire exercise. No explicit deny entry is required anywhere in this process. After this change, the local Users group has no access to the key at all.

Granting Explicit Access

Breaking inheritance also removes the SYSTEM and Administrators grants, so our explicit entries will replace them. Well-known security identifiers (SIDs) are used instead of account names, so this works correctly on non-English Windows installations.

$ServiceIdentity = 'corp\gmsa_ndes$'   # or 'corp\svc_ndes' if using a domain service account
$Sid = (New-Object System.Security.Principal.NTAccount($ServiceIdentity)).Translate([System.Security.Principal.SecurityIdentifier])
ForEach ($Identity in @('S-1-5-18', 'S-1-5-32-544', $Sid.Value)) {
    $Trustee = New-Object System.Security.Principal.SecurityIdentifier($Identity)
    $Acl.AddAccessRule((New-Object System.Security.AccessControl.RegistryAccessRule($Trustee, 'FullControl', 'ContainerInherit', 'None', 'Allow')))
}

S-1-5-18 is the well-known SID for SYSTEM, and S-1-5-32-544 is the well-known SID for the local Administrators group. ContainerInherit ensures the rights propagate to the subkeys.

Removing Unapproved Access Entries

The remaining explicit entries are evaluated against an allowlist, and anything that does not belong to those three identities is purged.

$AllowedSids = @('S-1-5-18', 'S-1-5-32-544', $Sid.Value)
ForEach ($Entry in ($Acl.Access | Where-Object { -not $_.IsInherited } | Select-Object -ExpandProperty IdentityReference -Unique)) {
    If ($Entry -is [System.Security.Principal.SecurityIdentifier]) {
        $EntrySid = $Entry
}
Else {
        $EntrySid = $Entry.Translate([System.Security.Principal.SecurityIdentifier])   
}
   
If ($AllowedSids -notcontains $EntrySid.Value) {
        $Acl.PurgeAccessRules($EntrySid)   
}
}

Sweeping against an allowlist rather than purging a fixed list of known principals removes application capability SIDs, CREATOR OWNER, any application pool entry that no longer matches the current SCEP application pool service account, and anything left over from previous administrative changes, without enumerating them in advance. It also makes the operation repeatable, so running it a second time on an already hardened server produces the same result.

Important Note: This code uses SID comparison. Identity references can be returned as either an NTAccount or a SecurityIdentifier, depending on whether the account resolves, so comparing by name will silently miss orphaned entries.

Auditing Changes to the MSCEP Key

Restricting the ACL reduces unnecessary access, but it cannot prevent a local administrator from taking ownership or rewriting the permissions. Auditing provides a complementary detective control by recording attempts to modify the key.

Add the Registry Audit Rule

To enable auditing, add an audit rule to the MSCEP key’s SACL that records successful and failed attempts by any identity to modify its values, subkeys, or permissions. Then commit the DACL and SACL together.

$Everyone = New-Object System.Security.Principal.SecurityIdentifier('S-1-1-0')
$AuditRule = New-Object System.Security.AccessControl.RegistryAuditRule($Everyone, 'SetValue, CreateSubKey, Delete, ChangePermissions, TakeOwnership', 'ContainerInherit', 'None', 'Success, Failure')
$Acl.AddAuditRule($AuditRule)
Set-Acl -Path $Key -AclObject $Acl

The audited operations are limited to changes. Specifically, setting a value, creating or deleting a subkey, changing permissions, and taking ownership. Reads are intentionally not audited. The three identities that still have access read these values routinely, so auditing that activity would generate excessive noise. Note that failure auditing applies only to the listed modification rights, so a denied read attempt will not be logged.

In addition, TakeOwnership and ChangePermissions are included deliberately because an attempt to alter the key’s security descriptor could indicate that someone is trying to weaken or bypass the applied controls. These operations should be rare after deployment and warrant investigation when they are not associated with an approved administrative change.

Recycle the SCEP Application Pool

Once the permissions are committed, recycle the SCEP application pool to close any existing registry handles and ensure the worker process reopens the MSCEP key under the new access controls.

Restart-WebAppPool -Name SCEP

Enable the Registry Audit Subcategory

An audit rule on its own does not generate events. The Object Access category must have the Registry subcategory enabled before Windows will write anything to the Security event log. Confirm the current setting by running the following command.

auditpol.exe /get /subcategory:"{0CCE921E-69AE-11D9-BED3-505054503030}" /r

The subcategory is referenced by GUID rather than by name for locale independence. If it is not enabled, enable it through Group Policy under Advanced Audit Policy Configuration > Object Access > Audit Registry rather than setting it locally, so the setting survives and applies consistently across your NDES infrastructure.

Recommended Security Alerts

With the Registry audit subcategory and the SACL configured as described, creating, deleting, or modifying a registry value under the MSCEP key generates event ID 4657 in the Security event log, identifying the account, the value name, and both the old and new data. That last detail is what makes the event immediately actionable. You do not have to look up what the template was supposed to be, because the event tells you what it was and what it was changed to.

My recommendation is to alert on every event ID 4657 associated with EncryptionTemplate, GeneralPurposeTemplate, or SignatureTemplate values rather than attempting to tune out individual processes or accounts. These values should remain static after deployment, so their expected change volume is zero. Monitor modifications elsewhere under the MSCEP path as well but establish a baseline before treating every such event as an alert because some NDES configurations may update other values or subkeys during normal operation.

Additional Alerts

Two additional events are worth correlating when one of these fires:

  • Event ID 4670 records a change to the permissions on the object. On a hardened key, this is a strong signal, since it means someone modified the ACL you just applied.
  • An application pool recycle or an IIS restart shortly after a value change is the corroborating signal. Because NDES caches the template configuration in the worker process, a substituted template does not take effect until the SCEP application pool or server restarts. An attacker seeking immediate activation would therefore need to trigger a recycle or restart, creating another potentially observable event. Otherwise, the change could take effect later during a routine recycle or restart.

Add Process Context with Sysmon

Security event ID 4657 identifies the account, process name, process ID, registry value, and old and new data associated with a change. However, it does not provide the full command line, process lineage, hashes, or surrounding activity needed for a more complete investigation. The System Monitor (sysmon.exe) utility from the Microsoft Sysinternals suite supplements the Security event log with this information.

Sysmon is not a replacement for SACL. The Security event records the authorization decision as Windows made it, which is the authoritative record. Sysmon records the process lineage around that decision. The two sources are complementary. Sysmon can capture the process that triggers an application pool recycle or an IIS restart when that activity matches the configured process creation rules.

Sample Sysmon Configuration for NDES

I have published a sample Sysmon configuration for NDES servers on GitHub. It is available here. This targeted configuration monitors SCEP enrollment settings, IIS application pool activity, registration authority certificates and private keys, credential access, and selected AD CS, certificate store, IIS, and operating-system security events relevant to an NDES deployment. It is not intended to serve as a general enterprise baseline. You can run it as a standalone configuration on an NDES server or merge its rule groups into an existing baseline such as SwiftOnSecurity or Olaf Hartong sysmon-modular.

Install or Update Sysmon

After reviewing and testing the sample configuration, install Sysmon or apply the configuration to an existing Sysmon deployment. To install Sysmon, open an elevated command window and run the following command.

sysmon.exe -accepteula -i sysmon-ndes.xml

To update an existing installation and confirm the active configuration, run the following commands.

sysmon.exe -c sysmon-ndes.xml
sysmon.exe -c

Sysmon events are written to the following event log location.

Applications and Services Logs > Microsoft > Windows > Sysmon > Operational.

Sysmon Monitoring Coverage

The configuration is centered on detecting changes to security-sensitive registry locations. The remaining rules capture the process, file, network, and system activity needed to investigate those changes.

  • Registry events 12, 13, and 14 cover the MSCEP key and its subkeys using a contains condition so both the native and WOW6432Node paths are captured. The same rule group covers the Certificate Services configuration key, machine certificate stores and trust anchors, SCHANNEL and TLS configuration, IIS service configuration, and common persistence locations.
  • Process creation events capture the tools used to make these changes, including reg.exe, regedit.exe, certutil.exe, appcmd.exe, and iisreset.exe. Tools such as appcmd.exe and iisreset.exe, as well as PowerShell commands such as Restart-WebAppPool, can recycle the SCEP application pool or restart IIS, allowing a modified template configuration to take effect. Sysmon can capture these actions when the initiating process and command line match the configured process-creation rules. PowerShell Script Block Logging provides additional visibility into commands executed within an existing PowerShell session, which might not be captured as separate Sysmon process-creation events.
  • Process access events are restricted to handle requests against LSASS with the access masks commonly associated with credential dumping. On a host that holds registration authority private keys and runs under a gMSA identity, this is the single highest-value rule.
  • File creation and deletion events cover the private key containers under Crypto\RSA, Crypto\Keys, and Crypto\PCPKSP, the IIS configuration directory, and certificate file extensions. Web content extensions such as .aspx and .ashx are also included, because a file with one of those extensions appearing under the NDES site is a strong indicator of a web shell.
  • Network connection events are purposefully scoped to scripting hosts and file transfer utilities rather than everything. An NDES server constantly talks to the CA and enrolling clients, and logging all of it produces excessive noise and provides little insight.
  • Named pipe, WMI, and process tampering events are also included. Legitimate volume for these is close to zero on a dedicated NDES server, so they are logged in full.

Note: The registry rule group includes an exclusion for the highest-volume legitimate writers, such as services.exe, svchost.exe, and TrustedInstaller.exe, as well as CreateKey events. Without those exclusions, useful events are buried within minutes. However, broad process-based exclusions can create visibility gaps. Administrators should validate that those exclusions do not suppress meaningful changes to the monitored paths.

Correlating Sysmon and Security Log Events

When a template value is modified, the Security event log records event ID 4657 with the account, value name, and old and new data. Sysmon records event ID 13 for the same operation, including the image path and process GUID associated with the write. If Sysmon also captured the corresponding process-creation event, the process GUID can be used to correlate event ID 13 with event ID 1, which provides the full command line and parent-process information. The Security event identifies the audited account and registry change, while Sysmon supplies richer process lineage and surrounding activity.

Sysmon Deployment Considerations

Before deploying this configuration, confirm that it is compatible with your installed Sysmon version and existing monitoring baseline. Test it on a representative NDES server first, then review the resulting event volume and adjust only those rules that conflict with known, legitimate activity.

  • Confirm the schema version supported by your installed Sysmon build by running
    sysmon.exe -s before deployment. The sample configuration uses schema version 4.90 and therefore requires Sysmon 15 or later.
  • The FileBlockExecutable rules actively block matching executable files rather than merely recording their creation. Review and test these rules carefully before deploying the configuration in production.
  • If you already run a Sysmon baseline, merge these rule groups into it rather than installing this configuration over the top of it. Installing a new configuration replaces the existing one entirely.
  • Forward both the Sysmon Operational event log and the Security event log to your Security Information and Event Management (SIEM) platform. Local event logs on a compromised server hosting an Internet-published SCEP endpoint are of limited investigative value, and an alert that nobody receives provides little protection.
  • Validate the configuration in a lab first. Sysmon rule evaluation order is not always intuitive, and an overly broad include rule on a busy server can generate a surprising amount of data.

NDES Operational Considerations

Tightening permissions on a key that a running service depends on has consequences worth understanding before you make these changes in production.

  • If the Intune Certificate Connector service runs as a custom account rather than SYSTEM, add that account to the allowlist and grant it read access. Check the logon account on the connector service before you begin. In this scenario, I recommend running the Intune Certificate Connector as SYSTEM to follow security best practices.
  • If you change the SCEP application pool identity later, NDES will fail until the key permissions are updated to include the new identity. These permissions are aligned to a specific account, so any change to that account requires a corresponding change here.
  • If you operate multiple NDES servers, apply these changes to all of them to ensure full coverage.
  • Document any planned change to the template configuration in your change management process. If you alert on these events as recommended, someone will need to close the ticket the alert generates.

Validate Permissions, Auditing, and Enrollment

Run the following PowerShell command to verify the resulting access rules.

(Get-Acl -Path $Key).Access | Format-Table IdentityReference, RegistryRights, IsInherited

Only SYSTEM, BUILTIN\Administrators, and the NDES service account identity should be listed, and none of the entries should be inherited. Next, run the following command to confirm the audit rule is present.

(Get-Acl -Path $Key -Audit).Audit

With the Registry audit subcategory enabled, perform a controlled test in a lab by changing a template value and recycling the SCEP application pool. Verify that event ID 4657 appears in the Security event log and includes the expected old and new values.

If event ID 4657 does not appear in the Security event log after you modify a registry value under the MSCEP key, confirm that the Registry audit subcategory is enabled.

auditpol.exe /get /subcategory:"{0CCE921E-69AE-11D9-BED3-505054503030}"

If you deployed the Sysmon configuration, confirm it is loaded and generating events. Sysmon events are recorded in the Applications and Services Logs > Microsoft > Windows > Sysmon > Operational event log. The log should include events related to the test, including the registry value modification. Depending on how the application pool was recycled and which process-creation rules are enabled, it might also contain the process that initiated the recycle.

You will also find events containing process creation details, including the full command line, process ID, parent process ID, and related information.

Finally, perform a device enrollment. Certificate enrollment should remain unaffected by these changes, and confirming successful enrollment after making these changes is essential before returning the NDES server to production.

Restore the Previous Registry Permissions

If enrollment breaks and the cause is not immediately obvious, administrators can restore the security descriptor captured earlier by running the following PowerShell commands.

$Sddl = Get-Content -Path '.\mscep-acl-backup.txt' -Raw
$Acl = Get-Acl -Path $Key -Audit
$Acl.SetSecurityDescriptorSddlForm($Sddl.Trim())
Set-Acl -Path $Key -AclObject $Acl
Restart-WebAppPool -Name SCEP

In practice, the most common cause of failure is granting access to the wrong service identity. This is why confirming the application pool identity is the first step in this process. Administrators should not skip this validation step.

Summary

The MSCEP registry values determine which certificate templates NDES uses for SCEP enrollment. An attacker with administrative access to the NDES server could modify these values and redirect enrollment to an unintended template without creating an obvious service failure. Restricting access to the MSCEP key reduces unnecessary exposure, while registry auditing and Sysmon provide visibility into unauthorized changes and the processes responsible for them. Forward these events to your SIEM, configure alerts for unexpected modifications, and validate the detection workflow before relying on it in production.

Additional Information

Sample Sysmon Configuration for NDES on GitHub

Download Sysmon from Microsoft Sysinternals

Microsoft NDES Information Disclosure: Detection and Remediation

Get-NdesNtlmDisclosure PowerShell Script on GitHub

Configure Infrastructure to Support SCEP with Microsoft Intune

Publish NDES with Microsoft Entra Application Proxy

Microsoft NDES Information Disclosure: Detection and Remediation

The Active Directory Certificate Services (AD CS) Network Device Enrollment Service (NDES) is a common building block for certificate deployment with Microsoft Intune. When NDES is used with the Intune Certificate Connector, the NDES server is published to the Internet so that managed devices can enroll for certificates using the Simple Certificate Enrollment Protocol (SCEP). Anything accessible via the Internet warrants careful attention, and a default NDES installation can expose more information than administrators might expect. Specifically, the NDES administration page can disclose sensitive information and should be removed. However, removing access to the page isn’t enough. Even after the NDES administration page is removed, IIS can continue to expose Windows authentication on that path through orphaned configuration entries, enabling NTLM-based information disclosure to unauthenticated Internet clients.

NDES Administration Page

NDES exposes its web-based functionality through applications hosted in Internet Information Services (IIS). A default NDES installation creates two IIS applications under the CertSrv virtual directory. The first is mscep, which is the SCEP endpoint itself. The second is mscep_admin, which is the NDES administration page used to generate one-time challenge passwords.

Standalone Configuration

In a standalone NDES deployment, an administrator browses to the administration page, authenticates, and receives a one-time password that is embedded in the certificate request. NDES validates the password against its local cache before forwarding the request to the certification authority (CA).

Intune Certificate Connector

The Intune Certificate Connector does not use this mechanism. Intune generates its own challenge, and the NDES policy module installed by the connector validates the certificate request against the authorizations Intune has granted for that specific device. The connector also disables the standard NDES challenge-password mechanism. As a result, the administration page is not used for Intune certificate enrollment and serves no operational purpose in this configuration.

Preauthentication Limitations

Reverse-proxy preauthentication normally provides an additional security boundary by requiring a client to authenticate before its request is forwarded to the published application. With Microsoft Entra Application Proxy, Microsoft Entra ID preauthentication can block unauthenticated Internet clients from reaching the internal web application, reducing its exposure to scanning, password-spraying attacks, and other malicious requests.

However, SCEP clients cannot complete the Microsoft Entra ID authentication process or present the authentication token required by Application Proxy. Enabling preauthentication would therefore prevent managed endpoints from reaching NDES and enrolling for certificates. When publishing NDES through Microsoft Entra Application Proxy, the Pre Authentication setting must be configured as Passthrough. Other reverse proxies must similarly allow unauthenticated requests to reach the NDES SCEP endpoint. The Intune SCEP policy module, not the reverse proxy, validates and authorizes certificate requests before NDES submits them to the certification authority.

Information Disclosure

Because the NDES administration page is configured to use Windows authentication, IIS can negotiate NTLM with an unauthenticated client that requests the mscep_admin path. When the client sends an NTLM Type 1 negotiation message, IIS can respond with a Type 2 challenge containing a target information block. No credentials are required to receive this challenge or the information it contains.

Depending on the server configuration and negotiated NTLM options, the Type 2 message can disclose some or all of the following information:

  • NetBIOS domain name
  • NetBIOS computer name
  • DNS domain name
  • DNS computer name (server FQDN)
  • DNS forest name
  • Operating system version and build number

This is significant because the internal Active Directory namespace often differs from the public namespace used to publish NDES. For example, the published external name might be ndes1.example.com, but the NTLM challenge might disclose an internal domain of corp.example.net and a server FQDN of ndes1.corp.example.net. None of that information is available from public DNS.

Testing

To view disclosed information, use curl.exe to send a static NTLM type 1 negotiation message and inspect the response headers. Run the following command on the NDES server.

curl.exe -skI -H 'Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=' https://localhost/certsrv/mscep_admin

A response containing a WWW-Authenticate header with an NTLM value indicates the endpoint is offering a challenge. When the header includes a base64 payload beginning with TlRMTVNTUAAC, the server has returned a type 2 message, leading to information disclosure on the target host. A response with no WWW-Authenticate header at all is the desired result.

Here are the PowerShell commands to decode and view the base64 payload and the disclosed information.

$Response = curl.exe -skI -H 'Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=' https://localhost/certsrv/mscep_admin
$Challenge = ($Response | Select-String -Pattern '^WWW-Authenticate:\s*NTLM\s+(\S+)').Matches.Groups[1].Value
$Bytes = [Convert]::FromBase64String($Challenge)
[Text.Encoding]::Unicode.GetString($Bytes) -Replace '[^\x20-\x7E]', ' '

PowerShell Script

I have created and published a PowerShell script to simplify testing NDES servers for information leakage. The script is published on GitHub here. In addition, you can install the script from the PowerShell Gallery by running the following command.

Install-Script -Name Get-NdesNtlmDisclosure

The output of the command on a vulnerable server is as follows.

A Note on External Testing

When NDES is published using Microsoft Entra Application Proxy, external test results can be inconsistent. In my repeated testing across three separate servers, the first request sometimes returned a bare NTLM challenge with no payload, and a second request, seconds later, returned the full type 2 message. Therefore, do not treat a single clean external result as confirmation. Test locally on the server itself, then repeat external tests at least twice to confirm the results.

Additional Security Concerns

Beyond the namespace disclosure, an Internet-accessible NDES administration page introduces some additional security concerns.

Password Spray Attacks

An internet-facing endpoint that accepts domain credentials is a target for password spraying attacks. Failed authentication attempts can count toward the configured account-lockout threshold, introducing a potential denial-of-service risk to user accounts.

Service Disclosure

The presence of an NTLM challenge on the well-known mscep_admin path also identifies the server as an NDES host, providing attackers with useful reconnaissance information for targeted attacks.

Remediation

If the reverse proxy configuration exposes the NDES administration page, it becomes an Internet-accessible authenticated endpoint that no part of the Intune enrollment workflow uses. Removing it is a simple and effective attack-surface reduction measure.

Remove the NDES Administration Page

Administrators can remove the NDES administration page IIS application by opening an elevated PowerShell command window and running the following command.

Remove-WebApplication -Site 'Default Web Site' -Name 'CertSrv/mscep_admin'

After running this command, browsing to the administration page returns HTTP 404. The application is gone, and SCEP enrollment continues to work normally. At this point, most administrators would consider the task complete.

The Problem

If you attempt to browse the administration page after removing it, you will still be prompted to authenticate. If you supply valid credentials, you will receive the expected 404. The authentication prompt itself is the real problem.

IIS Authentication Settings

The NDES role configuration writes IIS authentication settings for the administration page into a separate location element in applicationHost.config. Remove-WebApplication deletes the application definition under the sites element, but it does not touch the location element. IIS continues to match the path and applies the authentication settings it finds there, even though no application exists at that location.

The orphaned configuration is visible only in the raw configuration file. It does not appear in IIS Manager, and Get-WebApplication reports nothing at that path. You can run the following command to view this configuration.

Select-String -Path "$env:SystemRoot\System32\inetsrv\config\applicationHost.config" -Pattern '<location path=|windowsAuthentication enabled='

On a server where the administration page has been removed, the output still includes an entry like the following.

991: <location path=”Default Web Site/CertSrv/mscep_admin”>
997: <windowsAuthentication enabled=”true”>

Orphaned Configuration

To fully remediate this information disclosure and prevent potential disruption caused by password-spraying attacks, administrators must also remove the orphaned configuration location. This eliminates Windows authentication on the administration path entirely.

Remove-WebConfigurationLocation -Name 'Default Web Site/CertSrv/mscep_admin'

The NDES role configuration also enables Windows authentication on the SCEP application. Because anonymous authentication is also enabled, requests to the SCEP endpoint are ordinarily processed without an authentication challenge. However, Windows authentication is not required on an NDES server supporting the Intune Certificate Connector, and leaving it enabled on an Internet-facing endpoint serves no operational purpose. I recommend disabling it explicitly.

Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Location 'Default Web Site/CertSrv/mscep' -Filter 'system.webServer/security/authentication/windowsAuthentication' -Name 'enabled' -Value $False

By default, Windows authentication is handled in kernel mode, so stale state information in HTTP.SYS can continue serving challenges after a configuration change. Be sure to run iisreset.exe after making these changes.

iisreset.exe /restart

Validation

Repeat the NTLM probes demonstrated earlier against the administration page. The absence of a WWW-Authenticate header confirms the challenge has been eliminated.

curl.exe -skI -H 'Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=' https://localhost/certsrv/mscep_admin

Confirm that SCEP still responds anonymously. A status code of 200 with a plain-text capability list is expected.

curl.exe -skI 'https://localhost/certsrv/mscep/mscep.dll?operation=GetCACaps'

Repeat the first test against the internal FQDN and the published external FQDN, then perform a device enrollment to confirm the deployment is unaffected.

PowerShell

After making these changes, Get-NdesNtlmDisclosure.ps1 will indicate that the NTLM challenge is not offered.

Summary

The NDES administration page is not required when the Intune Certificate Connector is installed on an NDES server and should be removed as part of attack surface reduction. However, removing the IIS application leaves behind an orphaned configuration location that continues to apply Windows authentication settings to the path. The result can be an Internet-facing endpoint that discloses the internal domain name, server name, forest name, operating system build, and other information to an unauthenticated remote client that initiates NTLM negotiation.

Removing the admin application alone is not enough. You must also remove the configuration location, disable Windows authentication where it is not required, restart IIS, and validate the result with an NTLM probe to ensure full mitigation.

Additional Information

Get-NdesNtlmDisclosure PowerShell Script on GitHub

Publish NDES with Microsoft Entra Application Proxy

Intune Certificate Connector Configuration Failed

Microsoft Intune Certificate Connector Failure

Certificate Connector for Intune Configuration Failure

Create and Assign SCEP Profiles in Microsoft Intune

RFC 8894 – Simple Certificate Enrolment Protocol

Always On VPN Dynamic Profile Configurator (DPC) Webinar

Managing Microsoft Always On VPN deployments doesn’t have to be complicated. Always On VPN Dynamic Profile Configurator (DPC) is a free, open-source solution that simplifies deploying and managing Always On VPN client configuration settings while extending the capabilities of native deployment methods such as Microsoft Intune VPN profiles, custom XML, and PowerShell scripts.

Whether you’re deploying Always On VPN for the first time or looking to streamline an existing implementation, DPC provides powerful features that make advanced VPN configuration easier to deploy, manage, and maintain.

Join Our Live Webinar

Join me on Tuesday, August 18, at 1:00 PM EDT for a live webinar featuring Leo D’Arcy, creator and lead developer of Always On VPN DPC. During this live session, we’ll demonstrate many of DPC’s latest capabilities and show how they can simplify even the most complex Always On VPN deployments. Topics include:

  • Configuring flexible VPN deployment strategies
  • Optimizing interface and route metrics
  • Dynamically excluding Microsoft 365 and custom domains from the VPN tunnel
  • Configuring IKE mobility settings for improved roaming
  • Defining and managing IPv6 routes
  • Deploying DPC using Active Directory and Microsoft Intune
  • Exploring additional advanced features and deployment scenarios

Throughout the webinar, we’ll share practical guidance, configuration tips, and real-world examples to help you get the most from Always On VPN DPC.

Register Today

Registration is free, but you must register in advance to attend. If you can’t attend the live session, register anyway, and you’ll receive access to the on-demand recording after the event.

We’ll also reserve time for a live Q&A at the end of the presentation, giving you the opportunity to ask questions directly to the developers and experts behind DPC.

We look forward to seeing you there!

Additional Information

Always On VPN Dynamic Profile Configurator (DPC)

Always On VPN DPC Advanced Features

Always On VPN DPC with Microsoft Intune

Migrating from Always On VPN DPC Commercial to Open Source

Always On VPN DPC Commercial Support Now Available

Always On VPN DPC Discord Channel

Mastering Certificates with Microsoft Intune September 2026

I’m excited to announce that I will be delivering another edition of the Mastering Certificates with Microsoft Intune course, hosted by ViaMonstra Online Academy. This is a three-day live online training course that takes place September 1-3, 2026. This course dives deep into issuing and managing certificates using Microsoft Intune, covering both on-premises and cloud-based solutions.

Course Overview

This interactive training equips IT professionals with the skills to provision and manage enterprise PKI certificates using Microsoft Intune. It explores Active Directory Certificate Services (AD CS), Microsoft Cloud PKI for Intune, and non-Microsoft solutions, with live demonstrations featuring real-world scenarios.

Key Learning Objectives

Those taking the online training course will learn the following.

  • Certificate Basics: Understand certificate roles and enterprise use cases.
  • Deployment Options: Master Intune certificate deployment (Intune policies, revocation, security) and Microsoft Cloud PKI (licensing, benefits, limitations, BYOCA).
  • Intune Deployment: Learn PKCS and SCEP deployment, security best practices, and troubleshooting.
  • High Availability: Explore strategies for reliable certificate management.

Course Highlights

Here are some key highlights for attendees of the training.

  • Expert-Led: Learn from a veteran IT professional, a Microsoft MVP, with deep PKI and Intune expertise.
  • Interactive Demonstrations: The course includes numerous practical exercises in real-world scenarios.
  • Resources: Access to security best practices and sample scripts for automated configuration.
  • Community: Join a private Facebook group for peer collaboration.
  • Live Q&A: Engage directly with the instructor for a clearer understanding.

Who Should Attend?

This training event is ideal for IT administrators, security professionals, and systems engineers working with Intune, AD CS, or Microsoft Cloud PKI for Intune.

Prerequisites

Those attending the online training course should be familiar with the following.

  • Basic networking knowledge (TCP/IP, DNS).
  • Familiarity with Active Directory, Windows OS, and Intune.
  • Access to an AD CS setup and an Azure subscription with Intune Suite licenses.

Why It Matters

Certificates are vital for secure authentication and communication. This course bridges theory and practice, equipping you to deploy and manage digital certificates effectively in cloud-native environments.

Details

Here is some additional information about the training event.

  • When: September 1-3, 2026 (sessions begin at 9:00 AM CDT).
  • Where: Live online via ViaMonstra Online Academy.
  • Cost: $2,395.00 (Sold separately – not included in All-Access Pass).

Why ViaMonstra?

ViaMonstra delivers top-tier IT training from Microsoft MVPs, focusing on practical, up-to-date skills and fostering a collaborative community.

Take the Next Step

Ready to master certificate management with Microsoft Intune? Register at ViaMonstra Online Academy for the August 2025 Mastering Certificates with Microsoft Intune training course today!

What’s New in Entra Global Secure Access Client v2.31.125

On June 2, 2026, Microsoft released version 2.31.125 of the Entra Global Secure Access (GSA) client. This update introduces several enhancements designed to improve client resiliency, simplify troubleshooting, and provide administrators with better visibility into network connection status.

Changes in v2.31.125

GSA client v2.31.125 includes new features to streamline connectivity troubleshooting.

Network Status

The new GSA client can now distinguish between a complete network disconnection and a scenario where the device remains connected to a local network but lacks internet access. This distinction helps administrators and users more quickly identify the source of connectivity issues and reduce troubleshooting time.

Network Disconnected

No Internet Connectivity

Local Access

When Intelligent Local Access (ILA) is enabled, the client now clearly indicates when a device is connected to a trusted private network. This provides additional visibility into ILA decision-making and helps confirm that local access policies are functioning as expected.

Sign Out

The new GSA client includes an account picker when a user signs out on Entra-registered or Entra-joined devices. This enhancement simplifies account management on shared or multi-user devices by allowing users to switch identities without fully reinstalling or reconfiguring the client.

The sign out option is disabled by default. It must be enabled by setting the following registry key.

HKLM\Software\Microsoft\Global Secure Access Client\HideSignOutButton DWORD = 0

User Session Detection

Because the GSA client supports only a single interactive Windows session, this new indicator helps quickly identify unsupported multi-session scenarios that may impact client functionality or troubleshooting efforts.

Other Changes

In addition to the new features and capabilities outlined above, these changes are also included.

  • Updated embedded .NET Runtime to version 8.0.26.
  • GSA Forwarding Profile Service now automatically restarts after a failure.
  • Improved detection and tunneling of agentic network connections.
  • Various bug fixes and performance improvements.

Summary

GSA Client v2.31.125 introduces several useful enhancements focused on troubleshooting, resiliency, and user experience. Improved network status visibility, Intelligent Local Access awareness, account sign-out support, and enhanced session detection provide administrators with better diagnostic capabilities while making the client easier for end users to understand and manage. Although this release remains in preview, administrators are encouraged to begin testing this latest release soon.

Additional Information

Microsoft Entra Global Secure Access (GSA) Client v2.31.125

Microsoft Entra Private Access Intelligent Local Access