18 minute read
Active Directory Certificate Services (AD CS) attack surface is pretty well explored in Active Directory itself, with checks notes already 16 “ESC” attacks being publicly described. Hybrid attack paths have not gained that much attention yet, though I have come across several hybrid integrations while reviewing cloud configurations. In these setups, certificates are rolled out to cloud-managed endpoints via Microsoft Intune and the Intune certificate connector. The certificate connector runs in on-premises AD and requests the certificates on AD CS via the SCEP or PKCS integrations. In such environments, it would be possible to request certificates with arbitrary subjects as an Intune administrator. What I have also observed in some cases are certificate configurations in Intune being misconfigured in a way that would allow regular users to perform the same attack and effectively perform ESC1 over Intune certificates. That means going from regular user and their endpoint to Domain Admin in AD, all from the cloud. This blog explores the scenarios where this is possible and provides exploitation and remediation guidance.
Intune supports a “Certificate Connector” that can be installed on-prem, to allow Intune to request certificates in AD CS. The certificate connector is documented here and provides 3 options for distributing certificates:
The certificate connector is usually installed on a standalone server in AD, and in case of the SCEP protocol will also need the Network Device Enrollment Service (NDES) server role (part of AD CS). In addition, both of these configuration options require an AD CS certificate template that allows user supplied SANs. On the AD side, such a template would look as follows (output from Certipy):
1
Template Name : NDES-Computer
Display Name : NDES-Computer
Certificate Authorities : hybrid-HYBRID-DC-CA
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : True
Certificate Name Flag : EnrolleeSuppliesSubject
Extended Key Usage : Server Authentication
Client Authentication
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Schema Version : 4
Validity Period : 1 year
Renewal Period : 6 weeks
Minimum RSA Key Length : 2048
Template Created : 2025-05-22T14:09:06+00:00
Template Last Modified : 2025-05-22T14:10:00+00:00
Permissions
Enrollment Permissions
Enrollment Rights : HYBRID.IMINYOUR.CLOUD\svc_ndes
HYBRID.IMINYOUR.CLOUD\Domain Admins
HYBRID.IMINYOUR.CLOUD\Enterprise Admins
The following details are important for this attack:
NTAuthCertificates object in AD.EnrolleeSuppliesSubject flag is set, this is a requirement for Intune to be able to issue certificates for other users/devices, meaning that this flag should always be set for Intune templates.While the Intune Certificate connector supports both protocols, companies are likely to use either one or the other. Architecture wise they are quite different, so let’s take a high-level look at how both operate:
PKCS performs most of the operations between Intune and the device. The flow is as follows:
In a diagram, that looks as follows:

The important details here are:
With SCEP, the flow is different:
Again a diagram of this flow:

A few notable points:
It should be no surprise that if such a setup is present, it can be abused by attackers if they have a privileged role in the tenant. After all, the AD CS template allows any subject, the Certificate Connector or NDES server can enroll these templates, so with the correct configuration we can impersonate a Domain Admin or a domain controller. There are three main challenges with this:
Let’s look at the Intune part first. Consider an example certificate profile here:

This is a device certificate, which is why it uses the DNS Subject Alternative Name (SAN) for mapping it to a specific device. User certificates would usually use the UPN instead of the DNS name. The Intune “Certificate type” is a device certificate in this case, which means it will be saved as a computer certificate on the endpoint if the Entra ID device object is in scope of the configuration profile. For user certificates, they are stored as a user certificate on the endpoint, and will be issued to users in scope of the configuration profile.
Both user or device certificate can be used to impersonate user or computer accounts in AD, since the mapping is done based on the SAN and the AD CS template will allow both objects. Whether to target a user or device in AD is up to you, in this example the goal will be to impersonate a Domain Controller, so I will pick a computer as a target and use a DNS SAN.
We will create a new configuration profile rather than modifying an existing one, to prevent the change from being rolled out to actual endpoints. This also makes sure the certificate will be provisioned immediately, since I don’t know how fast Intune picks up on “changed” certificate configurations, if at all, once a certificate is already issued.
Based on MS-PKCA section 3.1, during PKINIT the certificate will need to be strongly mapped. Luckily for us there is a SAN URL tag specifically for Intune that we can use to ensure this: URL=tag:microsoft.com,2022-09-14:sid:<value>. In normal configurations this would be dynamically filled in for hybrid joined devices based on the SID that they have in AD, but we can also hard code it in the template. So in our new template, make sure to configure:
In my case the final config looks like this:

