Enumeration and exploitation of Windows active Directory

Enumerating and exploiting Active Directory environments is an important aspect for penetration testing of any organization. Despite this, it is poorly understood and usually reserved for advanced ethical hacking training. In this chapter, we will cover the basics of AD and look at ways of enumerating and exploiting these environments. By the end of this chapter, you should understand the different components of AD, how they work and interoperate and a number of different paths of attack.

What is Active Directory?

At its core, Active Directory is a directory of objects which represent computers, users, groups and devices. Each object has data associated with it that is stored according to a schema that defines its attributes. A user for example will have attributes like SAM-Account-Name and DisplayName, Home Directory, Account-Expires, etc.
The directory can be queried and updated through an LDAP (Lightweight Directory Services) interface and so each object has a distinguished name (DN) that is made up of a hierarchy of names such as common names (CN), organizational unit (OU), organization (O), and domain component (DC). So a user in an AD directory may have a DN of:
cn=Rin Asogi,ou=Megabank IT,dc=megabank,dc=com
Each group of objects is organized in a domain. Domains can be grouped together as a tree which in turn can be grouped as a forest. Domains can have different trust levels between each other.
The default authentication protocol for Active Directory is Kerberos which replaced NTLM. This is important from our perspective because a number of vulnerabilities in AD are based on misconfiguration or actual design features of Kerberos.
Before going into detail on Kerberos, we will finish off with other services Active Directory provides. These are:
Certificate Services: This provides a public key infrastructure that can create, validate and revoke public key certificates. The certificates can be used for encrypting files, emails and network traffic.
Federation Services: This service supports single sign-on for web-based services and network resources. Once a user has logged on once, they do not need to log on again when they use a new service as long as it is in within a configurable time period.
Rights Management Services: This service controls access to documents such as emails, Word or Excel documents and web pages. The service will determine what a user can do with a document for example being able to read it but not print, copy, forward, or edit.

Kerberos Authentication

Kerberos consists of a Key Distribution Center which has an Authentication Server and a Ticket Granting Server. The Authentication Server is responsible for mutual authentication of a client and is involved in the first step of the process. The user sends a request to the Authentication Server to get a Ticket Granting Ticket (TGT). The request will contain the user's ID, the ID of the Ticket Granting Server, an IP address and a time to live (TTL). Depending on the configuration, and we will see later why this is important, if pre-authentication is required, the client will take the user's password and use it to encrypt a time stamp. The Authentication Server looks up the users in AD to check if they are valid, gets a saved NTLM hash of the user's password and uses that to decrypt the time stamp that was sent through with the request. If the time stamp is valid (a reason why clocks on the client and server need to be synchronized), the Authentication Server determines the users to be pre-authenticated.
The KDC will send back to the user:
  • a session key that is encrypted with the user's password.
  • a Ticket Granting Ticket which contains the session key and the user's authorization data. The TGT is then encrypted using the user's password.
The user then will decrypt the session key and the TGT and store those for use. Note that if there is no pre-authentication, the client would not be able to proceed at this point if the password they used was incorrect because the decryption would fail.
When the user wants to make use of a service, the client software sends a request for a service ticket to the KDC. The request consists of the session key, an encrypted authenticator message, the TGT obtained previously and the identity of the service. The KDC checks the authenticator message, decrypts the TGT with its own key and creates a new session key for the client to use with the service. One copy of the service session key is encrypted with the user's key, the second is added to the user's authorization data (the Privilege Attribute Certificate PAC) and encrypts that as a ticket using the server's master key. The KDC sends this back to the client. The client decrypts the service session key and stores the ticket it has been sent.
Finally, when the client wants to communicate with the service, It sends the service ticket, with an authenticator signed with the service session key to the service. The service decrypts the ticket, obtains the session key from that and checks the authenticator message. If that passes the service can optionally mutually authenticate itself by taking the time from the user's authenticator message, encrypting it with the session key and sending it back to the user.
Just to summarise, there are three secrets that are used in Kerberos authentication and access to services:
  1. 1.
    The user password hash that is used by the user to authenticate requests to the KDC
  2. 2.
    Service password hash. Kerberos maintains a mapping between the Service Principle Name (SPN) and the service account that runs the service. The password hash that is used by the service is that of the service account.
  3. 3.
    The KDC password hash of the account krbtgt that is used to encrypt the TGT and sign the PAC that is sent to the service.
When we come to compromises of hashes, it is possible to compromise all three under particular circumstances which we will come to as we go through the process of enumerating and attacking AD.

Enumeration of Active Directory

We have already seen an example of enumeration of AD users using rpcclient. The more direct way of enumerating objects in AD is to use the LDAP interface which was designed exactly for this purpose. We can use ldapsearch as a tool to explore ldap and use an Onine LDAP test server. This server requires us to authenticate to read the contents and this process is known as doing a "bind". To authenticate, we specify the bind distinguished name "cn=read-only-admin,dc=example,dc=com" and the password of "password". To list all of the mathematicians in the directory, we can use the following ldapsearch:
┌─[rin@parrot][~/boxes/book]
└──╼ $ ldapsearch -h ldap.forumsys.com -D "cn=read-only-admin,dc=example,dc=com" \
-w password -b "ou=mathematicians,dc=example,dc=com"
# extended LDIF
#
# LDAPv3
# base <ou=mathematicians,dc=example,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# mathematicians, example.com
dn: ou=mathematicians,dc=example,dc=com
uniqueMember: uid=euclid,dc=example,dc=com
uniqueMember: uid=riemann,dc=example,dc=com
uniqueMember: uid=euler,dc=example,dc=com
uniqueMember: uid=gauss,dc=example,dc=com
uniqueMember: uid=test,dc=example,dc=com
ou: mathematicians
cn: Mathematicians
objectClass: groupOfUniqueNames
objectClass: top
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
Here we specified the base DN of "ou=mathematicians,dc=example,dc=com" which is the group of users who are mathematicians. We can search for a specific mathematician jmacy using the query:
┌─[][rin@parrot][~/boxes/book]
└──╼ $ldapsearch -h ldap.forumsys.com -D "cn=read-only-admin,dc=example,dc=com" \
-w password -b "dc=example,dc=com" "(&(objectClass=person)(uid=jmacy))"
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=com> with scope subtree
# filter: (&(objectClass=person)(uid=jmacy))
# requesting: ALL
#
# jmacy, example.com
dn: uid=jmacy,dc=example,dc=com
uid: jmacy
telephoneNumber: 888-111-2222
sn: training
cn: FS Training
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
Although specifying the objectClass in the query is superfluous, it illustrates doing a query with 2 terms that are "anded" together. The symbol '|' represents "or" and "!" is "not". The object that is returned is of multiple classes: inetOrgPerson, organizationalPerson, person and top. Each of these classes has associated attributes that they contribute to the overall object.
If we hadn't know that the base DN was dc=example,dc=com we could have queried this with the query:
┌─[rin@parrot][~/boxes/book]
└──╼ $ldapsearch -h ldap.forumsys.com -D "cn=read-only-admin,dc=example,dc=com" \
-w password -s base namingContexts
# extended LDIF
#
# LDAPv3
# base <> (default) with scope baseObject
# filter: (objectclass=*)
# requesting: namingContexts
#
#
dn:
namingContexts: dc=example,dc=com
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
We will see the use of this in our Hack The Box case study of Forest: