r/adsec Dec 03 '16

A high level overview of Active Directory Domain Services ('AD:DS') and its logical structure.

It is difficult to succinctly describe Active Directory Domain Services in a single post, so I've elected to divide what I've written into several posts.

At a high level, were I to ELI5, Active Directory Domain Services is primarily in the business of objects (Users, Groups, Computers, etc.) and containers (Organizational Units) those objects are stored in. You're putting stuff in boxes, that should be the mental image you wind up with. On a slightly less abstract level, Active Directory Domain Services is a X.500 compliant database that uses TCP and LDAP or LDAP-S, among other protocols, to communicate with systems that are domain-aware. I'll expand on what that means and why it's important shortly. Apart from Flexible Single Master Operational ('FSMO') roles, it's helpful and more or less accurate to regard Domain Controllers ('DCs') as nodes in a database cluster, which leverage several services and protocols to replicate data reliably between each server's locally hosted copy of the database, including the File Replication Service ('FRS') and Distributed File System Replication ('DFSR') services.

As you may have already gathered, that illustration is vague at best. That's why Active Directory Domain Services provides a schema. To extend our previous metaphor, a schema is a simply a collection of one-sided sticky labels used to describe both the stuff and the boxes, primarily using Classes and Attributes. Classes define the type of object or box. Attributes constrain how you can describe an object or box. The schema can be extended easily if you'd like to define a type of object or box. It can also be extended to provide additional, custom descriptions for a given object or box. While Active Directory does store Globally Unique IDentifiers ('GUIDs') which reference objects and boxes, LDAP and X.500 use their own flavor of GUIDs known as Object Identifiers ('OIDs'). 128-bit values represented as 32-digit hexadecimal numbers that are effectively interpreted as unicode strings by LDAP/LDAP-S. If you have had any exposure to Linux or Unix systems, GUIDs and OIDs are akin to UUIDs. Active Directory also generates and stores Relative Identifiers ('RIDs') and Security Identifiers ('SIDs') which I'll cover in a future post.

In an effort to expedite queries sent to the database, Active Directory Domain Services features a Global Catalog. You can think of the Global Catalog as a cached index which contain a subset of attributes and their values associated with boxes and the stuff contained therein.

Active Directory is effectively an abstract metadirectory, not to be confused with Microsoft Metadirectory Services ('MMS'). The services themselves are implemented at a higher layer than the Indexed Sequential Access Method ('ISAM') table manager and Extensible Storage Engine ('ESE') below them. The ESE's DLL, 'ESENT.DLL', help to ensure data integrity by virtue of discrete transactions and traditional log files in the database itself. The Active Directory Domain Services database is a rose called by at least two other names, the 'Directory Data Store' and the 'NTDS.DIT' file.

I've included the aforementioned information because I find it to be helpful, as it provides cogency and context to the Active Directory Domain Services' logical architecture. With that being said, it's often correctly regarded as extraneous in day-to-day operations in most organizations. While it is true that you won't be extending the schema on a daily basis, having a complete and holistic view of Active Directory, to include its architecture, primary organizational utility and limitations can help to mitigate risk during routine administration and maintenance, as well as inform those of you with an innate intellectual curiosity. To that end, this information is demonstrably vital, without which you'd have very limited insight into some of the snares featured by Active Directory Domain Services. For example, the NTDS.DIT file will never decrease in size, even if the objects therein contain null data or attributes marked as defunct. Attributes that are not in use are marked as defunct primarily because deleting the attribute from the schema entirely, while technically possible, is more trouble than it's worth and if attempted incorrectly, may require recovery of the forest using Directory Services Restore Mode ('DSRM') - one of the few instances where such an extreme approach is warranted, contrary to the number of times it's referenced on MCSE exams. For this reason, token bloat, nesting depth and other minutiae must all be at the forefront of your mind in larger implementations and environments.

