You are on site, audit wasn't properly configured and yet you need to understand what has changed. If Active Directory is not your specialty, it's hard to catch what exactly happened. You will probably open a case with GBS but you also know that every second you wait, you risk to lose information. In this session, we will quickly review what the customers could have done proactively, but also what they can do after a modification to track what has changed in the directory. With simple tools and command lines out of the box and a more elaborated PowerShell code, we can easily keep track of every single change in the directory reading metadata and log files. It's maybe not too late to understand what happened!
Of course, when I write metadata I mean Active Directory Replication Metadata. The Metadata series will describe various scenarios where the use of the metadata can help understanding what happened in an Active Directory forest.
Metadata #1 - When did the delegation change? How to track security descriptor modificationsMetadata #2 - The ephemeral admin, or how to track the group membershipMetadata #3 - Spot who is cheating with the password policyMetadata #4 - How to track the password policy changesMetadata #5 - The locked-out built-in administratorMetadata #6 - Track the recovery operationsMetadata #7 - The adminSDHolder strikes again!Metadata #8 - Get-ADHistory or how to list the environment milestones
But before digging into those scenarios, let's go through a quick intro to make sure we're all on the same page.
Why do we care?
We care because metadata gives you a ton of information. When something changed, from where, how many times it changed... And everything without having the audit configured! Well it will not tell you who did a change, but sometimes it will give us just enough information to understand what's going on in the forest.
What is it?
Fundamentally, it is information that the Active Directory replication engine is using to track the changes and help the replication partners to know what to replicate.
Active Directory is a multi master environment. You can basically modify an object on any domain controller and the changes will be propagated everywhere on the forest (off course there are some exceptions but in general that's the drift). What do we replicate? Objects and attributes. The replication is actually attribute based. So if you modify the password of a user on a domain controllers in France and at the same time some provisioning tool is changing the phone number of the same user on a domain controller in Canada both changes are effective and there is no replication conflict.
Double click on the metadata
What if I change the telephone number again from Paris? Well it will be replicated all the way to Canada. To keep track of the changes, each attribute has a set of metadata which helps domain controllers to know what the most recent change is. As long as an attribute needs to be replicated, Active Directory will need replication metadata. The reason why I mentioned this is because some attributes are not being replicated. Either because it is irrelevant to replicate them or because replicating them will cause to much replication traffic on the network. What if an attribute changes every two minutes? The domain controllers will spend their life replicating it and making sure it is the right value everywhere. So it better be for a good reason. It is actually for that reason that the good old attribute lastLogon is not replicated. Every time a user logs on, interactively or on the network it updates the attribute on the domain controllers where the authentication is performed but it does not get replicated (see this article for more details about the lastLogon attribute and its friend the lastLogonTimestamp attribute: “The LastLogonTimeStamp Attribute” – “What it was designed for and how it works"). How do we know which attributes are getting replicated and which are not? It is defined in the schema with the flag FLAG_ATTR_NOT_REPLICATED. So a simple LDAP query will give us the list of all attributes which do not replicate in our forest. The LDAP filter would be (&(objectClass=attributeSchema)(systemFlags:1.2.840.1135220.127.116.113:=1)) and of course scoping the naming context of the schema for example with ADSIEDIT:
Note that the attribute whenChanged is not replicated. Therefore, you cannot fully trust this one if you want to know when was the last time an attribute has been changed for a given object.
So let's focus on the attribute which do replicate. Can I see their metadata? Sure anytime, as long as you have the right to read an object you can read its metadata. They are readable from the attribute msDS-ReplAttributeMetaData. This attribute is a bit special because it is in fact a constructed attribute, meaning that if you want to see the value of this one, you need to explicitly request for it. Example:
-SearchBase "CN=Administrator,CN=Users,DC=contoso,DC=com" `
-Filter * -SearchScope Subtree `
-Properties * | Select-Object msDS-ReplAttributeMetaData
In the query above, I do ask for all the attributes of the object Administrator (properties = *). Yet the value of msDS-ReplAttributeMetaData is empty. Bellow is the same query but this time I explicitly ask for the attribute containing the metadata:
-Properties msDS-ReplAttributeMetaData | Select-Object msDS-ReplAttributeMetaData
This time I do have something because I asked for it (properties = msDS-ReplAttributeMetaData). The value is structured in a very specific way: DS_REPL_ATTR_META_DATA (well to be exact, it is in fact the structure documented here: DS_REPL_ATTR_META_DATA_2). When using the usual graphical tools, you have to play with the filter button:This is what it looks like:
This attribute contains all the metadata for all the replicated attributed set on the object (technically if the attribute has never been set, there is no metadata associated to it yet but sometimes the console you are using to create an object is setting things that you would not suspect). Note that it does not contain the value of the attribute, just the metadata which is the following:
C:\>repadmin /showrepl dc2008r2Default-First-Site-Name\DC2008R2DSA Options: IS_GCSite Options: (none)DSA object GUID: e5622c77-09c3-419e-8db2-c93ae981eedcDSA invocationID: 90d9dcd9-9da9-49ff-8040-896227e1487f
==== INBOUND NEIGHBORS ======================================
DC=contoso,DC=com Default-First-Site-Name\DC2012 via RPC DSA object GUID: 9d26e124-6b7d-491f-a0a1-ac037b5b8447 Last attempt @ 2014-08-04 18:58:09 failed, result 1908 (0x774): Could not find the domain controller for this domain. 1 consecutive failure(s). Last success @ 2014-07-18 12:56:49.
How to read this information?
Depending on what you are trying to achieve by reading the information (simple check or complex report) you might want to use simple out of the box tools or more complicated PowerShell code. As an admin (if you are a developer you can use whatever language you want as long as you use the right classes etc. see MSDN), this is what we have to read this info...
C:\>repadmin /showobjmeta DC2008R2 "CN=Administrator,CN=Users,DC=contoso,DC=com"
37 entries.Loc.USN Originating DSA Org.USN Org.Time/Date Ver Attribute======= =============== ========= ============= === ========= 7697 a6768194-9d5a-43ab-9139-97da4b7fbca1 1410 2000-07-02 19:59:15 1 objectClass 7697 Default-First-Site-Name\DC2008R2 7697 2010-07-10 12:54:43 1 cn 19350 Default-First-Site-Name\DC2012 20559 2014-07-18 12:13:13 2 sn 19344 Default-First-Site-Name\DC2012 20549 2014-07-18 12:10:09 1 l 7697 a6768194-9d5a-43ab-9139-97da4b7fbca1 1410 2000-07-02 19:59:15 1 description 7697 a6768194-9d5a-43ab-9139-97da4b7fbca1 1410 2000-07-02 19:59:15 1 instanceType 7697 a6768194-9d5a-43ab-9139-97da4b7fbca1 1410 2000-07-02 19:59:15 1 whenCreated 7697 a6768194-9d5a-43ab-9139-97da4b7fbca1 1410 2000-07-02 19:59:15 1 displayName 7697 ecc31b35-05d1-406a-941c-581804e9ad3c 18511 2008-07-21 17:15:53 4 nTSecurityDescriptor 19355 Default-First-Site-Name\DC2012 20560 2014-07-18 12:13:32 1 wWWHomePage 7697 a6768194-9d5a-43ab-9139-97da4b7fbca1 1410 2000-07-02 19:59:15 1 name...
-Object "CN=Guest,CN=Users,DC=contoso,DC=com" `
-Server DC2008R2 | Select-Object `
LastOriginatingChangeDirectoryServerInvocationId | Out-GridView
Now that you have the basics, it is time to browse the different scenario listed at the beginning of the post!
Wait a minute... What about the msDS-ReplValueMetaData attribute?
There are actually two attributes which can be used to retrieve the replication metadata. The one we discussed so far, the msDS-ReplAttributeMetaData, stores the replication metadata for the "regular" attributes. But there is another one, the msDS-ReplValueMetaData, which store the metadata for the linked value attributes (information such as group membership, direct reports...). In PowerShell, all of them do not show up by default unless you request for them:
-Object "CN=Administrators,CN=Builtin,DC=contoso,DC=com" `
This one will be seen in details in the post describing how to track group membership. So have a look there :)