ShadowGate
Challenge Lab (Easy) - by Ross
The following post by 0xb0b is licensed under CC BY 4.0
Scenario
Objective
ShadowGate recently completed a corporate acquisition that significantly expanded its internal network, user base, and application footprint. Several business-critical systems were migrated and consolidated under tight operational deadlines to minimize downtime and maintain service continuity.
While functional validation was completed, the organization deferred a comprehensive security assessment due to delivery pressure and staffing constraints. Leadership has since requested an independent penetration test to validate the security posture of the newly created environment and identify any material risk before the next audit cycle.
The assessment will evaluate whether a motivated attacker with standard network access could compromise sensitive systems, escalate privileges, or move laterally within the enterprise environment.
The Hack Smarter team has been authorized to perform a black box internal penetration test against the ShadowGate environment.
Initial Access
The client has provided you with VPN access to their internal network, but no credentials.
Summary
Summary
In ShadowGate, we begin without credentials against a Windows Domain Controller DC01.shadow.gate. Initial enumeration via NetExec reveals anonymous SMB authentication is permitted, allowing us to extract the domain user list and feed it into GetNPUsers.py for an AS-REP Roasting attack. The blob returned for jtrueblood is cracked with Hashcat mode 18200, granting our first set of valid credentials and SMB access to the domain.
BloodHound enumeration exposes jtrueblood's GenericWrite over bbrown, a member of the ADCS-READERS group, which we abuse through a Targeted Kerberoasting attack to register an SPN, request a TGS, and crack bbrown's password offline with Hashcat mode 13100. With bbrown, a second Certipy enumeration reveals an ESC8 misconfiguration where the AD CS Web Enrollment endpoint accepts NTLM authentication without channel binding, alongside a DomainController template suitable for machine enrollment. We launch a Certipy relay against http://DC01.shadow.gate and coerce the DC into authenticating to our host using PetitPotam's MS-EFSRPC abuse, capturing the relayed session and issuing a certificate as DC01$.
Authenticating with the resulting dc01.pfx through Certipy yields a TGT and the NTLM hash of the DC01 machine account, which we leverage through secretsdump.py to perform a DCSync and retrieve the krbtgt hash.
Recon
We use rustscan -b 500 -a 10.1.99.8 --top -- -sC -sV -Pn to enumerate all TCP ports on the target machine, piping the discovered results into Nmap which runs default NSE scripts -sC, service and version detection -sV, and treats the host as online without ICMP echo -Pn.
A batch size of 500 trades speed for stability, the default 1500 balances both, while much larger sizes increase throughput but risk missed responses and instability.
The target 10.1.99.8 is a Domain Controller DC01.shadow.gate. DNS is exposed on port 53 and Kerberos on port 88, alongside Kerberos password change on port 464. LDAP and LDAPS services are available on ports 389 and 636. SMB is exposed via ports 139 and 445 with message signing enabled but not required. Remote management and access are available through RDP on port 3389 and WinRM on port 5985. The host also exposes a .NET Message Framing service on port 9389, RPC over HTTP on ports 593 and 53559, and several MSRPC endpoints on ports 135, 49664, 49667, 49669, 53562, 53570, 53585, 53600, and 53613.

We begin by enumerating the domain controller's SMB service via Netexec.
We'll follow the orange-cyberdefense mindmap.

We test for an anonymous authentication and are able to authenticate.

From there we generate a /etc/hosts file entry...

... and add the following line to our /etc/hosts file.
Access as jtrueblood
Using anonymous access, we first attempt to enumerate users in the domain using NetExec.


With those users we can try to ASREProast them.
With ASREProasting accounts with Kerberos pre-authentication disabled are exploited by requesting a TGT for them, since the KDC will return an AS-REP containing a session key encrypted with the user's password-derived hash. We can then crack that hash offline to recover the plaintext password, though the TGT itself remains unusable without it.

We use impackets GetNPUsers.py for AS-REP Roasting and are able to extract the blob from jtrueblood.

Next, we try to crack the blob and are successful.

With the credentials recovered we are able to authenticate as jtrueblood against SMB using NetExec.

BloodHound Enumeration
With that user credentials gathered we are now able to enumerate the domain using BloodHound.

If we look at the outbound controls of our recently compromised account jtrueblood we see that the user has GenericWrite permissions over the user bbrown. Potentially allowing us to perform a targetedKerberoast attack or a shadow auto credentials attack on the users account for an account takeover.

Furthermore, we see that bbrown is member of the ADCS-READERS group. This is interesting, maybe there are some misconfigured certificates to abuse.

