Some notes about a recent requirement to modify the access to LAPS attributes in one of our directories. We had a specific class of computer objects that we did not want all of our usual LAPS readers to be able to retrieve the local password for.

Quick Summary:

  • LAPS passwords are stored in ms-Mcs-AdmPwd
  • Read access to the attribute is usually granted at the OU level for a group who can look at the attribute.
  • Just having read access to this attribute does not mean you will actually be able to read it. ms-Mcs-AdmPwd is marked as 'confidential' in the schema.
  • For the most part you should be using the LAPS powershell module to make changes (import-module admpwd.ps).
  • If you have inheritance related challenges, you might be able to get crafty with ACE's to achieve the outcome you are looking for.

Background

Before I jump in... since most people installed LAPS a long time ago, so here's a quick refresher on what you probably did:

  1. You obtained the LAPS software from Microsoft: https://www.microsoft.com/en-us/download/confirmation.aspx?id=46899
  2. You installed it on an administrative machine to get some new group policy templates and some powershell modules.
  3. You extended the directory schema to include the new LAPS attributes - ms-Mcs-AdmPwdExpirationTime and ms-Mcs-AdmPwd, the attributes where appended to the computer object in the schema as optional attributes:
  4. You deployed the LAPS client side extension and used Group Policy to get computers to do better things with their local passwords.

During step 3, the new LAPS attributes had permissions applied, but you also probably allowed the computer object to modify its own AdmPwd attribute. Usually by doing something like:

Set-AdmPwdComputerSelfPermission -Identity "OU=ToddsOffice, DC=chadduffey,DC=com"

After you modified the computers SELF rights, you probably also added some rights to an administrative group to read the passwords when needed. Something like "Set-AdmPwdReadPasswordPermission –Identity 'OU=ToddsOffice,DC=chadduffey,DC=com' –AllowedPrincipals 'todds-laps-admins' " is the standard approach.

Just to quickly show the changes  we could compare "ToddsOffice" from the first command against a different OU that we haven't made any changes to:

(get-acl -path "AD:CN=TDUFF-01,OU=ToddsOffice,DC=chadduffey,DC=com").access > todd.txt
(get-acl -path "AD:CN=TAM-01,OU=TamsOffice,DC=chadduffey,DC=com").access > tam.txt

If i diff the two text files, i can see some of the information from the new ACE's for the "NT AUTHORITY\SELF" principal:

We can also find the modified ace reasonably quickly in the Users and Computers UI by looking for ACE's which inherit from the OU we targeted in our ACL modification PowerShell command:

ACE 1:

ACE 2:

But!

Even after all that poking around, its really important to note that in the case of the ms-Mcs-AdmPwd attribute, the confidentiality bit is set as well.

The 'confidential' bit is set on the searchflags attribute in the schema for the ms-Mcs-AdmPwd object.

Meaning?

Basically, that read permissions are not enough for this attribute. Even if you were to grant someone read access to the attribute they still might not be able to see the password for the computer admin account like you might expect.

You also need ''Control Access" [ADS_RIGHT_DS_CONTROL_ACCESS] (or 'full control' or 'all extended rights', but usually 'Control Access' is what you'll see for LAPS permissions. Jiri Formacek explains in more detail here).

We could continue to poke around the topic of extended rights and attribute permissions associated with LAPS, but actually, Microsoft made this reasonably easy to understand without going much deeper. They wrapped this information in a PowerShell command that you can use to figure out who can actually read the LAPS attribute.

After importing 'admpwd.ps' try something like:

Find-AdmPwdExtendedRights -Identity "OU=ToddsOffice,DC=chadduffey,DC=com" | fl

Where 'identity' is the OU you are interested to learn about.

ObjectDN : OU=ToddsOffice,DC=chadduffey,DC=com
ExtendedRightHolders : {NT AUTHORITY\SYSTEM, CHADDUFFEY\Domain Admins}

If the Extended rights holders list is long and truncated try this:

(Find-AdmPwdExtendedRights -Identity "OU=ToddsOffice,DC=chadduffey,DC=com").extendedrightholders

Making Changes:

So, with all that in mind, how do you change access on the attribute and control who can read the passwords stored there?

The most straightforward approach is to create a group containing the folk who should have access to that attribute for a given OU.

Set-AdmPwdReadPasswordPermission –Identity “OU=ToddsOffice,DC=chadduffey,DC=com” –AllowedPrincipals “todds-laps-admins”

Then, check your work with the previous command:

What if i discover groups or users that should not have access?

(Find-AdmPwdExtendedRights -Identity "OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com").extendedrightholders

Uh Oh!

There's a few ways that would revoke access and it will depend on what your actual goal is.

