Shadow Principals is a new cool feature in Active Directory 2016. It’s part of the Optional Feature Privileged Access Management. I have covered the basic concept with Just In Time Admin Access two years ago, and I also wrote about time-based groups a year ago.
The first article is kind of outdated and everything wasn’t fully implemented yet. Missing pieces was Shadow Principals and PIM Trusts. So, I decided to write an article about it and how to test it with basic built-in functionality.
Just a quick background if you don’t want to read earlier posts:
A while back Microsoft release a guidance of Securing Privileged Access.
In step three they include creating one and even two new forests for managing privileged admin accounts (in this example we will use one). You can read more about it here: ESAE Administrative Forest Design Approach.
The idea is: to secure the existing production domain, a shadow forest will be created and is a single domain forest built on Windows Server 2016, it is hardened and locked down from day one. By using the new PAM feature we can create Shadow Principals based on the production domain and grant time limited access (which also is integrated in Kerberos).
The administrative groups in the production domain will be empty and kind of remove the map of admins in the domain. The shadow admins will only have administrative access in the production domain when needed providing just-in-time administration (JIT).
With this, Microsoft Identity Manager also comes in to play with its PAM feature managing this in the Shadow Forest, where users can request admin access.
In this example, we won’t use MIM, we will look at the Shadow Principal and test the PAM feature in Active Directory at its core basics.
The environment will be two domains:
- The production domain corp.secid.se. From now on called the CORP domain.
- The shadow domain priv.secid.se. From now on called the PRIV domain.
Now when that is done, let’s start with the actual blog post 🙂
In the Windows Server 2016 version a couple of new Objects and a Attribute was introduced:
msDS-ShadowPrincipalContainer:
This class is the dedicated container for msDS-ShadowPrincipal objects. One default container is created in the Services container in the Configuration NC.
CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=priv,DC=secid,DC=se
You can create Principal Containers in other locations but won’t work with Kerberos.
msDS-ShadowPrincipal:
This class represents a principal from an external forest. Can only be created in a Shadow Principal container, it must have a msDS-ShadowPrincipalSid value.
A Shadow principal can represent any Security Principal User, Security Group or Computer. It also has the member attribute and here is one of the cool stuff with PAM and Shadow Principals, we can set TTL values on the membership the same way as with time-based groups.
If the Shadow Principal resides in the default CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=X container, the membership any domain user has of any Shadow Principal will be added in the Kerberos tickets as with any other group membership. One constraint is it can only have members of principals within its own forest.
If a TTL value of the membership is set it will integrate with Kerberos and the lifetime of the tickets will be set to the shortest expiring TTL value.
msDS-ShadowPrincipalSid:
This attribute contains the SID of a principal from an external forest. It has constraints so you can’t add SIDs from its own domain or from any other domain within its own forest. You also must have a forest trust configured to being able to add the SIDs from another domain.
This attribute is also indexed.
To setup a simple PoC we have a few prerequisites and configuration to do:
To be able to use this the Forest Functional Level of the PRIV Forest must be in Windows Server 2016 Mode and have the PAM optional feature enabled.
Since this is a new fresh Forest we only need to enable the PAM Optional Feature with a simple PowerShell one-liner:
Enable-ADOptionalFeature "Privileged Access Management Feature" –Scope ForestOrConfigurationSet -Target priv.secid.se
NOTE: This action isn’t revertible.
Since it’s a shadow principal containing SIDs from other forest next step is to configure a trust. You will need to have at least a one-way incoming forest trust from the domain you want to use as Shadow Principals.
In this example, we will create a one-way forest transitive trust. We need to disable Quarantine and Enable SIDHistory so the SIDs from CORP domain won’t be filtered out when a user from the PRIV domain logs on to a server in CORP.
In Windows Server 2016 there is a new type of trust for this scenario, it’s called a PIM trust. In earlier versions, it wasn’t possible to have SIDs like Domain Admins and Enterprise Admins to be used with SIDHistory, they were always filtered out.
In this scenario, this is what we want so we also must enable the PIM Trust option.
If you have a Windows Server 2012R2 FFL domain there is a patch you can install to enable this feature: Article ID: 3155495
In CORP domain we can use the netdom command line tool and run the following commands:
netdom trust corp.secid.se /Domain:priv.secid.se /Add /UserD:pdanne@priv.secid.se /PasswordD:* /UserO:danne@corp.secid.se /PasswordO:*
netdom trust corp.secid.se /domain:priv.secid.se /ForestTRANsitive:Yes
netdom trust corp.secid.se /domain:priv.secid.se /EnableSIDHistory:Yes
netdom trust corp.secid.se /domain:priv.secid.se /EnablePIMTrust:Yes
netdom trust corp.secid.se /domain:priv.secid.se /Quarantine:No
In the PRIV domain we only need to run:
netdom trust priv.secid.se /domain:corp.secid.se /ForestTRANsitive:Yes
And don’t forget to enable Kerberos AES encryption for the trust in the PRIV domain. Open properties on the CORP TDO object in the System container and mark the checkbox: The other domain supports Kerberos AES Encryption.
Since the CORP forest trusts the PRIV forest the users in PRIV can read everything authenticated users is granted in AD and this will be enough in this example.
To create a Shadow Principal, we need to get the SID of the Security Principal in the CORP domain we want to use. Here is a simple example with PowerShell where we get the properties we need from the example group Domain Admins and then use it to create the Shadow Principal in the PRIV domain.
$CORPPrincipal = "Domain Admins"
$CorpDC = "corpdc01.corp.secid.se"
$ShadowSuffix = "CORP-"
$CorpShadowPrincipal = Get-ADGroup -Identity $CORPPrincipal -Properties ObjectSID -Server $CorpDC
$ShadowPrincipalContainer = "CN=Shadow Principal Configuration,CN=Services,"+(Get-ADRootDSE).configurationNamingContext
New-ADObject -Type "msDS-ShadowPrincipal" -Name "$ShadowSuffix$($CorpShadowPrincipal.SamAccountName)" -Path $ShadowPrincipalContainer -OtherAttributes @{'msDS-ShadowPrincipalSid'= $CorpShadowPrincipal.ObjectSID}
In this example, I created a shadow of Domain Admins group. I have also done this for my CORP user account Tony, you see, it’s not bound to creating shadow groups, you can take any Security Principal.
Now when we have the Shadow Principals in place we can use the TTL feature for the member attribute.
Add a user in the PRIV domain as member of the Shadow Principals with a TTL of 3600 seconds (1 Hour).
Set-ADObject -Identity "CN=CORP-User-Tony,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=priv,DC=secid,DC=se" -Add @{'member'="<TTL=3600,CN=Priv-Al Bundy,OU=CORP-Shadow,DC=priv,DC=secid,DC=se>"}
Set-ADObject -Identity "CN=CORP-Domain Admins,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=priv,DC=secid,DC=se" -Add @{'member'="<TTL=3600,CN=Priv-Al Bundy,OU=CORP-Shadow,DC=priv,DC=secid,DC=se>"}
The GUI doesn’t have built-in functionality to show the TTL value of the membership, and Microsoft hasn’t implemented the LDAP Control for Get-ADObject cmdlet, its only part of Get-ADGroup and Get-ADGroupMember. Since Shadow Principals isn’t a real group we can’t use those cmdlets. That’s a shame.
Instead we must use LDP.exe and the LDAP Controls: LDAP_SERVER_LINK_TTL_OID 1.2.840.113556.1.4.2309 to verify this.
Hopefully Microsoft releases an update to the Get-ADObject or something.
Now when we have the trust, the shadow principal and a time-based member we can use this in the CORP domain.
If we logon to a management server in the CORP domain with a regular user, we can choose to start PowerShell with another account from the PRIV domain:
If we run whoami and whoami /groups we can see that the PRIV\priv.al user has CORP\Domain Admins membership and also is CORP\Tony.
And then run Get-ADGroupMember -Identity "Domain Admins"
we only see the default member Administrator.
Since the PRIV\priv.al user is member of the Shadow Groups in the PRIV domain, the KDC will add those in the Kerberos tickets. The machines in the CORP domain will resolve it to the real groups in its own domain.
If we run klist we also see that the tickets lifetime is under an hour and when the time is up, he won’t be a Domain Admin nor a Tony anymore.
In the future, we will also use JEA in combination with JIT/PAM and we’ll start seeing some really cool things. But that’s for another time.
Hello,
Based on my first tests on Shadow Group, I have built quickly a set of functions available in a Powershell module (Manage-ADShadowGroup).
If it can help someone… Available here : https://github.com/MS-LUF/Manage-ADShadowGroup
Lucas.
Best guide out there. Thank you!
Hi Daniel,
I’m not seeing a TTL under the member attribute under LDAP? I’m running 2016 FFL and Domain Level. Any ideas?
member: CN=PRIV.test.user,OU=PAM objects,DC=fsbx,DC=gig,DC=com;
Question why is the trust transitive? We only have two forest. From my understanding transitivity does not actually take place here. Am I wrong?
Hi,
Forest trusts are always transitive, if not its something else.
You can try to remove 0x8 on the trustAttributes attribute in a forest trust object 😉