Thursday, April 18, 2019

How NOT to use the PAM trust - Leveraging Shadow Principals for Cross Forest Attacks

I did a super interesting AD security assessment for a client recently. They are re-deploying their infrastructure and upgrading their forest(s) to Server 2016 Functional Level. There are so many interesting things which we did during the assessment but the most interesting for me was their attempt to establish Privileged Access Management (PAM) trust in an "interesting" way. It is a classic example of deploying something which sounds secure without actually understanding what it does. 

Microsoft introduced Privileged Access Management (PAM) with Server 2016. Among other things, it has very interesting features like -
- A bastion forest (Think the administrative forest in ESAE or the famous Red Forest)
- Shadow security principals
- Temporary group membership (Add a user to a group with time-to-live (TTL))

So what is PAM? 


PAM has been discussed in much detail here by Russel and here by Willem. Please read them for understanding what PAM has to offer. A quick explanation is below:

In a perfect world, PAM enables managing an existing production/user forest using a bastion forest which has a one-way PAM trust with the existing forest. The users in the bastion forest can be 'mapped' to privileges groups like Domain Admins and Enterprise Admins in the user forest without modifying any group memberships or ACLs. This is done by creating Shadow security principals in the bastion forest, which are mapped to SIDs for high privilege groups in the user forest and then add users from the admin forest as members of the shadow security principals.

Example


Let's have a look at an example. We have powershell.local as our user forest and bastion.local as the bastion or admin forest. What we want to do it to be able to manage powershell.local from bastion.local without modifying any group membership or ACLs on powershell.local.

A one way PAM trust can be established between the two forest using the commands below (taken from Petri article linked above) :
On user forest (powershell.local in our example) -
On bastion forest -
Shadow Principals reside in a special container 'CN=Shadow Principal Configuration' in the Configuration container on bastion forest. We can create Shadow security principals on bastion.local using the below PowerShell code:
In the above command we are mapping the SID of Enterprise Admins group of the user forest powershell.local to a Shadow security principal "psforest-ShadowEnterpriseAdmin". Please note that we can also map the shadow principal to a user in the user forest.

Finally, we need to make users from bsation.local member of the Shadow security principals:
Shadow Principals reside in a special container 'CN=Shadow Principal Configuration,CN=Services' under the Configuration container on bastion forest. We can create Shadow security principals on bastion.local using the below PowerShell code:

Now, it is possible to manage powershell.local forest from bastion.local without making any changes in the group memberships or ACLs on powershell.local.

This looks great! This takes away administrative overhead of managing groups and ACLs and reduces chances of lateral movement techniques like OverPTH, PTT and other credential relay techniques.

Now, there is something worth noticing about the above setup. To be able to use the shadow security principals, we had to allow SIDHistory in the PAM trust which means no SID Filtering. We will see in the next section how this can be dangerous if not configured properly.

The Misconfiguration

 

Let's get back to the scenario I saw during the assessment. The client enabled PAM and they were using a forest in production (not a separate bastion or admin forest) to manage other forest(s). The forest used to manage other forests was located at their headquarters and their forests for their sites across the country were managed using it. An applause for them to have separate forests for different locations :)

They were sold on the part that using PAM will protect the credential based attacks - no logon using credentials from the bastion forest to any other forest.

But, a PAM trust where you do not have an isolated bastion forest is disastrous. Why? Because in such a case if we compromise the bastion forest we get high privileges (Enterprise Admins or Domain Admins) in the other forest. And:
- There is no group membership (unlike Foreign Security Principals)
- No ACLs modification
- AFAIK, no other modification to look for in the forest which gets compromised!

Let's have a look at an example. Following is the setup in my lab (diagram built using draw.io):
defensiveps.local is the bastion forest and powershell.local is the user/production forest.

Abusing the PAM trust


Here is how to identify and approach abusing a PAM trust:

Enumeration

First, let's enumerate if our current forest has any PAM trust with any other forest, that is, if our current forest can access any other forest without worrying about SID Filtering.

Using the ADModule, we can simply run Get-ADTrust and look for a trust which has ForestTransitive set to True and SIDFilteringQuarantined set to False - this means that SID Filtering is disabled.