Certipy Enumeration I
We try to enumerate misconfigured certificates using certipy but do not find any.


Access as bbrown
We move on and try to get access as bbrown. Since that user is member of the ADCS-READERS we might get more insight regarding ADCS configurations.
TargetedKerberoast
We'll start with the TargetedKerberoast. See below links for further reading:
This abuse can be carried out when controlling an object that has a
GenericAll,GenericWrite,WritePropertyorValidated-SPNover the target. A member of the Account Operator group usually has those permissions.The attacker can add an SPN (
ServicePrincipalName) to that account. Once the account has an SPN, it becomes vulnerable to Kerberoasting. This technique is called Targeted Kerberoasting.
To perform the TargetedKerberoast we will use the following tool:
We run the following command and are able to get the Kerberos 5, etype 23, TGS-REP blob of the jtrueblood user.

We use hashcat again to crack the blob and are able to retrieve the password of bbrown.

Shadow Credentials Attack
The following Section descirbes the Shadow Credentials Attack and can be skipped.
Further information on the Shadow Credentials Attack can be found under the following link:
The Kerberos authentication protocol works with tickets in order to grant access. An ST (Service Ticket) can be obtained by presenting a TGT (Ticket Granting Ticket). That prior TGT can only be obtained by validating a first step named "pre-authentication" (except if that requirement is explicitly removed for some accounts, making them vulnerable to ASREProast). The pre-authentication can be validated symmetrically (with a DES, RC4, AES128 or AES256 key) or asymmetrically (with certificates). The asymmetrical way of pre-authenticating is called PKINIT.
The client has a public-private key pair, and encrypts the pre-authentication data with their private key, and the KDC decrypts it with the client’s public key. The KDC also has a public-private key pair, allowing for the exchange of a session key.
Active Directory user and computer objects have an attribute called
msDS-KeyCredentialLinkwhere raw public keys can be set. When trying to pre-authenticate with PKINIT, the KDC will check that the authenticating user has knowledge of the matching private key, and a TGT will be sent if there is a match.There are multiple scenarios where an attacker can have control over an account that has the ability to edit the
msDS-KeyCredentialLink(a.k.a. "kcl") attribute of other objects (e.g. member of a special group, has powerful ACEs, etc.). This allows attackers to create a key pair, append to raw public key in the attribute, and obtain persistent and stealthy access to the target object (can be a user or a computer).
To perform the Shadow Credentials Attack we are using Certipy.
In short: If we can write to the msDS-KeyCredentialLink property of a user, we can retrieve the NT hash of that user.
With the following command we issue the attack and are succesful. We retrieve the NT hash of bbrown.

We test the credentials using NetExec. We successfully authenticated.

Certipy Enumeration II
We spin up certipy again, this time with bbrown. We can use either the retrieved password or the hash.
Alternative using the NTLM hash:

We see ESC8 is there. ESC8 is an AD CS misconfiguration / attack where an HTTP-based certificate enrollment endpoint accepts NTLM authentication without enforcing channel binding or HTTPS-only, allowing to relay coerced NTLM authentication from a victim like a domain controller to that endpoint. The relayed session is used to enroll a certificate on the victim's behalf, which then can be use to authenticate via PKINIT. It's not a misconfigured template.
A more detailed explanation can be found here:

We are looking for a template that allows machine/DC enrollment. We use certipy again but this time we query for all templates.
Alternative using the NTLM hash:

The DomainController template is fitting.

Access as dc01$
First, we start a relay using certipy to capture NTLM authentication and relay to the AD CS Web Enrollment endpoint, requesting a certificate using the DomainController template. If successful, it issues a certificate for the relayed identity, enabling authentication to the Active Directory services.

Next, we use PetitPotam to coerce DC01 into authenticating to the attacker-controlled host 10.200.52.92 by abusing MS-EFSRPC calls. The provided credentials of bbrown are used to trigger the authentication attempt, which can then be captured and relayed. We use our machine IP 10.200.52.92 since we run the relay.
Alternative using the NTLM hash

After a while, we receive a certificate file.

Next we authenticate via certipy using the dc01.pfx certificate obtained giving us a ccache file and the NTLM hash of the DC01$ machine.

Since we now have access as the DC01 we are able to perform a DCSync.
DCSync is a technique that uses Windows Domain Controller's API to simulate the replication process from a remote domain controller allowing to request password data from a domain controller as if they were another DC. We can do it either using the gathered hash or the ccache file via impackets secretsdump.py.
We retrieve the NTLM hash of the krbtgt account.

Last updated