Call4Cloud | MMP-C | Autopilot | Device Preparation

Autopilot: Escape the Administrator

Patch My Pc | install & update thousands of apps

Did you ever run into an issue in which the user was still in the local administrator group after the device was enrolled with Windows Autopilot (at least that is what you thought happened) even when you configured the Autopilot profile and made sure the user account type was set to “standard

In this blog, I will explain at which point during Autopilot the user will become or NOT become a local admin. I hope this explanation will make things clearer after you read this blog post!

1. Introduction

Every time I read these kinds of questions on Reddit, I immediately tell them the fact that the device didn’t receive the proper Autopilot profile and just enrolled and performed a regular Azure Ad Join/Entra Join instead.

a reddit post mentions that his autopilot deployment profile is set to standard user but got local admin

With Autopilot, we can natively ensure that the enrolling user is not added to the local administrators‘ group. We can do so by configuring a simple Autopilot Profile setting to define the user account type. As shown below, the user account type is configured to Standard.

Windows Autopilot Profile user account type is configured to standard

Nothing more, right? But I started questioning myself what this flow looked like and how I could explain it a bit better because just yelling at people and telling them the device didn’t receive the Autopilot profile isn’t going to work.

So let’s dive into how you could become an administrator (preferably not) during Windows Autopilot

Please Note: A new option suddenly showed up in Entra under devices –> all devices –> device settings, and we can now configure the same kind of setting for regular Entra enrollments. If you wonder if that setting could interfere with the settings in the Autopilot Profile, please read this blog!

2. Cloud Domain Join

Let’s first start by explaining when the user will become an Admin or not! To explain at which point the user becomes or does not become a local admin on the device, we need to zoom in on the Azure Ad Join / Entra Join process.

If we kick off the Autopilot Enrollment, the device will eventually start enrolling the device into Entra if you enter the username and password. If you have read my blogs about Autopilot, there are some barriers it needs to cross first, so keep that in mind.

How autopilot is receiving its deployment profile

If we enter our username and password, the Enrollment Status Page (ESP) will kick in (if configured) and the device will start joining your organization.

Afbeelding met tekst, schermopname, Lettertype, logo  Automatisch gegenereerde beschrijving

After generating the device and transport key, It will hand over the access token for the enrollment service and will start enrolling/registering the device. If everything works out the service will send back the MS-organization-Certificate

Afbeelding met tekst, schermopname, Lettertype, lijn  Automatisch gegenereerde beschrijving

Let’s start by examining how this Entra join request looks when we configure the Autopilot user to be a standard user. I will use the Fiddler tool to do so. If we install Fiddler, we will notice a couple of things.

mSA-DDID and the CertificateRequest will be included in the device registration request sent to enterpriseregistration.net together with the Access toke

As shown above, the MSA-DDID and the CertificateRequest will be included in the device registration request sent to enterpriseregistration.net together with the Access token.

We will find some interesting information in the device registration response we get.

 in the device registration policy response we received, we will find the MS-Organization-Certificate and some additional information. This additional information contains the MemberShipChanges and the SIDs that will be added to the LocalSid S-1-5-32-544 AKA Local Administrator group.

As shown above, in the device registration policy response we received, we will find the MS-Organization-Certificate and some additional information. This additional information contains the MemberShipChanges and the SIDs that will be added to the LocalSid S-1-5-32-544 AKA Local Administrator group.

LocalSid S-1-5-32-544

Those 2 SIDS(Global administrator role and the Device administrator role) are the default ones that will be added to the local administrator group.

If we don’t want everyone who has the global admin role to become an admin on all of our devices (duhhh), we need to make sure we change the device registration policy and configure the EnableGlobalAdmins to False. To do so we need to change this Global Adminstrator option in Entra and configure it to NO

Global Adminstrator option in Entra and configure it to NO

The device registration request above is based on the fact that the enrolling user is a standard user but how does it look like when the enrolling user is NOT a standard user but a friendly local admin?

As shown above, the only real difference is that in the response, we will notice an additional SID added to the “AddSIDs.” This additional SID belongs to my user and will be added to the local administrator group.

I need to add a small note here because when using Autopilot pre-provisioning this happens when the user logs in, NOT when we are pre-provisioning the device. (the device only joins Entra to enroll into MDM, from there on the Azure AD / Entra certificate is whacked, and with it the Entra enrollment)

So, when our device gets a proper Entra Join with the enrolling user, that’s when the user will become a local administrator….. or not. But still, the question remains: How does this exactly happen?

