Today, on July 15th I received an e-mail from Microsoft I was re-awarded again with the MVP Award for the Identity & Access and PowerShell Areas. This year is the 21st time I have received this award!
Thank you Microsoft for the award, and thank you Semperis for supporting this adventure.
Let’s go for yet another year! Whooohoooo!
Going into my 22nd year!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
This release (v4.1) is a MINOR update with bug fixes, feature requests and feedback from the community. The biggest feature request, and now supported, was the ability to fully customize both the SUBJECT and BODY of the e-mail being send. To support that, the XML structure of the Configuration XML file was updated. If using the new script with an older XML file, the script will abort and notify about that accordingly.
Below is the link for the main github page of the script containing everything.
As ALWAYS, TEST FIRST IN A TEST ENVIRONMENT (I DID 😉 )!!!
HAVE FUN!
PS: Got any feedback or request, please use Github to report bugs or requests! Thanks!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
About 4 years ago a colleague of mine wrote a blog post about how it is possible to misuse a unidirectional trust (forest or external) from the side of the trusting AD domain/forest. About 2 years ago I also wrote about the same and added somewhat more details to the story. However, that was in the Windows Server 2022 or earlier era. Since a few years, we can now also use Windows Server 2025.
The question is obviously: “Are there any changes in Windows Server 2025 around this”?
The short and sweat answer to that question is: YES!, but unfortunately not what you would expect.
To explain what is new and how it works, I will first explain the environment I will be working with and the tools used. I will also explain how to test this yourself in a TESTLAB and also provide the commands for you to try out.
So what’s new in Active Directory 2025 with regards to trusts?
By default a trust account, a special user account, has the primaryGroupID set to Domain Users (a.k.a. GROUP_RID_USERS = 513).
However as soon as the first W2K25 RWDC is introduced, the AD schema will be extended to support those DCs. As soon as the PDC FSMO is transferred onto the W2K25 RWDC, the following happens:
The global security group “Forest Trust Accounts” (objectSid = <Forest Root Domain SID>-528) is created
The global security group “External Trust Accounts” (objectSid = <Domain SID>-529) is created
All Forest Trust Accounts are reconfigured with a new primaryGroupID 528, and with that become a member of the “Forest Trust Accounts” global security group
All ExternalTrust Accounts are reconfigured with a new primaryGroupID 529, and with that become a member of the “External Trust Accounts” global security group
Figure 1: The New Trust Related Global Security GroupsFigure 2: A Forest Trust Account With The New PrimaryGroupID
What does that mean?
Any resources secured with global security group “Domain Users” or domain local security group “Users” are now not accessible anymore by any trust account! Cool! But is there more to this?
To try to answer that question, let’s go back to a session delivered in 2023 about what’s new in Windows Server 2025.
Figure 3: Comments Section Of The What’s New In Active Directory 2025
Looking at the question from Robin (a.k.a. CANIX1) and the response from Linda to his question, *I* got the impression the 2 new security groups would ALSO prevent the authentication of trust accounts to perform e.g. reconnaisance in the trusted domain from the trusting domain. With that in mind, a custom authentication policy would not be needed anymore as an internally coded one would achieve the same goal. NICE!
Let’s try that out and see what happens!
For starters, let’s FIRST check out the TRUSTED AD DOMAIN “IAMTEC.NET”
Figure 8a: The Secrets/Keys Of The Trust Account In The Trusted AD Domain For The Trusting AD DomainFigure 8b: The Secrets/Keys Of The Trust Account In The Trusted AD Domain For The Trusting AD Domain
Now, let’s check out the TRUSTING AD DOMAIN “PARTNER.LAN”
Figure 10: The Outgoing Trust Endpoint In The Trusting AD Domain
As a bad actor controling the TRUSTING AD domain/forest, I can do whatever I found in that AD domain/forest. The next step is to try to move into the TRUSTED AD domain! Let’s try that out.
Creating an offline copy of the NTDS.DIT to grab the credentials from the trust in the trusting AD domain
Figure 11: The Secrets/Keys Of The Trust Account In The Trusting AD Domain For The Trusted AD Domain
If you compare the secrets (figure 11 and figure 8b), you will see those are the same on both sides. Obvious as it is required for a trust account to work!
Grabbing the different secrets/keys from the trust for the TRUSTED AD domain and putting those in variables to use later
Figure 13: Trying To Get In The Trusted AD Domain From The Trusting AD Domain Using The AES 128 Key Of The Trust Against The W2K22 DC
Grabbing TGT for the trust account in the TRUSTED AD domain against a W2K22 DC and using the RC4 KEY….FAILURE! (Probably because RC4 is not allowed due to its recent deprecation)
Figure 14: Trying To Get In The Trusted AD Domain From The Trusting AD Domain Using The RC4 Key Of The Trust Against The W2K22 DC
Grabbing TGT for the trust account in the TRUSTED AD domain against a W2K25 DC and using the AES256 KEY….SUCCESS! (With what I thought earlier, this was not really expected!)
Figure 15: Trying To Get In The Trusted AD Domain From The Trusting AD Domain Using The AES 256 Key Of The Trust Against The W2K25 DC
Grabbing TGT for the trust account in the TRUSTED AD domain against a W2K25 DC and using the AES128 KEY….SUCCESS! (With what I thought earlier, this was not really expected!)
Figure 17: Trying To Get In The Trusted AD Domain From The Trusting AD Domain Using The RC4 Key Of The Trust Against The W2K25 DC
Now, let’s grab the TGT again for the trust account in the TRUSTED AD domain against a W2K25 DC and using the AES256 KEY. We now want to see the content and understand what the group memberships are of the trust account under the new conditions in W2K25. However to be able to see the content of the TGT we need to have the secret/key of the KRBTGT account in the TRUSTED AD domain that encrypted the TGT. Remember, as a bad actor I only control the TRUSTING AD domain, and NOT the TRUSTED AD domain! So, having that said, just to show the content of the TGT I will just use the KRBTGT from the TRUSTED AD domain.
Figure 18a: Getting The Secrets/Keys Of The KRBTGT Account In The Trusted AD DomainFigure 18b: Getting The Secrets/Keys Of The KRBTGT Account In The Trusted AD Domain
Figure 19: Getting A TGT For The Trust Account In The Trusted AD Domain From The Trusting AD Domain Using The AES 256 Key Of The Trust Against The W2K25 DCFigure 20a: Displaying The Content Of The TGT For The Trust Account In The Trusted AD Domain From The Trusting AD DomainFigure 20b: Displaying The Content Of The TGT For The Trust Account In The Trusted AD Domain From The Trusting AD Domain
So, the careful conclusion here is that the 2 new global security groups unfortunately DO NOT resolve the issue by misusing the trust accout in the TRUSTED AD domain from the TRUSTING AD domain. So what is the solution? The solution previously being used, the creation of an Authentication Policy in the TRUSTED AD domain referring to a a non-existing Authentication Silo is still required!
Let’s set that up in the TRUSTED AD domain.
The creation of an Authentication Policy referring to a non-existent Authentication Silo
$authNPolicyParams = @{
Name = "AuthN_Policy_Protecting_Trust_Account_From_Trusting_Domains"
Description = "AuthN Policy Protecting Trust Account From Trusting Domains"
Figure 22: Assigning The New Authentication Policy In The Trusted AD Domain To The Trust Account In Trusted AD Domain
Grabbing TGT for the trust account in the TRUSTED AD domain against a W2K22 DC and using the AES256 KEY….FAILURE! (due to the presence and assigned Authentication Policy in the TRUSTED AD domain)
Figure 23: Trying To Get In The Trusted AD Domain From The Trusting AD Domain Using The AES 256 Key Of The Trust Against The W2K22 DC – After Configuring And Assigning The Authentication Policy In The Trusted AD Domain
Grabbing TGT for the trust account in the TRUSTED AD domain against a W2K25 DC and using the AES256 KEY….FAILURE! (due to the presence and assigned Authentication Policy in the TRUSTED AD domain)
Figure 24: Trying To Get In The Trusted AD Domain From The Trusting AD Domain Using The AES 256 Key Of The Trust Against The W2K25 DC – After Configuring And Assigning The Authentication Policy In The Trusted AD Domain
Now you may ask yourself…. Why is it still possible to read AD content? The main reason is that the trust account is still part of AUTHENTICATED USERS, and that is very likely part of the “Pre-Windows 2000 Compatible Access” security group. As an addition to the Authentication Policy, it is also a good idea to remove Authenticated Users from the “Pre-Windows 2000 Compatible Access” security group to enhance the security posture of your AD. But WAIT before actually doing that as it very likely will break stuff!!!! Before removing the Authenticated Users from the “Pre-Windows 2000 Compatible Access” security group, you need to understand which properties on objects in AD are protected by the “Pre-Windows 2000 Compatible Access” security group, which systems and applications required access to those properties on objects in AD. As soon as you know that, and TESTED it, you can…. well that is a very long story, that colleague of mine already wrote about here.
So…… the main and overall conclusion is that even with W2K25 DCs, the creation and configuration of an authentication policy in the TRUSTED AD domain is still required in the case of a uni-directional forest or external trust to protect the trust!
Protect yourself and implement this easy and very effective solution!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
As ALWAYS, TEST FIRST IN A TEST ENVIRONMENT (I DID 😉 )!!!
HAVE FUN!
PS: Got any feedback or request, please use Github to report bugs or requests! Thanks!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
As ALWAYS, TEST FIRST IN A TEST ENVIRONMENT (I DID 😉 )!!!
HAVE FUN!
PS: Got any feedback or request, please use Github to report bugs or requests! Thanks!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
As ALWAYS, TEST FIRST IN A TEST ENVIRONMENT (I DID 😉 )!!!
HAVE FUN!
PS: Got any feedback or request, please use Github to report bugs or requests! Thanks!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
As ALWAYS, TEST FIRST IN A TEST ENVIRONMENT (I DID 😉 )!!!
HAVE FUN!
PS: Got any feedback or request, please use Github to report bugs or requests! Thanks!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
Some days ago I was reading REDDIT and stumbled across this post, where someone mistakenly deleted a DNS application partition. I responded to that post by providing steps on how to recover. In addition I also wanted to refresh my memory and see if i had written down was correct or not. All I wrote in that REDDIT post was correct with the addition of having forgotten 1 important step!
WARNING: The steps listed here apply to restoring a deleted Application Partition in Active Directory. These steps DO NOT apply to restoring a deleted AD Domain!
To test this all out I used the following TEST environment:
AD Forest: IAMTEC.NET
Forest Root AD Domain: IAMTEC.NET –> 3x live RWDCs – W2K19 – R1FSRWDC1 (All Forest And Domain FSMO Roles), R1FSRWDC2, R1FSRWDC3) and 1x live RODC (W2K19 – R1FSRODC1) and 1x bogus RODC (RIVERBED)
Figure 1: Creating The Application Partition And Enlisting Additional DCs To Host It
Gave the DCs some minutes to replicate the partition data around.
Figure 2: The Definition (I.e., crossRef Object) Of The Application Partition
After this, I created a full backup of the AD forest using Semperis ADFR. After having confirmed the backup had completed successfully, it was time to start with the “mistaken” deletion. I used the following code to delete the application partition
NTDSUTIL
ACTIVATE INSTANCE NTDS
PARTITION MANAGEMENT
CONNECTIONS
CONNECT TO SERVER R1FSRWDC1.IAMTEC.NET
Q
LIST NC REPLICAS DC=APP_NC_TEST
DELETE NC DC=APP_NC_TEST
Q
Q
Figure 3: Listing The DCs That Host The Application Partition And Deleting The Application Partition
Gave the DCs some minutes to replicate the deletion of the partition data around.
To make sure all was deleted I used the following code:
With the following event from every DC hosting the partition, I knew for sure the partition did not exist anywhere anymore!
Figure 4: Confirming The Partition Was Deleted/Removed On All DCs In The AD Forest (In This Case!)
After the deletion of the data, I used Semperis ADFR to non-authoritatively restore the DC R1FSRWDC2.IAMTEC.NET using the most recent backup created.
Figure 5a: Non-Authoritative Restore Using Semperis ADFR Figure 5b: Non-Authoritative Restore Using Semperis ADFR Figure 5c: Non-Authoritative Restore Using Semperis ADFR
After the non-authoritative restore the DC R1FSRWDC2.IAMTEC.NET, I confirmed that INbound AD replication was disabled. This is needed to be able to authoritatively restore some objects to bring back the deleted partition. If this would not be done, more recent data in the AD Domain/Forest would update the restored DC as if nothing had happened.
Figure 6: Confirming Inbound AD Replication Was Disabled To Prevent Overwriting The Data Of The Non-Authoritative Restore
In this state I wanted to check the state of the objects of interest on both the restored DC R1FSRWDC2.IAMTEC.NET and some other DC R1FSRWDC1.IAMTEC.NET
LEFT WINDOW (RESTORED CROSS-REF OBJECT OF THE PARTITION):
Figure 8a: Comparing NTDS Settings Object Of The Restored DC On Both The Restored DC And Another DC – Differences ExistFigure 8b: Comparing NTDS Settings Object Of The Restored DC On Both The Restored DC And Another DC – Differences Exist
Now lets analyze what needs to be done! Before the non-authoritative restore the application partition “DC=APP_NC_TEST” does not exist on any DC and its definition (i.e. cross-ref object) does also not exist. The question is “how to bring back (i.e., restore) the deleted application partition?”.
One way to restore the deleted the deleted application partition “DC=APP_NC_TEST” is to perform a full AD forest restore using the most recent backup that still contains the application partition. Although a solution, that would be some serious overkill, and let alone the huge impact on the environment!
So, IMHO, the best way to bring back the deleted application partition “DC=APP_NC_TEST” is to use the most recent backup available of any DC that actually hosted the partition, following up with some additional actions.
In my case, I use the DC R1FSRWDC2.IAMTEC.NET to perform an NON-authoritative restore. Now for the follow up actions, my logic is as follows, while using the following code that also executed on the restored DC R1FSRWDC2.IAMTEC.NET (!):
At first we need to bring back the definition of the application partition. That is done by authoritatively restoring the cross-ref object of the deleted application partition.
Figure 9a: Authoritative Restore Of The Cross-Ref Object On The Restored DCFigure 9b: Authoritative Restore Of The Cross-Ref Object On The Restored DC
Now when you look at the data:
The cross-ref object lists which DCs (a.k.a. replica locations) host the application partition
The NTDS Settings object of each DC lists, across multiple attributes, which partitions (a.k.a. NCs) are hosted the corresponding DC
The first bullet has already been authoritatively restored, so that is done! However, the data of the NTDS Settings object of the restored DC on the restored DC itself is older than the data of the NTDS Settings object of the restored DC on any other DC. Check the differences in figure 8a and 8b. On the left you can see the NTDS Settings object shows that R1FSRWDC2.IAMTEC.NET hosts the application partition and on the right you can see the NTDS Settings object shows that R1FSRWDC2.IAMTEC.NET DOES NOT host the application partition. Obviously we want the version on the left to take priority. In other words, if the NTDS Settings object of the restored DC on the restored DC is not authoritatively restored, the restored DC will have the actual application partition, but other DCs WILL NOT be able to replicate from it as its NTDS Settings object does not specify the hosts the application partition. Although specified as a Replica Location, other DCs will not be able to inbound replicate and host the application data as they cannot find another DC that hosts (i.e., has instantiated) the actual partition. The restored DC, although being a Replica Location, having the data, but not having specified it has it instantiated, will not be able to service replication requests from other DCs. Something similar like the following would be seen.
Figure 10: DCs Defined As Replica Locations But Not Being Able To Instantiate The Application Partition
The solution? Also perform an authoritative restore of the NTDS Settings object of the restored DC on the restored DC. After that the NTDS Service again.
Figure 11a: Authoritative Restore Of The NTDS Settings Object Of The Restored DC On The Restored DCFigure 11b: Authoritative Restore Of The NTDS Settings Object Of The Restored DC On The Restored DC
Now you might also think that it is also needed to authoritatively restore the actual partition itself. That is not needed as nothing from that partition exists on the other DCs, and there is nothing to overwrite. The partition and its data are not in a deleted state, but rather have been fully deleted. In short, authoritative restore of the actual partition is not needed.
After the restore, OUTbound AD replication is forced on the restored DC so that the changes propagate to other DCs.
Figure 12: Forcing Outbound AD Replication On The Restored DC For The Changes To Propagate To Other DCs
LEFT WINDOW (NTDS SETTINGS OBJECT OF THE RESTORED DC ON THE RESTORED DC):
Figure 13a: Comparing NTDS Settings Object Of The Restored DC On Both The Restored DC And Another DC – NO Differences ExistFigure 13b: Comparing NTDS Settings Object Of The Restored DC On Both The Restored DC And Another DC – NO Differences Exist
It is now time to enable INbound AD Replication on the restored DC.
Forcing OUTbound AD Replication on the restored DC
REPADMIN.EXE /SYNCALL $ENV:COMPUTERNAME /edjqAP
Figure 14: Forcing Outbound AD Replication On The Restored DC For The Changes To Propagate To Other DCs
Forcing INbound AD Replication on the restored DC
REPADMIN.EXE /SYNCALL $ENV:COMPUTERNAME /edjqA
The error below can be expected if a certain DC has not (yet) instantiated the application partition
Figure 15: Forcing Inbound AD Replication On The Restored DC To Receive Any Updates From Other DCs
As of this point in the process all the other Replica Locations, as defined on the cross-ref object, that have nothing instantiated, will instantiate the application partition and inbound replicate the data from any other DC that already has instantiated the application partition, and in this case it is the DC R1FSRWDC2.IAMTEC.NET.
Checking which Replica Locations exist and which have instantiated the application partition.
NTDSUTIL
ACTIVATE INSTANCE NTDS
PARTITION MANAGEMENT
CONNECTIONS
CONNECT TO SERVER R1FSRWDC1.IAMTEC.NET
Q
LIST NC REPLICAS DC=APP_NC_TEST
Q
Q
Figure 16: Listing The Replica Locations Of The Application Partition And Their Instantiation State – Not (Yet) Complete
As you can see above, not all DCs (i.e., Replica Locations) have completed the operation. Just give it time to complete, especially when having many DCs hosting the application partition and lots of data is involved.
Figure 17: Listing The Replica Locations Of The Application Partition And Their Instantiation State – Completed!
Because of the restore of the application partition and the (re-)instantiation of the application partition, every DC hosting the application partition will report through event ID 1587 in the Directory Services Event Log it is processing the new Invocation IDs of each DC that instantiated the partition. To get assurance the process is working, I only need to see 1 Event on every DC as it otherwise could be an overload of data.
(Get-ADForest).Domains | ForEach-Object {(Get-ADDomain -Identity $_).ReplicaDirectoryServers + (Get-ADDomain -Identity $_).ReadOnlyReplicaDirectoryServers | ForEach-Object {$dcFQDN = $_; Try{$events = Get-WinEvent -ComputerName $dcFQDN -FilterHashtable @{LogName = 'Directory Service'; ID = 1587} -MaxEvents 1 -ErrorAction STOP; $events | Format-Table @{Label="DC FQDN"; Expression={$dcFQDN}},TimeCreated,LevelDisplayName,Message -Wrap -AutoSize} CATCH {Write-Host "$dcFQDN - NO EVENTS YET... PATIENCE AND RETRY (UNLESS IT IS AN RODC, A DECOMMISSIONED DC, ETC)" -ForegroundColor Red}}}
Figure 18a: Every Replica Location (I.e., Every DC Hosting) Of The Application Partition Is Processing The New Invocation ID Of Each That Instantiated The Application PartitionFigure 18b: Every Replica Location (I.e., Every DC Hosting) Of The Application Partition Is Processing The New Invocation ID Of Each That Instantiated The Application PartitionFigure 18c: Every Replica Location (I.e., Every DC Hosting) Of The Application Partition Is Processing The New Invocation ID Of Each That Instantiated The Application PartitionFigure 18d: Every Replica Location (I.e., Every DC Hosting) Of The Application Partition Is Processing The New Invocation ID Of Each That Instantiated The Application Partition
And as I final step, I want to make sure all Replica Location are fully functioning for the application partition. You can easily do that through the PowerShell script SCRIPT: Check-AD-Replication-Latency-Convergence
Figure 19a: Checking The Restored Application Partition On Every DC Hosting It And The AD Replication Between eachFigure 19b: Checking The Restored Application Partition On Every DC Hosting It And The AD Replication Between eachFigure 19c: Checking The Restored Application Partition On Every DC Hosting It And The AD Replication Between eachFigure 19d: Checking The Restored Application Partition On Every DC Hosting It And The AD Replication Between eachFigure 19e: Checking The Restored Application Partition On Every DC Hosting It And The AD Replication Between eachFigure 19f: Checking The Restored Application Partition On Every DC Hosting It And The AD Replication Between each
Everything is now back to normal again! Hope this helps someone, if this mistake occurs. Remember, although there are similarities, THESE STEPS CANNOT BE USED FOR RESTORING A DELETED DOMAIN!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
Some time ago, almost 7 years ago, I wrote a PowerShell script to reset the KrbTgt Account Password of both RWDCs and RODCs. This is UPDATE 8 – FINALLY!!!!!!!! There was lots of coding and functional and stress testing of the new and updated components, and both took some serious time. In addition, I also wanted to move the documentation from individual blog post to 1 centralized link containing everything about the script. It contains lots of information and screenshots to show what happens. I also had some moment where I wanted to release it, and then found a bug. Back to the drawing board to recode and…. retest.
More information can be found through the following links regarding the previous updates:
This release (v3.6) (v3.5 was never released) is a MAJOR update with bug fixes, requests from the community and some new stuff.
The main focus was full set and forget automation of the password reset of the KRBTGT accounts in any given AD domain. There are 2 options for automation, and use whatever option works best for you:
[OPTION 1]: Schedule the script to run every given period defined by you, e.g. every day or week at time HH:mm
[OPTION 2]: Schedule the script to run every day at HH:mm and configure and enable the Password Reset Routine. Based on the configuration it will reset the KRBTGT password at specific moments.
Below is the link for the main github page of the script containing everything.
As ALWAYS, TEST FIRST IN A TEST ENVIRONMENT (I DID 😉 )!!!
HAVE FUN!
PS: Got any feedback or request, please use Github to report bugs or requests! Thanks!
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################
When using either Group Managed Service Accounts (gMSAs) or Delegated Managed Service Accounts (dMSAs) (currently only possible Windows Server 2025 DCs), in addition to some account metadata, the KDS Root Key(s) available in the AD forest play a very important part in the password (re)calculation by the writable DCs (RWDCs) when servicing a managed password request from any server that uses the corresponding gMSA/dMSA. The set of “secret” data is stored in the msKds* attributes of the KDS Root Key Object. While the KDS Root Key object exists on ALL DCs in the AD forest, the secret data is only available on RWDCs (figure 1) and not on RODCs (figure 2). From any KDS Root Key object, the msKds* attributes are all part of the Filtered Attribute Set (FAS). All the attributes that are part of the FAS can be found when querying the Schema Partition using the filter “(&(objectClass=attributeSchema)(searchFlags:1.2.840.113556.1.4.803:=512))“.
Figure 1: The Set Of (Secret) Data Of A KDS Root Key In AD On A RWDCFigure 2: The Set Of Data Of A KDS Root Key In AD On A RODC
If you want to know which KDS Root Key is being used by any given gMSA or dMSA, when that KDS Root Key created, etc, etc, then I suggest you have a look at the following PowerShell code:
Figure 4: Relevant Data Of All The dMSAs In The AD Domain
As the KDS Root Key objects contain the secret data to calculate previous, current or even future passwords using the metadata of ANY gMSA/dMSA account (see: Get-ADDBServiceAccount From DSInternals), you can imagine those KDS Root Key objects should be protected.
By default, nobody needs any access to the KDS Root Keys or their secret data, besides RWDCs for valid purposes, and obviously attackers for bad purposes like Golden gMSA Attack or Golden dMSA Attack.
To gain OFFline access to the KDS Root Key objects, the following actions should be audited/monitored to understand if those are valid or not:
Stopping the NTDS Service on RWDCs
Restarting the RWDC
Creation of IFM Sets on RWDCs through NTDSUTIL or any other way
Creation of snapshots on RWDC through NTDSUTIL or any other way using some VSS Provider
Officially, for ONline access, ONLY the RWDCs need access the KDS Root Key objects to (re)calculate the password of the corresponding gMSA/dMSA when servicing a managed password request from any server that uses the corresponding gMSA/dMSA. Nobody else should have or need access to any KDS Root Key object! But… are you also aware the any online access is NOT audited in any way by default? There is a solution to enable auditing for any access to any KDS Root Key object. This is done by configuring/enabling in ALL AD domains of the AD forest and configuring a SACL on “CN=Master Root Keys”!
STEP1: Configure And Enable Advanced Auditing In EVERY AD Domain In The AD Forest
Make sure to use a GPO that targets all RWDCs of the AD domain
Within the GPO configure: Computer Configuration > Policies > Windows Settings > Security Settgins > Local Policies > Security Options > Audit: Force Audit Policy Subcategory Settings (Windows Vista) To Override Audit Policy Category Settings = ENABLED (figure 5)
Figure 5: Enabling Advanced Auditing
Within the GPO configure: Computer Configuration > Policies > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Audit Policies > DS Access > Audit Directory Service Access = ENABLED for SUCCESS events (figure 6)
Figure 6: Enabling “Audit Directory Service Access” For SUCCESS Events
STEP2: Configure The SACL On The Object “CN=Master Root Keys” In The Configuration NC/Partition
“CN=Group Key Distribution Service,CN=Services,CN=Configuration,DC=<YOUR FOREST ROOT DOMAIN>,DC=<YOUR TLD>”
“CN=Master Root Keys,CN=Group Key Distribution Service,CN=Services,CN=Configuration,DC=<YOUR FOREST ROOT DOMAIN>,DC=<YOUR TLD>”
Right-click on “CN=Master Root Keys,CN=Group Key Distribution Service,CN=Services,CN=Configuration,DC=<YOUR FOREST ROOT DOMAIN>,DC=<YOUR TLD>” > Advanced > Security Descriptor, then check SACL and click OK
You should then see something similar to what you see in the figure 8
Figure 8: Viewing The Configuration Of The SACL On “CN=Master Root Keys” Using LDP
When someone access the attribute “msKds-RootKeyData” of any KDS Root Key object, you should see something similar to figure 9 and figure 10.
Figure 9: A User Account Accessing The Attribute “msKds-RootKeyData” Of A KDS Root Key ObjectFigure 10: A User Account Accessing The Attribute “msKds-RootKeyData” Of A KDS Root Key Object
But… as mentioned earlier, you should also expect RWDCs (figure 11) to access the attribute “msKds-RootKeyData” of a KDS Root Key object to be able to calculate the password of the corresponding gMSA/dMSA as requested.
Figure 11: An RWDC Accessing The Attribute “msKds-RootKeyData” Of A KDS Root Key Object
Cheers,
Jorge
————————————————————————————————————————————————————- This posting is provided “AS IS” with no warranties and confers no rights! Always evaluate/test everything yourself first before using/implementing this in production! This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years! DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/ ————————————————————————————————————————————————————- ########################### IAMTEC | Jorge’s Quest For Knowledge ########################## #################### https://jorgequestforknowledge.wordpress.com/ ###################