Delegating access in AD to BitLocker recovery information

Normally in AD, all attributes are readable by “Authenticated Users”. Some attributes should inherit permissions, but should not be readable by “just anyone” To protect attributes like this, they can be marked as “confidential”.

There are 3 attributes relating BitLocker to which are marked in the schema as “confidential”.

This is done by marking the searchFlags attribute as enabled for bit 7 (128 decimal) in the schema where the attribute is defined. See here for more information on searchFlags: https://support.microsoft.com/kb/922836

These attributes are:

Attribute

Applies to Object

Used for

msTPM-OwnerInformation

computer

Contains the owner information of a computers TPM.

msFVE-KeyPackage

msFVE-RecoveryInformation

Contains a volumes BitLocker encryption key secured by the corresponding recovery password.

msFVE-RecoveryPassword

msFVE-RecoveryInformation

Contains a password that can recover a BitLocker-encrypted volume.

An object of type “msFVE-RecoveryInformation” is created for every encrypted volume and is stored as a sub-object of the computers object where the volume was encrypted.

Simply granting “read” access to these attributes will not allow a user to read the information in these attributes. A user who wants to read the attribute must also have an Access Mask for “Control_Access”. This is a special type of ACE (Access Control Entry). See here for more information on Access Masks: https://msdn.microsoft.com/en-us/library/aa374896(v=vs.85).aspx

GUI Tool to Manage Permissions

The only GUI tool which can set and view these special Control_Access ACEs is LDP.exe (using the version from Windows Server 2003 R2 ADAM or newer). This is shown below:

The "Control_Access" flag is needed in ADDITION to the normal "Read Propery" right. The "Control_Access" flag gets you past the confidentiality bit. You still need to be able to read the contents of the attribute.

Apply the permission once at the top of EACH DOMAIN where you need to delegate access to the recovery information of BitLocker volumes. Usually this does not include forest root domains or resource forests. Ensure the “inheritance” box is checked on each ACE so that it propagates to every msFVE-RecoveryInformation or Computer object and only to its relevant attributes.

(Note from Ryans comment below: You can aply this permission anywhere in the OU structure if you'd like to split the delegation bewteen groups - e.g. Help Desk users can access the keys for Standard Workstations and the Server Admins can access the keys for servers etc. You could apply the "read propery" ACE at the top of the domain to a super-group for everyone who is allowed to access the keys, and then have different groups able to use the "Control_Access" flags for their particular OUs. This will help limit ACE bloat in lsass.exe working set while still locking down the keys in the way you'd expect.)

Here are sample scripts to add the "Control_Access" flag to the top of the domain:

DelegateBitLocker.vbs

Taken from: https://technet.microsoft.com/en-us/library/cc771778(WS.10).aspx

'To refer to other groups, change the group name (ex: change to "DOMAIN\Help Desk Staff")

strGroupName = "BitLocker Recoverers"

' -----------------------------------------------------------

' Access Control Entry (ACE) constants

' -----------------------------------------------------------

'- From the ADS_ACETYPE_ENUM enumeration

Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &H5 'Allows an object to do something

'- From the ADS_ACEFLAG_ENUM enumeration

Const ADS_ACEFLAG_INHERIT_ACE = &H2 'ACE applies to target and inherited child objects

Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &H8 'ACE does NOT apply to target (parent) object

'- From the ADS_RIGHTS_ENUM enumeration

Const ADS_RIGHT_DS_CONTROL_ACCESS = &H100 'The right to view confidential attributes

Const ADS_RIGHT_DS_READ_PROP = &H10 ' The right to read attribute values

'- From the ADS_FLAGTYPE_ENUM enumeration

Const ADS_FLAG_OBJECT_TYPE_PRESENT = &H1 'Target object type is present in the ACE

Const ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = &H2 'Target inherited object type is present in the ACE

' -----------------------------------------------------------

' BitLocker schema object GUID's

' -----------------------------------------------------------

'- ms-FVE-RecoveryInformation object:

' includes the BitLocker recovery password and key package attributes

SCHEMA_GUID_MS_FVE_RECOVERYINFORMATION = "{EA715D30-8F53-40D0-BD1E-6109186D782C}"

'- ms-FVE-RecoveryPassword attribute: 48-digit numerical password

SCHEMA_GUID_MS_FVE_RECOVERYPASSWORD = "{43061AC1-C8AD-4CCC-B785-2BFAC20FC60A}"

'- ms-FVE-KeyPackage attribute: binary package for repairing damages

SCHEMA_GUID_MS_FVE_KEYPACKAGE = "{1FD55EA8-88A7-47DC-8129-0DAA97186A54}"