3. CloudAssignedOobeConfig

When determining what this process looked like, I looked at the Windows Autopilot file: Windows.Management.Service.dll. In this DLL we have a function called: GetOobeSettingsOverride

Afbeelding met tekst, schermopname, Lettertype, lijn  Automatisch gegenereerde beschrijving

This nice function calls upon another function called GetConfig. I assume it tries to get a specific config.

The name spoils the fun a bit but let’s move on, shall we? Afbeelding met tekst, schermopname, Lettertype, lijn  Automatisch gegenereerde beschrijving

As shown above, this GetConfig function essentially attempts to retrieve the AutoPilot configuration named “CloudAssignedOobeConfig”

The CloudAssignedOobeConfig…. That is one we heard before, right? As in this blog, I was describing how a specific setting in the Autopilot profile allows or prevents the Pre-Provisioning

Only WhiteGlove in the Building – Call4Cloud | MMP-C | WinDC | Autopilot | Intune

At first, I was trying to find this Allow Pre-provisioning setting in the CloudAssignedOobeConfig but if you have read the blog above, that setting isn’t defined in the CloudAssignedOobeConfig. Maybe this time it’s different?

Let’s get back to the story to find out! The GetConfig is indeed trying to find the CloudAssignedOobeConfig. This config is stored on the disk in a file called AutopilotDDSZTDFile.Json in the c:\windows\servicestate\wmansvc folder

Besides being stored on the disk, it is also cached in the registry. The CloudAssignedOobeConfig will be stored in the Microsoft\Provisioning\AutopilotPolicyCache registry node. To be precise in a PolicyJsonCache value

Afbeelding met tekst, schermopname, Lettertype, software  Automatisch gegenereerde beschrijving

If you ever are stuck with a lingering Autopilot Profile, just trash these registry keys above (Autopilot) and the corresponding JSON file on the disk. If we open this reg_sz value we will indeed spot the CloudAssignedOobeConfig in it with a value of 1310

If we change the setting in the Autopilot profile to define if the user is a standard user or a local admin, we will notice that just as shown below, the value will change with “2”

the cloudassignedoobeconfig showing the OobeUserNotLocalAdmin setting that ensures the enrolling user is a local admin or not

This value 2, points us directly to the OobeUserNotLocalAdmin setting. I guess we can now be pretty sure that the CloudAssignedOobeConfig is responsible for making sure the user is or is NOT a local admin on the device.

This config will be checked when the device boots and the Windows Management Service is started. But still, the question remains… How does the CloudDomain Join process know how to start looking for this config? Do you know? Let’s find out!

4. getOobeSettingsOverrideAsync

Looking back, I should have started with the CloudDomainJoin.JS which is stored in the systemapps\Microsoft.Windows.CloudExperienceHost folder because that’s the file that holds the “code” to kick off the Cloud Domain in the first place.

cloudomainjoin.js holds the function

If we open that important JS file, we could spot a thing or 2. Let me describe how I think the Cloud Domain join that is taking place will determine if the user needs to be a standard user or not.

1.Initialization:

When the CloudDomain.JS code is executed, the getCommonFeatures function is called upon to compare client and server features.

Besides the wonderful MMPCRedirectFeature (which got my attention…) we also have an additional ClientFeature called: GetPolicy

Afbeelding met tekst, Lettertype, schermopname, lijn  Automatisch gegenereerde beschrijving

2.Fetching Policy Information:

The “CentralizedGetPolicy” will redirect me to the getPolicyString function. This function is called to retrieve the policy information.

Afbeelding met tekst, schermopname, Lettertype, lijn  Automatisch gegenereerde beschrijving

3. Fetching OOBE Settings (AutoPilot):

From there on the Getpolicystring will make a call to the getOobeSettingsOverrideAsync function. This function is used to retrieve AutoPilot OOBE settings.

I guess the circle is round now, right?

getOobeSettingsOverride –> CloudDomain.js

The same function that got me on the correct path to the CloudAssignedOobeConfig is also mentioned in the Windows.Management.Service.dll

Afbeelding met tekst, schermopname, Lettertype, lijn  Automatisch gegenereerde beschrijving

To resume: The Cloud Domain Process checks which settings are defined in the Oobe Settings. This code is tied to the same one in the Windows Management Service.dll. With those settings in the pocket, it will determine if the user needs to be added to the local administrator group when the device is going to be Cloud Domain AKA Entra joined!