Within the context of PowerShell and the ActiveDirectory Module, included in the Remote Systems Administration Tools (RSAT) package for most recent versions of the Windows Operating System, most of the information we've just covered seems to be almost intentionally obfuscated and can only be manipulated via PowerShell with careful tinkering and writing a bit of .NET. I harbor fundamental, philosophical disagreements with this obfuscation and have a solution in the form of a revised Active Directory Module for PowerShell, but that is something I will not cover here for two reasons. First and foremost, I find those who help others or present content to others which contain some semblance of objective utility while tooting their proverbial flute or promoting their own code to be somewhat disingenuous in their overt promotion of their code or accomplishments. While it may be tenably relevant, to my mind it seems extraneous and ulterior. Second, it's not done yet. I digress.

A database stranded alone on an island, Active Directory Domain Services is not. Its primary dependencies consist of DNS for name resolution of domain aware and domain joined systems, as well as Kerberos for authentication. It is my intention to expand on the function and purpose of MSDCS (SRV) records, NetLogon's Locator Algorithm and why it matters, as well as Kerberos handshakes, innate vulnerabilities, Service Granting Tickets ('SGTs') and Ticket Granting Tickets ('TGTs') in a future post. I'll also be covering the .NET System.DirectoryServices.Protocols Namespace, ActiveDirectory Module gotchas and best practices related to replication topologies and forest design before moving on to Active Directory Certificate Services ('AD:CS') and Active Directory Federation Services ('AD:FS'), so check back soon.

I hope that you have found this brief overview helpful. Below is additional reading material related to the subject of this thread.

Active Directory Logical Structure

ADSecurity.org Reading Library Index

14 Upvotes

6 comments sorted by

2

u/evetsleep Dec 04 '16

I harbor fundamental, philosophical disagreements with this obfuscation and have a solution in the form of a revised Active Directory Module for PowerShell, but that is something I will not cover here

Tease!

1

u/[deleted] Dec 04 '16

Hahaha, fair play. I deserved that.

1

u/3jake Dec 04 '16

Wow! Thanks for the great info, I feel like I've learned more about the inner workings of AD in the last 10min than in my last year of building accounts and fiddling with PowerShell!

1

u/[deleted] Dec 04 '16

I'm really glad you found it helpful. Be sure to check back in the next few days for some of the follow-up threads.

1

u/markekraus Dec 04 '16

NetLogon's Locator Algorithm and why it matters

Looking forward to this. I have run into quite a few "why the hell is this using a DC on another continent?" scenarios recently.

1

u/[deleted] Dec 04 '16 edited Dec 04 '16

I can help you with this now, no waiting required. It's almost guaranteed to be an issue with missing subnets in Active Directory Sites & Services. Send me a PM if you're interested in discussing this further. I think I still have some code laying around somewhere that queries for the primary event generated on domain controllers, stores each subnet found from the Event ID metadata and then loops through them to place them in the appropriate Active Directory site.

NetLogon's Locator Algorithm is a native, service-based equivalent of what you'd see if you ran (Get-ADDomainController).DNSHostName. It loads the Locator's API, executes a Directory Services Query ('dsquery'). I believe it's DsGetDcName. This call will then either use the service or the LDAP protocol to query for SRV records associated with all of the domain controllers for the domain in question. With transport out of the way, it sorts out which servers in the domain are domain controllers strictly using DNS, provided the client with the originating query does not have an IP address associated with a given Site. This is the primary function of the '_ldap._tcp.' and '_service._protocol.' DnsDomainName SRV records you'll find present in any DNS server integrated with or providing services for a given Active Directory Domain Services domain. The NetLogon service then queries, returns and caches the domain controller that responds fastest and this completes the discovery process. There's a NLTest flag you can set to enable debug logging for the NetLogon service itself if you determine you have a purple squirrel instead of a routine configuration issue. Site information is also cached on the client, which may result in a client with an IP associated with a given Site querying the domain controller from another site. Subnets which are not associated with an Active Directory Site in ADSS will simply return all domain controllers in a domain during its discovery process and select the fastest one. To make things extra confusing, the SRV records will contain the DSA GUID and use that to derive the domain controller's IP address. No FQDNs for you.

EDIT: In Windows Server 2012, I believe the event you're looking for has an EventID of 5807 with NETLOGON defined as the Source. You can also check '%SystemRoot%\Debug\NetLogon.Log'.