Now we need to scope this to a device to actually issue the certificate. There are multiple approaches to this:
While roadtune has (or will have actually from the next release) the most seamless support for this attack, it is currently not available as an open source tool but is part of the Outflank Security Tooling framework. If you have that, great, you can read more about the roadtune specific implementation in the roadtune documentation. But since I don’t want to promote commercial tooling in this blog I will stick with explaining the other flows here, with the primary focus on real Windows devices or VMs.
In this case I have an already enrolled VM that is in a group that I scope this configuration profile to:

It can take a while for the device to pick up the new policy or for Intune to actually start pushing it. Assume a delay of around 5-10 minutes (that is what I had in my test). The telemetry in Intune is quite slow so don’t rely on that. Since it may take a long time for the device to sync, it is better to trigger a manual sync until we see the certificate in the store:



Once the certificate is in the store, we can either export it out (and bypass the key export restrictions) using mimikatz, or we can use it directly with Rubeus by specifying the thumbprint. Note that Rubeus only searches in the user store, so if the certificate type was “device” you need to patch out the store lookup to target the system cert store instead. We specify the certificate by its thumbprint.

If we want to capture the certificate before it is stored in the store, we can actually see the PFX cert in the SyncML data as well. There is a super awesome tool to debug this called SyncMLViewer by Oliver Kieselbach that allows us to capture the SyncML messages via ETW. If we search for the PFX install message, which will contain the “PFXCertInstall” command, we find the PFX itself and it’s encrypted password:

Decrypting the PFX password requires using the Intune MDM cert and private key, and using that to decrypt the PKCS7/CMS encoded data blob, which gives the PFX password. Performing this is out of the scope of this blog but that would be an alternative to exporting the key out of the Windows certificate store.
Now that we have a TGT for a Domain Controller we have essentially compromised the on-prem domain.
If you have a SCEP configuration profile instead of a PKCS profile, we can use the same technique to issue the cert to a real device, alternatively we can also pick the required details out of the SyncML stream and use that with scepreq as explained further down in the blog.
Now that we understand the general setup, let’s look at how we can achieve this without the modification of configuration profiles, for example from the point of a low-privileged user with an Intune license. Consider for example the following template:

This template puts the FQDN of our device as a SAN in the template. There are many variables that could be used here, as is reflected in the Microsoft documentation. What is important here is that some of these come from essentially untrusted / user controlled data. This will mostly be the case for “device” type certificates, since “user” certificates are usually based on Entra data such as a UPN, which can’t be modified by the user themselves.
There could be a corner case if the company is syncing Tier 0 AD users to Entra ID, which is against best practices. If you could compromise such an account it could also be used to request certificates. But that would be a corner case that likely requires similar privileges in the tenant as the scenario above.
Back to the device cert based scenario. Microsoft does call it out in the documentation that these parameters could be spoofed.

So this is exactly what we will be doing in this case. Before strong mapping was required, this would have been quite easy since we only need to include the correct DNS or UPN SAN in our request. Now that strong mapping is the default, that leaves us with two options:
StrongCertificateBindingEnforcement is set to 1, then we can use both PKCS and SCEP templates to request a certificate with a UPN or DNS name SAN that is attacker controlled.Why SCEP? Because with PKCS, the entire flow is between Intune and the Certificate Connector, which means we cannot add the strong mapping. The KDC will not accept our certificate and throw an error if no strong mapping is present. With SCEP we can create our own CSR, and as long as the subject and SANs match with the values in the Intune configuration profile it turns out we can add the SID security extension to the certificate with an arbitrary SID, this will pass the validation.
To sum up the requirements:
There are a few challenges here:
Some abusable configurations in SANs are:
{{DeviceName}}. The device name can be configured as an FQDN, though Windows will not allow you to do so in the UI. Intune accepts these names without issue.{{DeviceName}}.companydomain.com. In this case we only need to spoof the first part, which we can do by renaming the real device.{{IMEI}} or {{SerialNumber}}. I don’t know where real Windows devices source this information from, so you’d have to figure that out yourself, or enroll a fake device.Examples of configurations that are not vulnerable:
{{DeviceName}}.companydomain.com, if the domain does not match the on-premises domain name.AAD_Device_ID or DeviceIdI have not figured out yet where {{FullyQualifiedDomainName}} is sourced from, it may be that this only exists on hybrid joined devices.
In this walkthrough we will explore the simplest configuration, where there is a SCEP cert that has a SAN based on the device name and a domain suffix that matches with on-prem AD.