The most simple, if the group should no longer have any special permissions over the OU is to just remove the permission entry for that group altogether (#1 in the image). But assuming they need some rights on the OU, you'll instead be looking to do a combination of: 1) remove the "all extended rights" permission; or if they don't have that,  2) remove the "control access" permission and either way, you'll probably want to 3) take away the basic 'read' permission itself (#2 in the image).

What about Inheritance?

Inheritance makes things a little more tricky.

Using the previous example, if I am allowing 'bad-folk' to read the ms-Mcs-AdmPwd attribute at the parent OU "toddsOffice", but want to lock it down to 'mega-admins' in the child OU "SecretComputers" like shown below, what then?

Parent OU - 'ToddsOffice':

Child OU - 'SecretComputers':

You see that the "Control Access" extended right has flowed down to the child OU.

So, extended rights flow down as well.

Confirming with an example:

  • "Barney" is in the "bad-folk" group.
  • If inheritance is in play then Barney will be able to read the password attribute for computers in the "ToddsOffice" parent OU and the "SecretComputers" OU.

Parent OU:

Child OU:

We confirmed what we kind of already knew: the 'bad-folks' permissions including the extended rights to the ms-Mcs-AdmPwd attribute is inherited.

Quick side-note: in the context of reviewing permissions, its probably a good time to point out that there is a great script called 'lapstoolkit': https://github.com/leoloobeek/LAPSToolkit written by leoloobeek available.

It's much more convenient than clicking through everything like we have here. You just download the script, import it as a module, then let it rip.

For example:

PS C:\Users\Administrator\Documents> Import-Module .\lapstoolkit.ps1

PS C:\Users\Administrator\Documents> Find-LAPSDelegatedGroups
OrgUnit Delegated Groups 
------- ---------------- 
OU=ToddsOffice,DC=chadduffey,DC=com CHADDUFFEY\todds-laps-admins
OU=ToddsOffice,DC=chadduffey,DC=com CHADDUFFEY\bad-folk 
OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com CHADDUFFEY\mega-admins 
OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com CHADDUFFEY\todds-laps-admins
OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com CHADDUFFEY\bad-folk

If you prefer a 'built-in' tool dsacls actually does a really good job here as well, its just not as easy as the script:

dsacls "OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com"

If you point it at the OU in question you'll see that it provides really clear evidence when a principal has the two required ingredients to see LAPS passwords:

  1. Access to the AdmPwd attribute
  2. "Control access" to be able to see attributes marked confidential.

Blocking Inheritance and configuring the ACL as you want it

Getting back on track, the most obvious approach, just removing the ACE for the groups we don't want won't work because the permissions are being inherited from the parent.

We don't really want to disable inheritance because that would apply to the whole ACL, rather than the small change we are attempting to make. It would also apply going forward, so changes that admins believe would be flowing down might no longer do so.

But, we could flip this model around. Remember that an explicit deny takes precedence over the inherited allow we should be able to remove access from that 'bad-folk' group with a crafty ACE.

We could kill the extended-access right for the "bad-folk" group with PowerShell:

$acl = get-acl "ad:OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com"
$group = get-adgroup "bad-folk"
$sid = [System.Security.Principal.SecurityIdentifier] $group.SID

$identity = [System.Security.Principal.IdentityReference] $SID
$adRights = [System.DirectoryServices.ActiveDirectoryRights] "ExtendedRight"
$type = [System.Security.AccessControl.AccessControlType] "Deny"
$inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All"
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType

$acl.AddAccessRule($ace)
Set-acl -aclobject $acl "ad:OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com"

Notice that 'barney' cant see the ms-Mcs-AdmPwd attribute any more:

And "sally" who is not in the "bad-folk" OU can see it just fine:

Another way to achieve the same thing would be to use dsacls.exe:

dsacls "OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com" /I:S /D "CHADDUFFEY\very-bad-folk:CA;"

The command above is setting the inheritance to sub-objects (/I:S), its setting the ACE as DENY (/D), its applying the ACE to the "chadduffey\verybadfolk" group. The "CA" is making the deny apply to the Control Access right.

But we can actually do better...

The control access right is interesting when working with an ACE. Microsoft explain it like this: "For this permission, if [Object/Property] is not specified to define the specific "extended right" for control access, it applies to all control accesses meaningful on the object, otherwise it applies to the specific extended right for that object."

So what we should actually do is:

dsacls "OU=SecretComputers,OU=ToddsOffice,DC=chadduffey,DC=com" /I:S /D "CHADDUFFEY\very-bad-folk:CA;ms-Mcs-AdmPwd"

Even though the first option will work fine for most use cases.

Anyway, that'll do for now. Hopefully there's enough ramble in here to cover off:

  1. How to add permissions for LAPS
  2. How to remove permissions for LAPS
  3. How to deal with inheritance if you need to
  4. Most importantly, things to poke around and learn more about LAPS in your environment.