'- Computer object

SCHEMA_GUID_COMPUTER = "{BF967A86-0DE6-11D0-A285-00AA003049E2}"

'Reference: "Platform SDK: Active Directory Schema"

' -----------------------------------------------------------

' Set up the ACE to allow reading of all BitLocker recovery information properties

' -----------------------------------------------------------

Set objAce1 = createObject("AccessControlEntry")

objAce1.AceFlags = ADS_ACEFLAG_INHERIT_ACE + ADS_ACEFLAG_INHERIT_ONLY_ACE

objAce1.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT

objAce1.Flags = ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT

objAce1.Trustee = strGroupName

objAce1.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS + ADS_RIGHT_DS_READ_PROP

objAce1.InheritedObjectType = SCHEMA_GUID_MS_FVE_RECOVERYINFORMATION

' Note: ObjectType is left blank above to allow reading of all properties

' -----------------------------------------------------------

' Connect to Discretional ACL (DACL) for domain object

' -----------------------------------------------------------

Set objRootLDAP = GetObject("LDAP://rootDSE")

strPathToDomain = "LDAP://" & objRootLDAP.Get("defaultNamingContext") ' e.g. string dc=fabrikam,dc=com

Set objDomain = GetObject(strPathToDomain)

WScript.Echo "Accessing object: " + objDomain.Get("distinguishedName")

Set objDescriptor = objDomain.Get("ntSecurityDescriptor")

Set objDacl = objDescriptor.DiscretionaryAcl

' -----------------------------------------------------------

' Add the ACEs to the Discretionary ACL (DACL) and set the DACL

' -----------------------------------------------------------

objDacl.AddAce objAce1

objDescriptor.DiscretionaryAcl = objDacl

objDomain.Put "ntSecurityDescriptor", Array(objDescriptor)

objDomain.SetInfo

WScript.Echo "SUCCESS!"

 

DelegateTMPOwners.vbs

Taken from: https://technet.microsoft.com/en-us/library/cc771778(WS.10).aspx

'To refer to other groups, change the group name (ex: change to "DOMAIN\TPM Owners")

strGroupName = "TPM Owners"

' ------------------------------------------------------------

' Access Control Entry (ACE) constants

' ------------------------------------------------------------

'- From the ADS_ACETYPE_ENUM enumeration

Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &H5 'Allows an object to do something

'- From the ADS_ACEFLAG_ENUM enumeration

Const ADS_ACEFLAG_INHERIT_ACE = &H2 'ACE applies to target and inherited child objects

Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &H8 'ACE does NOT apply to target (parent) object

'- From the ADS_RIGHTS_ENUM enumeration

Const ADS_RIGHT_DS_CONTROL_ACCESS = &H100 'The right to view confidential attributes

Const ADS_RIGHT_DS_READ_PROP = &H10 ' The right to read attribute values

'- From the ADS_FLAGTYPE_ENUM enumeration

Const ADS_FLAG_OBJECT_TYPE_PRESENT = &H1 'Target object type is present in the ACE

Const ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = &H2 'Target inherited object type is present in the ACE

' ------------------------------------------------------------

' TPM and FVE schema object GUID's

' ------------------------------------------------------------

'- ms-TPM-OwnerInformation attribute: SHA-1 hash of the TPM owner password

SCHEMA_GUID_MS_TPM_OWNERINFORMATION = "{AA4E1A6D-550D-4E05-8C35-4AFCB917A9FE}"

'- Computer object

SCHEMA_GUID_COMPUTER = "{BF967A86-0DE6-11D0-A285-00AA003049E2}"

'Reference: "Platform SDK: Active Directory Schema"

' ------------------------------------------------------------

' Set up the ACE to allow reading of TPM owner information

' ------------------------------------------------------------

Set objAce1 = createObject("AccessControlEntry")

objAce1.AceFlags = ADS_ACEFLAG_INHERIT_ACE + ADS_ACEFLAG_INHERIT_ONLY_ACE

objAce1.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT

objAce1.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT + ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT

objAce1.Trustee = strGroupName

objAce1.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS + ADS_RIGHT_DS_READ_PROP

objAce1.ObjectType = SCHEMA_GUID_MS_TPM_OWNERINFORMATION

objAce1.InheritedObjectType = SCHEMA_GUID_COMPUTER

' ------------------------------------------------------------

' Connect to Discretional ACL (DACL) for domain object

' ------------------------------------------------------------

Set objRootLDAP = GetObject("LDAP://rootDSE")