Let’s rename our device to match a Domain Controller name:

We also run the SyncMLViewer tool to watch the SyncML traffic, since we will use this to capture the traffic. What we are looking for are SyncML nodes with the ClientCertificateInstall/SCEP URI. These will contain the data for our SCEP enrollment. Once we trigger the sync with the new name we should see the data.

This contains everything we need to use scepreq to talk to the NDES service. Scepreq is a new tool that I’m releasing with this blog. It is essentially a modified fork of PyScep with a command line wrapper and extensions for AD CS and Intune specific certificate requests. The structures for custom SANs and security extensions are borrowed from Certipy.
We will need:
ServerURL, which contains the SCEP endpoint.Challenge, which is used in SCEP as a password. The challenge is valid for an hour after it is issued.EKUMapping, which should at least contain client authentication (1.3.6.1.5.5.7.3.2), or the “any purpose” EKU.SubjectName for the cert.SubjectAlternativeNames to use. These have a bit of a weird format with the comment in the documentation “Refer name type definition in MSDN”. If someone knows which specification they are taken from let me know. But the format is as follows: [nameformat1]+[actual name1];[name format 2]+[actual name2], where the nameformat is a number. Number 3 stands for DNS name, number 11 for UPN, the rest I don’t know but should be deductible from the format.If we take all that we can pass it to scepreq. Note that most of these values are actually case sensitive!
scepreq -u https://s25-ndes.hybrid.iminyour.cloud/certsrv/mscep/mscep.dll -p <challenge> --dns HYBRID-DC.hybrid.iminyour.cloud -s 'CN=c711a89b-7b82-4d84-bfa2-040d03057ee5' --sid S-1-5-21-1414223725-1888795230-1473887622-1000
If all succeeds we get a certificate. If not, there is unfortunately zero error information that NDES will give to use as of why this failed. It will be in the Event logs on the NDES server, but that is not a source of information that we can see in this scenario. Anyway, if all goes well it should look like this:

Once we have the certificate we can request a TGT with PKINITtools, Certipy or Rubeus:

And once again we have a TGT for a Domain Controller, elevating our privileges to Domain Admin.
In this case the starting point was a Windows device on which we had Administrator access so that we could spoof the correct variables and abuse the template. If it is not such an easy example as above, it would be more complex to spoof the correct identifier (such as a serial number) on a real device. Getting a fake device enrolled with either a tool or as a VM would work, but then usually corporate device enrollment limitations would apply, often enforced through Autopilot. There is some discussion about whether Autopilot and the registration of hardware IDs is actually a security feature or more of an accidental security barrier for attackers. I see it as a feature that will often stop attackers from enrolling fake devices, though I don’t think it is intended this way.
In any case, the important message here is that Intune administrators should avoid using spoofable identifiers in certificate profiles. And of course be aware that when someone obtains Intune Administrator or Global Administrator and also has access to the AD network, it is pretty much game over.
As far as detection goes, the usual AD CS certificate abuse detection advice would apply, and hopefully some security product or custom detection rule will alert on certificates being issued for Domain Admins or Domain Controllers, or TGTs requested for them with a certificate if this is not normally something they do.
The scepreq tool is available on GitHub. If you want to do this with roadtune, expect a new release soon which includes PKCS extraction capabilities and automatic SCEP enrollment based on configurations that are pushed from Intune.
Lastly a shout-out to Rudy Ooms, whose documentation on all the Intune things was extremely valuable while developing the Intune related protocols.