Compromising a Domain With the Help of a Spooler
My job in the Cymulate Research Lab is to craft and implement attack scenarios for Cymulate customers to launch in their environment and increase their cyber-resilience. In this tech-blog post I will show how an attacker can gain access to corporate assets from an initial foothold by combining multiple techniques.
The scenario is performed in two stages. In the first stage we will abuse unconstrained delegation and use techniques to enumerate and escalate domain privileges. In the second stage we will show how it is possible to break the trust between a parent and a child domain to achieve full forest compromise.
The scenario is also implemented in the Cymulate Continuous Security Validation platform, Purple Team module. This allows blue teamers a simple way to launch the scenario in their environments using one tool. Whether using Cymulate or implementing à la carte the goal is to evaluate the enterprise IT system configuration’s resilience to this scenario and take steps to increase it.
Unconstrained Delegation & Printer Bug to Gain Domain Admin
The first stage of the scenario is to abuse the normal use of unconstrained delegation. So before we start, maybe it’s best I explain what unconstrained delegation is and why you may find it enabled in your environment.
Kerberos delegation is a delegation setting that allows applications to request end-user access credentials to access resources on behalf of the originating user. Unconstrained Delegation allows a first hop server (a web server for example) to request access to any service on any computer in the domain.
Microsoft Windows delegation settings
For example, when a user requests access to a web server and unconstrained delegation is enabled on that server, the Domain Controller (DC) authenticates the user and places the user's ticket-granting ticket (TGT), inside the ticket-granting service's (TGS). When presented to the web server the user’s TGT is extracted from the TGS and stored in the Local Security Authority Subsystem Service (LSASS).
This way the server can reuse the user's TGT to access any other resource mimicking the user. TGT’s expire after 10 hours by default.
Unconstrained Delegation Communication Flow:
- A user provides credentials to the Domain Controller.
- The DC returns a TGT.
- The user requests a TGS for the web service.
- The DC provides a TGS.
- The user sends the TGT and TGS to the web server.
- The web server service account uses the user's TGT to request a TGS for the database server from the DC.
- The web server service account connects to the database server as the user.
The scenario starts from an initial foothold attained on a compromised windows machine designated CYM-PT-3. Enumeration shows that the account we are running is that of a low privilege domain user. After domain Enumeration we identify the machine has the msDS-AllowedToDelegateTo attribute set, indicating that Unrestricted Kerberos Delegation is enabled.
With CYM-PT-3 compromised and unconstrained delegation enabled we can escalate privileges if a high privilege account has connected to it in the past 10 hours (per the default setting). For this scenario we will assume that a high privilege account has not connected to this machine, the next step will solve that deficiency.
The Printer Bug
Microsoft Print System Remote Protocol (MS-RPRN) allows a domain user to force any machine running the Spooler service to connect to a second machine with unconstrained delegation enabled. The RpcRemoteFindFirstPrinterChangeNotificationEx API allows print clients to subscribe to notifications of changes on the print server. By default, the spool service is enabled on Domain Controllers.
A call to this API will cause the print server on the DC to authenticate to CYM-PT-3 by providing its TGT and storing it in the Local Security Authority Subsystem Service (LSASS).
Forcing Authentication using SpoolSample:
We will use Spoolsample to perform the attack. Spoolsample is a tool that forces Windows hosts to authenticate to other machines via the MS-RPRN RPC interface.
In this scenario we will force the DC machine account, cymsrv2016$ to authenticate to our CYM-PT-3 by providing its TGT.
We now have a high privilege account(the Domain Controller Machine account) TGT on the compromised machine that has unconstrained delegation enabled.
Using Mimikatz to Extract the TGT
To extract the TGT of the domain controller on CYM-PT-3 we will use mimikatz. The following command will export all the available kerberos tickets into the folder from which mimikatz was started. From there we will extract the TGT of the Domain Controller machine account.
Pass the Ticket
Pass-the-ticket (MITRE ATT&CK T1550.003) allows us to request a TGS by using a TGT we have and gain access to network resources by impersonating the original owner of the TGT. We will use the TGT obtained from the Domain Controller machine account in the previous step to access the DC resources. Before doing so we will confirm that the low privilege account on CYM-PT-3 does not have access to resources on the DC cymsrv2016.
To pass-the-ticket we will use mimikatz to inject the DC’s TGT into a current session.
As shown below we now have access to resources on cymsrv2016.
DCSync to Domain Compromise (MITRE T1003.006)
In the first stage we escalated privileges from a compromised, low privileged account on a machine with Unconstrained Delegation to domain admin rights. In this second stage we will show how by breaking the trust between a parent and a child domain we will achieve full forest compromise.
First, we will obtain the KRBTGT hash of the domain controller. The KRBTGT account is responsible for encrypting and signing all the Kerberos tickets in the domain, if compromised, it can be used to perform many different types of attacks. For example, to achieve persistence by generating a golden ticket.
We will use DCSync attacks to obtain the KRBTGT hash. This attack allows a threat actor to impersonate a Domain Controller and request password hashes from other Domain Controllers, ATT&CK technique T1003.006.
- Find the Domain Controller to request replication from
- Request replication with GetNCChanges
- The Domain Controller return the replication data
To perform this type of attack the following privileged rights are required. Domain Admins, Enterprise Admins have these rights by default.
- Replicating Directory Changes
- Replicating Directory Changes All
- Replicating Directory Changes in Filtered Set
Since we imported the machineaccount ticket of the Domain Controller (cymsrv2016) to our current session, we know that this user has the necessary privileges listed above to allow us to perform this attack. Using Mimikatz to mimic the Domain Controller and request user replication from the Domain Controller we retrieve the KRBTGT hash.
We now have extracted the KRBTGT hash and can use it to create a golden ticket but since we already have Domain Admin Privileges this is not necessary. We will save the KRBTGT hash for later use. The next step is to achieve Enterprise Admin (forest) privileges.
Enumeration shows a bidirectional trust with the cymulate.lab domain. There are a variety of attacks that can be attempted across forest trusts such as Kerberoasting, SID History abuse, and more. To enumerate our available trusts, we’ve used powerview. Powerview is a PowerShell tool used to gain network situational awareness on Windows domains. (MITRE ATT&CK T1482 Domain Trust Discovery)
The enumeration shows that we are a child domain and we have a bi-directional trust with our parent domain cymulate.lab.
Compromising Parent Domain using the SID History method
As a child domain with bi-directional trust with our parent domain cymulate.lab we can try to compromise the parent domain by abusing the SID History method. ATT&CK T1134.005 Access Token Manipulation: SID-History Injection.
Many posts have been done on the topic such as this one so we will skip straight to the requirements and the attack.
In order to perform the SID History method and gain Enterprise Admin level access we need the following:
- The KRBTGT hash that we already extracted from our current domain.
- The SID (security identifier) of our current domain
- The SID of our parent domain
Extracting Domain SID and Parent SID using PowerView
Once we have all of the above, we can use mimikatz to inject a golden ticket with the krbtgt hash from our child domain: child.cymulate.lab and add the “enterprise admin” SID for cymulate.lab then once again pass the ticket and achieve Enterprise Admin level of access.
Replicating the Entire Scenario Using Cymulate's Purple Team Module
As mentioned in the beginning, both stages of the scenario described in this paper are implemented in the Cymulate Purple Team module. This automated instantiation enables repetitive execution of the scenario. For example, to launch the scenario from different start points in the enterprise infrastructure, or to validate proper remediation or detection after taking countermeasures.
As a Cymulate researcher the transition from concept to implementation is very fluid. The result of a flexible and open framework that is easy to use. We use the same framework as our customers who in preparing custom scenarios from A to Z so that they can be used by red and blue teamers out of the box, repeatedly, managed and integrated with the current security stack. Following is a description of the implementation.
Cymulate Purple Team Module
The Cymulate Purple Team module is an open framework used to craft and automate custom attack scenarios. The creation of scenarios requires minimal adversarial skills, while launching the scenarios and analyzing the results is achievable by security team members of any skill level.
The module makes it possible to perform different penetration testing tasks on a daily basis. The advanced use of the Purple Team module is for red/blue teamers to exercise a full attack on the enterprise environment by combining real world adversary techniques. For blue teamers it gives better visibility of what aspects of your current detection and response need to be improved, and it provides a better understanding about some of the more sophisticated attacks used by red teamers with a few clicks, minimal effort and skill set.
The Module supports the following:
Chained – different executions can be chained together to mimic the path used by a real adversary. An example would be running mimikatz to collect credentials from a machine, using the collected credentials to move laterally and escalate privileges to Domain Admin.
Atomic – testing a specific scenario Atomic Executions are standalone executions.
We can use atomic executions if we want to test different scenarios. For example, Enumerating all members of the domain admins group in a domain environment.
For the scenario described above we will use the Chained approach. We begin by creating a template and adding the executions to the template.
After adding the executions, we can chain other executions together. Below is an example of chaining the Ticket Extraction using Packed Mimikatz execution to Pass the Ticket and DCSync Execution. By chaining the Kerberos_ticket input argument the Purple Module knows it need to get its information regarding the ticket location from its chained execution, which is Ticket Extraction using Packed Mimikatz, as depicted below.
To implement the scenario described in this paper we chained all the relevant executions into a template, from which assessments can be created, launched and validated.
The result of running the assessment is a full replication of the scenario, resulting in full forest compromise.
Following are some mitigation tips to this attack scenario.
- Mimikatz was executed on disk. Build a signature based on the command line arguments provided. Keep in mind this is not a golden solution and can be manipulated by an attacker to evade detection. (eg, using software packing to avoid detection as used in our example)
- Configuration management, perform an Active Directory security assessment to audit user rights, identify hosts other than Domain Controllers with unconstrained delegation and remediate the “printer bug” CVE-2019-0683.
- Fine-tune logging and monitoring to alert on forged Kerberos tickets the other techniques highlighted in this post.
- Regularly change the KRBTGT password. This needs to be changed once to allow the AD replicate, and change again 24 hours later to update the KRBTGT password to make sure there are no issues validating existing Kerberos tickets.
- Avoid using Unconstrained Delegation when it is not absolutely necessary. Constrained delegation instead of Unconstrained is an option on machines that require it. By using constrained delegation, you can specify the exact servers that the server with delegation can access. Constrained delegation is not a silver bullet and can be as dangerous as unconstrained but it is safer option overall.
- Enabling SID Filtering between trusts in an Active Directory forest could potentially solve the issue. This disables SID History but introduces complexities in the production environment.
- Enable Application White-Listing Solution to Limit the user ability to execute arbitrary code.
- Prevent usage of SpoolSample and similar applications (application hash and/or detection on 5145 event ID+unrecognized client).
- Disable the Print Spooler service on machines that do not use a printing server.
*Stay tuned for our next research blog where we describe how to own an endpoint that has unconditional delegation enabled
Test the effectiveness of your security controls against possible cyber threats with a 14-day trial of Cymulate's platform.
Don’t speculate, Cymulate
- @tifkin_ (Lee Christensen), @harmj0y(Will Schroeder), @enigma0x3(Matt Nelson)
- https://msdn.microsoft.com/en-us/library/cc244528.aspx - MS-RPRN - Print System Remote Protocol