5. DSREG.Dll

You could say that the getOobeSettingsOverrideAsync function plays a key role in determining whether the user becomes a local administrator during device Entra join based on Autopilot settings but how does it go from there?

If we go back to part 2 (Cloud Domain Join) we would have noticed that during the Entra Join, based on the outcome of the OOBESettings the device would send out a device registration request to the service. The DLL responsible for registering a device in Entra Join is the famous DSREG.Dll! So, in this part, I am going to use the DSREG.Dll and combine it with the information you have learned from the previous parts.

Let’s assume we have configured the Autopilot profile and configured the user account type to be an Administrator

If we take a closer look at the device registration request this time with the dsreg.dll loaded in the back of our mind and the type set to administrator, we will notice that when the “ReturnClientSid” is added to the request

When taking a closer look at dsreg.dll and trying to find out which part of the dsreg.dll holds the ReturnClientSid, we will notice that this information is added in the Registration Request body.

If the User Account is set to Administrator in the Autopilot Profile, the “Flow will Supports Joiner as Admin” and would add the ReturnClientSid in the request (Which is also the default behavior with a regular AAD Join!)

If the user account is set to Standard in the Autopilot Profile, the flow will NOT support the joiner as admin and will NOT add the ReturnClientSid in the request.

Afbeelding met tekst, lijn, schermopname, Perceel
Automatisch gegenereerde beschrijving

If the request did NOT contain the ReturnClientSid attribute, we will notice that the device registration join response will mention that the User SID was not provided for the device Join.

Once the flow has determined if the user needs to be a local admin, the MemberShip Changes will also be applied.

In this ApplyMemberShipChanges, we noticed it would add the array of SIDs received in the device registration response to the local administrator’s group.

n this ApplyMemberShipChanges, we noticed that it would add the array of SIDs (AddSIDs) received in the device registration response to the local administrator's group.

If we switch back to Fiddler, we will notice this. As shown below, the membership changes, and with the addsids command, these SIDs (users) will be added to the local administrator group.

6. The Flow Version 1

As always, all of my fancy words in a nice simple mspaint flow

Windows Autopilot technical overview when a user becomes a standard user or local admin depending on how you configured the Autopilot Profile

6. The Flow Version 2

Windows Autopilot technical overview when a user becomes a standard user or local admin depending on how you configured the Autopilot Profile

7. Personal devices

Now we have learned the details about how a user becomes a standard user during Autopilot, we still need to defend ourselves when the device doesn’t receive the Autopilot profile.

When our device boots and somehow, the device doesn’t receive the Autopilot profile (issues with the Autopilot marker for example) The user could still enroll his device the old school way and with it become a local admin on his device. Believe me, you don’t want that to happen!

To ensure that the user is a standard user, you must also block the enrollment of personal devices!

Afbeelding met tekst, Lettertype, nummer, schermopname  Automatisch gegenereerde beschrijving

Overview of enrollment restrictions – Microsoft Intune | Microsoft Learn

If you are blocking personal devices to get MDM enrolled, the Intune enrollment will fail and with it the whole enrollment! So, if you didn’t configure this option, everyone could just enroll their device into Entra.

If you are using Autopilot, please make sure that this Enrollment restriction is in place and set to “block Personally owned MDM enrollment” If you are blocking personal devices, devices that didn’t receive the Autopilot profile because they aren’t recognized as an Autopilot profile will be blocked! If they are blocked, you will not end up with a device with the enrolling user in the local administrator group!

Of course, this personal device restriction can be bypassed by configuring an offline Autopilot JSON file, but then again, Autopilot isn’t a security feature.

Conclusion

The conclusion is straightforward: If the user on a newly enrolled Autopilot device is somehow a member of the local administrators group, the device was NOT recognized as a Windows Autopilot device. If the device isn’t recognized as a Windows Autopilot device, it will just perform a regular device enrollment (if not blocked)

3 thoughts on “Autopilot: Escape the Administrator

  1. hey Rudy,
    As always a terrific blog, was surprised to see this issue but it makes sense no enrollment profile so the user ends up as admin. However in our case, personal device enrollment is also blocked and still user ended up as local admin. Strange!

    1. Not if they do OOBE and sign-in with an azure account before the device is properly registered as an autopilot device

Leave a Reply

Your email address will not be published. Required fields are marked *

  +  3  =  9

Proudly powered by WordPress | Theme: Wanderz Blog by Crimson Themes.