Powerview (dev branch), calculates the TrustAttributes for you but does not tell you if SID Filtering is enabled when used from the user/production forest.

On the other hand, if you want to enumerate if your current forest is managed by a bastion forest (Blue Teams take note), look for ForestTransitive set to True and SIDFilteringForestAware set to True. In this case, TrustAttributes is also a very good indicator. It is 0x00000400 (1024 in decimal) for PAM/PIM trust. Simplifying it, it is 1096 for PAM + External Trust + Forest Transitive.
In this case (when rum from the bastion forest), PowerView (dev) tells if PIM Trust is enabled.

Next, let's enumerate the shadow security principals, its members from the current (bastion) forest and privileges in the user/production forest. We can use the following command from the ActiveDirectory module:
 
As clear in the above screenshot, we can look for Shadow securtiy principals in the special container 'CN=Shadow Principal Configuration,CN=Services' under the Configuration container on bastion forest. Following properties are the most interesting ones:

- Name - Name of the shadow principal

- member - Members from the bastion forest which are mapped to the shadow principal. In our example, it is the Domain Administrator of defensiveps.local.

- msDS-ShadowPrincipalSid - The SID of the principal (user or group) in the user/prodcution forest whose privileges are assgined to the shadow security principal. In our example, it is the Enterpise Admins group in the user forest.

Using the shadow principals

Now, if we compromise the user listed in "member" above we can use the shadow principals. In our example, we need to compromise the Administrator user fo defensiveps.local forest and then we will have enterpirse admins privileges on powershell.local forest!
This is very interesting! We crossed the forest security boundary with ease :) Remember that we need not have group membership or ACL on the user forest.

With the privileges achieved using shadow principals above, we can access the user forest using RDP (explicit credentials of the bastion user required), WMI, PowerShell Remoting etc. Please note that if Kerberos AES Encryption is not enabled for the PAM trust, we need to add the machines of existing forest in WSMan TrustedHosts and use '-Authentication Negotiate' option with PowerShell remoting cmdlets.
UPDATE (23/04/2019): Please note that we can also use SIDHistriy injection using mimikatz to abuse the PAM trust. I left it out because using a shadow principal looks more normal in the user forest then SIDHistory injection. But, since Riccardo pointed out that it will still be useful, please take a note of it!

Persistence

We can also use this for persistence. Please note that the persistence will be for the privileges on the user/prodcution forest and not the bastion forest itself. 

Once we have compromised the bastion forest, there are multiple ways we can use:

1. We can add a user to an existing shadow security principal container.

Please note that in this case, if someone looks at the details of the 'lowprivuser', he/she would appear to be a part of the psforest-ShadowEnterpriseAdmin 'group'.

2. Better, we can modify the ACL of the shadow principal object. We can provide a user we control, Full Permission overt shadow principal object but the fun is always with minimal permissions. So, with only Read Members and Write Members permissions on the shadow principal object, we can add and remove princiapls at will from the shadow principals. Take a look at the below screenshot:

Now, we can add or remove users at will with the privileges of 'reportdbadmin' user. On top of that, by-default there are no logs for any changes to the ACL or 'membership' of a shadow principal :)

Is PAM trust bad? Should I stop using a bastion forest?  Why is Microsoft so evil? What is the meaning of life?


PAM trust is not bad, IF used wisely! You can use a bastion forest with PAM trust but please be careful. Learn from the setup we discussed just now. Do not use a regular forest (with users doing non-admin activities) as bastion forest. As Willem pointed out in his article, when you use the PAM trust you extended the security boundary of the user forest to include the bastion forest. Treat the bastion forest as a special case and you will be fine.

Detection

On the bastion host, as we already discussed, there are no logs by-default for modification of membership or ACL of shadow principals.

On the existing/production forest, the detection seems pretty easy. There will always be the Speical Logon (4672), Logon (4624) and Logoff (4634) events when anyone uses principal from the bastion forest to access the existing forest. But the problem here is to detect an anomaly as the same logs will be there for actual operations as well. Unless, an adversary is using a new user or doing something very noisy, it may be difficult to detect her with only these entries.

I hope this post enocurages everyone to have another look at their forest trusts. As always, please leave feedback :)