strPathToDomain = "LDAP://" & objRootLDAP.Get("defaultNamingContext") ' e.g. string dc=fabrikam,dc=com

Set objDomain = GetObject(strPathToDomain)

WScript.Echo "Accessing object: " + objDomain.Get("distinguishedName")

Set objDescriptor = objDomain.Get("ntSecurityDescriptor")

Set objDacl = objDescriptor.DiscretionaryAcl

' ------------------------------------------------------------

' Add the ACEs to the Discretionary ACL (DACL) and set the DACL

' ------------------------------------------------------------

objDacl.AddAce objAce1

objDescriptor.DiscretionaryAcl = objDacl

objDomain.Put "ntSecurityDescriptor", Array(objDescriptor)

objDomain.SetInfo

WScript.Echo "SUCCESS!"

And this script can help pull the assigned ACEs out to show you who has been delegated access: https://gallery.technet.microsoft.com/ScriptCenter/0bd4af9e-968a-4ae6-9950-2b2450afda37/

Comments

  • Anonymous
    January 01, 2003
    @Ryan. Sure. There are only 2 reasons to create an OU:
  1. Apply different GPOs
  2. Apply different delegation. And all we're doing here is delegating. So in LDP, instead of opening the ACL of the domain (as we're doing in the example above), you'd open the ACL on the relevant OUs and add different groups per OU. And the "control access flag" isn't a special function of the domain object, you can apply it to OUs also. The scripts above also delegate the access mask "read property" which I've forgotten to include on the screenshot above. I'll try and get that updated.
  • Anonymous
    January 01, 2003
    @Rob Joyner: Rob, it sounds like your account is a member of domain admins and as such is already delegated rights to the attributes. That your delegated group has no permissions is a troubleshooting case that is too difficult to perform over blog comments. Contact Microsoft Support, quoting this blog to get assistance.

  • Anonymous
    January 01, 2003
    Thanks Craig, this post was most valuable for me.

  • Anonymous
    January 01, 2003
    @Mats - that's exactly what the table at the top of the post says to do.

  • Anonymous
    January 01, 2003
    @Craig. Have just tried this out in our corporate environment, used the same new AD group for all 3 ACE's have found that members of the group (its actually a few team groups added to the group bound to each ACE) still cannot see the keys in AD. Have tried reboot and relogin.. no difference. Strange thing is that my corporate elevated account (which is almost the same privs + admin access to servers) does work... and I can't specifically work out why. Even if I drop my elevated account from the server admin group it still works.
    Puzzled!!!.... any ideas ?

  • Anonymous
    January 01, 2003
    The problem reported by Rob, Mats, and Sean is very likely the fact that the Object Type restriction shown in the screenshot above (bottom-right) is incorrect. Object Type should actually be left blank when implementing delegation via LDP. If delegation is implemented by using the VBScript rather than LDP, this problem does not occur since the script does not specify an attribute restriction for the permission.

  • Anonymous
    June 07, 2011
    Hi, Is it possible to delegate the msfve recoveryinformation on a more granular level? Say to OU's? We dont want everybody in our domain to be able to view the recovery information for all computers?

  • Anonymous
    June 16, 2013
    Thank you, Craig! This post is very helpful for me!

  • Anonymous
    August 14, 2013
    Great post, helped a lot!! Many thanks

  • Anonymous
    May 15, 2014
    Pingback from Manage Local Admin Passwords – Additional Comments | JohanPersson.nu

  • Anonymous
    July 14, 2014
    Didnt work if I delegated access only on those two attributes, I needed to set them on the msFVE-RecoveryInformation object, then the standard user could see the key

  • Anonymous
    September 04, 2014
    @Mats, i had the same issue, to add clairity, i added a 4th ACE for non-admins that looks like this:
    ACE Type: Allow
    Read Property: Checked
    Control Access: Checked
    Inherit: Checked
    Inherit Only: Checked
    Object Type: msFVE-RecoveryInformation - class
    Inherited Object Type: msFVE-RecoveryInformation

  • Anonymous
    October 05, 2014
    Delegating access in AD to BitLocker recovery information - A Premier Field Engineer in Denmark - Site Home - TechNet Blogs

  • Anonymous
    October 11, 2014
    Delegating access in AD to BitLocker recovery information - A Premier Field Engineer in Denmark - Site Home - TechNet Blogs

  • Anonymous
    October 14, 2014
    Delegating access in AD to BitLocker recovery information - A Premier Field Engineer in Denmark - Site Home - TechNet Blogs

  • Anonymous
    October 15, 2014
    Delegating access in AD to BitLocker recovery information - A Premier Field Engineer in Denmark - Site Home - TechNet Blogs

  • Anonymous
    October 15, 2014
    Delegating access in AD to BitLocker recovery information - A Premier Field Engineer in Denmark - Site Home - TechNet Blogs

  • Anonymous
    October 18, 2014
    Delegating access in AD to BitLocker recovery information - A Premier Field Engineer in Denmark - Site Home - TechNet Blogs

  • Anonymous
    November 05, 2014
    Delegating access in AD to BitLocker recovery information - A Premier Field Engineer in Denmark - Site Home - TechNet Blogs

  • Anonymous
    August 20, 2015
    The comment has been removed

  • Anonymous
    August 21, 2015
    @Keith: I haven't got the bandwidth in my calendar to write a sample script which could do this, sorry. Try one of the many vbscripting chat forums for help if needed. The object class you are looking for is ms-FVE-RecoveryInformation and this will have an attribute of msFVE-RecoveryPassword. Each computer object which is BitLocker encrypted creates these child objects under their computer object, if configured to, and only at the time of encryption.
    Better yet, MBAM is the product to manage BitLocker recovery keys. It has a self service portal to retrieve keys from and audit logging to see who is retrieveing which keys, along with a host of other features.

  • Anonymous
    August 24, 2015
    I had to dig into the scripts because the GUI solution didn't work for me. I thought maybe I overlook something and digging in the script would point me to the detail I am missing. looking into the script found a couple of things;
    In DelegateBitLocker.vbs (and the source), there are 3 variables declared that are not used.
    SCHEMA_GUID_MS_FVE_RECOVERYPASSWORD
    SCHEMA_GUID_MS_FVE_KEYPACKAGE
    SCHEMA_GUID_COMPUTER

    SCHEMA_GUID_COMPUTER is only used in the second script but declared in the first script as well.

    SCHEMA_GUID_MS_FVE_RECOVERYPASSWORD and SCHEMA_GUID_MS_FVE_KEYPACKAGE seem to be missing. They are not set in the ACE object, (objAce1.ObjectType is missing in the first script, it is set in the second script). I don't know the outcome (Default in the GUI is ) but I'm sure it's a different outcome than the GUI guide.

    Maybe this is the difference that makes it work? because I see no one complaining your solution doesn't work. Maybe is it something in my environment that prevents your solution to work. checking the permissions on the msFVE-RecoveryInformation object in ldp.exe shows the desired permissions and my test user is member of the "trustee" group.

  • Anonymous
    August 25, 2015
    changing object type to "none" for both ACE's that will be inherited by msFVE-RecoveryInformation objects makes it work. but produces 2 identical ACE's. removing one ACE will delete both,

    create a single ACE with objecttype and inherited msFVE-RecoveryInformation, works.

    This could mean that a permission on an unknown attribute is missing. I tried an extra ACE for the one remaining msFVE attribute, but that didn't work. it could be any attribute.

  • Anonymous
    November 12, 2015
    Hi, i want to delegate the permissions to different OU's, Is this possible with the script in this post? What do i have to fill in and where?

  • Anonymous
    November 13, 2015
    @sander.kl - just change the strPathToDomain to be whatever DN you need, e.g. strPathToDomain = "LDAP://OU=Standard Users,OU=Accounts,DC=corp,DC=contoso,DC=com"

  • Anonymous
    December 19, 2016
    The comment has been removed

    • Anonymous
      December 21, 2016
      The comment has been removed
  • Anonymous
    February 03, 2017
    Hi,could there be any way to revoke the permission from groups or users again?We got some users that are not in domain admin group but still are able to retrieve bitlocker information from ad.I already tried to make a group and explicitly deny view permission via LDP.exe for it but members of the group are still able to view the information. What could be good attempt to revoke the permission from users again?Thank you very much

    • Anonymous
      February 05, 2017
      @Peter - This post details adding additional groups to be able to read this data. Domain Admins always has access via its inherited "Full Control" ACE. You don't say if you added another group to have access to BitLocker data and that they are members of that group or not. In any case, troubleshooting your configuration over Blog post comments isn't going to be effective use of our time. Please do create a support case at http://support.microsoft.com to get your issue resolved.
  • Anonymous
    March 07, 2017
    Ran the scripts off the original technet post and also tried to follow the GUI steps in the screenshot, not able to read the bitlocker key with my delegated user. I can read the data with my domain admin user. Not sure where mine is different.

  • Anonymous
    April 04, 2017
    Hi Craig,I can confirm the issue with the Object Type. When I set Object Type to none, it works fine. Maybe you can change the screenshots.