Saltar al contenido

Auditar las plantillas de certificado de AD CS (ESC1-ESC4)

Audite cada plantilla de certificado de AD CS frente a ESC1-ESC4: marcas de sujeto, EKU, derechos de inscripción y ACL, con PowerShell y un orden de corrección seguro.

Florian Amette8 min de lectura

La mayoría de los compromisos de AD CS no necesitan un fallo de software. Necesitan una plantilla de certificado que permita a un usuario con pocos privilegios escribir el sujeto de su propio certificado, o una ACL de plantilla que permita a ese usuario reescribir la plantilla hasta que lo permita. Las clases ESC1 a ESC4 son todas problemas a nivel de plantilla, lo que las hace auditables solo desde LDAP: cada configuración relevante es un atributo de un objeto pKICertificateTemplate en la partición de configuración, y cada derecho de inscripción es una ACE en ese mismo objeto.

El pilar de hardening de AD CS explica conceptualmente cada clase ESC. Esta guía es el procedimiento de auditoría que hay detrás: crear un inventario de las plantillas publicadas, puntuar cada una en las cuatro dimensiones de riesgo (control del sujeto, EKU de autenticación, quién puede inscribirse, quién puede escribir), corregirlas en un orden seguro y verificar el resultado. Las configuraciones de toda la CA, como EDITF_ATTRIBUTESUBJECTALTNAME2, y la inscripción web se tratan por separado en proteger la inscripción web de AD CS.

Medir: inventariar las plantillas y dónde están publicadas

Una plantilla solo importa para la inscripción cuando una CA la publica, así que el primer paso es separar las plantillas publicadas de la treintena de plantillas predeterminadas que permanecen sin usar en el directorio. Los nombres de las plantillas publicadas se almacenan en el atributo certificateTemplates del objeto pKIEnrollmentService de cada CA.

PowerShell
$configNC = (Get-ADRootDSE).configurationNamingContext
$pks      = "CN=Public Key Services,CN=Services,$configNC"
$tplBase  = "CN=Certificate Templates,$pks"
$caBase   = "CN=Enrollment Services,$pks"

# Qué CA publica qué plantilla
Get-ADObject -SearchBase $caBase -LDAPFilter '(objectClass=pKIEnrollmentService)' `
    -Properties dNSHostName, certificateTemplates |
    ForEach-Object {
        foreach ($t in $_.certificateTemplates) {
            [pscustomobject]@{ CA = $_.Name; Host = $_.dNSHostName; Template = $t }
        }
    } | Sort-Object Template | Format-Table -AutoSize

Conserve esta salida. También es su lista de CA empresariales, que deben figurar en su inventario de Tier 0 junto a los controladores de dominio.

Auditar: puntuar cada plantilla por sujeto, EKU y aprobación

Cuatro atributos deciden si una plantilla puede usarse para suplantar identidades:

AtributoQué buscar
msPKI-Certificate-Name-Flag0x1 (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT): el solicitante escribe el sujeto y el SAN
pKIExtendedKeyUsage / msPKI-Certificate-Application-PolicyClient Authentication (1.3.6.1.5.5.7.3.2), Smart Card Logon (1.3.6.1.4.1.311.20.2.2), PKINIT Client Authentication (1.3.6.1.5.2.3.4), Any Purpose (2.5.29.37.0) o ningún EKU
msPKI-Enrollment-Flag0x2 (CT_FLAG_PEND_ALL_REQUESTS): se requiere aprobación del administrador de certificados de la CA
msPKI-RA-SignatureNúmero de firmas autorizadas (firma conjunta de un agente de inscripción) requeridas

El script siguiente las combina con los datos de publicación. Una plantilla sin EKU se trata como apta para autenticación, porque un certificado sin restricciones de EKU es válido para cualquier propósito (el caso ESC2).

PowerShell
$published = Get-ADObject -SearchBase $caBase -LDAPFilter '(objectClass=pKIEnrollmentService)' `
    -Properties certificateTemplates | ForEach-Object { $_.certificateTemplates } | Sort-Object -Unique

$authEku  = '1.3.6.1.5.5.7.3.2','1.3.6.1.4.1.311.20.2.2','1.3.6.1.5.2.3.4','2.5.29.37.0'
$agentEku = '1.3.6.1.4.1.311.20.2.1'   # Certificate Request Agent (ESC3)

Get-ADObject -SearchBase $tplBase -LDAPFilter '(objectClass=pKICertificateTemplate)' -Properties `
    'msPKI-Certificate-Name-Flag','msPKI-Enrollment-Flag','msPKI-RA-Signature',
    'pKIExtendedKeyUsage','msPKI-Certificate-Application-Policy','msPKI-Template-Schema-Version' |
ForEach-Object {
    $eku = @($_.pKIExtendedKeyUsage) + @($_.'msPKI-Certificate-Application-Policy') |
        Where-Object { $_ } | Sort-Object -Unique
    [pscustomobject]@{
        Template        = $_.Name
        Published       = $published -contains $_.Name
        Schema          = $_.'msPKI-Template-Schema-Version'
        SuppliesSubject = [bool]($_.'msPKI-Certificate-Name-Flag' -band 0x1)
        AuthCapable     = ($eku.Count -eq 0) -or [bool]($eku | Where-Object { $_ -in $authEku })
        RequestAgent    = [bool]($eku -contains $agentEku)
        ManagerApproval = [bool]($_.'msPKI-Enrollment-Flag' -band 0x2)
        RASignatures    = [int]$_.'msPKI-RA-Signature'
        EKUs            = $eku -join ', '
    }
} | Where-Object Published | Sort-Object SuppliesSubject, AuthCapable -Descending | Format-Table -AutoSize

Interprete la salida así. SuppliesSubject y AuthCapable ambos a true, sin aprobación ni firmas RA, es un candidato de manual a ESC1: que sea explotable depende únicamente de quién puede inscribirse. RequestAgent a true es un candidato a ESC3. Una columna EKUs vacía en una plantilla publicada es ESC2.

Dos casos especiales merecen una nota. En primer lugar, las plantillas con versión de esquema 1 (como la plantilla integrada WebServer) que permiten un sujeto proporcionado fueron la base de ESC15 (CVE-2024-49019), en la que podían inyectarse directivas de aplicación en la solicitud; la actualización de seguridad de noviembre de 2024 lo corrigió en la CA, así que confirme que sus CA están parcheadas y duplique las plantillas v1 en versiones v2 o superiores que usted controle. En segundo lugar, las plantillas cuya directiva de emisión está vinculada a un grupo de AD mediante msDS-OIDToGroupLink (ESC13) conceden la pertenencia a ese grupo a quien posea el certificado, así que revise los objetos OID de directivas de emisión que tengan ese atributo.

Auditar: derechos de inscripción y ACL de las plantillas

La inscripción es un derecho extendido sobre el objeto de plantilla: Certificate-Enrollment (0e10c968-78fb-11d2-90d4-00c04f79dc55) y Certificate-AutoEnrollment (a05b8cc2-17bc-4802-a710-e7c15ab866a2). GenericAll también concede la inscripción. Los derechos de escritura (WriteProperty, WriteDacl, WriteOwner, GenericWrite, GenericAll) sobre la plantilla son ESC4: quien los tenga puede activar la marca de sujeto.

PowerShell
$rightNames = @{
    '0e10c968-78fb-11d2-90d4-00c04f79dc55' = 'Enroll'
    'a05b8cc2-17bc-4802-a710-e7c15ab866a2' = 'AutoEnroll'
    '00000000-0000-0000-0000-000000000000' = 'AllExtendedRights'
}
$broad    = '(^|\\)(Everyone|Authenticated Users|Domain Users|Domain Computers|Users)$'
$expected = '(^|\\)(Domain Admins|Enterprise Admins|SYSTEM)$'

Get-ADObject -SearchBase $tplBase -LDAPFilter '(objectClass=pKICertificateTemplate)' |
ForEach-Object {
    $tpl = $_
    (Get-Acl -Path "AD:\$($tpl.DistinguishedName)").Access |
        Where-Object { $_.AccessControlType -eq 'Allow' -and $_.IdentityReference.Value -notmatch $expected } |
        ForEach-Object {
            $r = $_.ActiveDirectoryRights.ToString()
            $kind = if ($r -match 'GenericAll|GenericWrite|WriteDacl|WriteOwner|WriteProperty') { 'WRITE (ESC4)' }
                    elseif ($r -match 'ExtendedRight') { $rightNames[$_.ObjectType.ToString()] }
            if ($kind) {
                [pscustomobject]@{
                    Template  = $tpl.Name
                    Published = $published -contains $tpl.Name
                    Trustee   = $_.IdentityReference.Value
                    Right     = $kind
                    Broad     = $_.IdentityReference.Value -match $broad
                }
            }
        }
} | Sort-Object Published, Right -Descending | Format-Table -AutoSize

Combine ambas salidas. La lista prioritaria la forman las plantillas publicadas aptas para autenticación que permiten proporcionar el sujeto o emiten certificados de agente de solicitud, cuando Broad es true en un derecho Enroll. Justo detrás va cualquier fila WRITE (ESC4) de un titular no administrador, esté publicada o no, ya que el acceso de escritura a una plantilla es un ESC1 latente a la espera de que alguien lo use. No olvide los propios contenedores: el acceso de escritura sobre CN=Certificate Templates, CN=Enrollment Services o el objeto NTAuthCertificates es ESC5 y entra en la misma revisión, como se describe en auditar las ACL de AD.

Contrastar con Locksmith y PSPKIAudit

Merece la pena ejecutar dos herramientas de PowerShell orientadas a la defensa junto a sus propios scripts. Locksmith (Invoke-Locksmith) informa de ESC1-ESC8 y de varias clases posteriores en su modo predeterminado y puede generar scripts de corrección; revise sus modos antes de ejecutar cualquiera que corrija. PSPKIAudit se basa en el módulo PSPKI y añade el análisis de certificados emitidos. Herramientas ofensivas como Certify y Certipy enumeran los mismos datos; si su red team las usa, compare sus hallazgos con su inventario en lugar de considerar a cualquiera de ellos como fuente definitiva. Para la vista de grafo de quién puede alcanzar un derecho de inscripción mediante grupos anidados, consulte gestión de rutas de ataque con BloodHound.

Aplicar: corregir en el orden menos disruptivo

Trabaje los hallazgos en este orden, que elimina el máximo riesgo por cambio y rompe el mínimo de flujos de trabajo.

  1. Despublicar las plantillas que nadie usa. Compruebe primero en la base de datos de la CA las emisiones recientes por plantilla (consulte Verificar más abajo). Despublicar es inmediato y reversible:
PowerShell
# En la CA (módulo ADCSAdministration)
Get-CATemplate | Sort-Object Name
Remove-CATemplate -Name 'LegacyVPNUser' -Force
  1. Eliminar los derechos de inscripción amplios. Sustituya Domain Users o Authenticated Users en las plantillas sensibles por un grupo dedicado que contenga solo las cuentas o equipos que necesitan el certificado. Mantenga Read para Authenticated Users para que la inscripción automática pueda seguir descubriendo plantillas.
  2. Eliminar la marca de sujeto proporcionado. En la consola Plantillas de certificado (certtmpl.msc), abra la plantilla, vaya a la pestaña Subject Name y seleccione «Build from this Active Directory information». La consola establece correctamente las marcas de sujeto y SAN correspondientes, lo que es más seguro que editar la máscara de bits directamente. Cuando un sujeto proporcionado sea un requisito real (certificados de servidor web solicitados por un sistema de aprovisionamiento), elimine los EKU de autenticación de cliente de esa plantilla y limite la inscripción al servicio de aprovisionamiento.
  3. Añadir aprobación o firmas RA en las plantillas que deban mantener un sujeto proporcionado junto con un EKU de autenticación. En la pestaña Issuance Requirements, marque «CA certificate manager approval».
  4. Retirar los derechos de escritura a cualquier titular que no sea administrador de PKI y restablecer el propietario de la plantilla a Enterprise Admins o a su grupo de administradores de PKI.
  5. Restringir los agentes de inscripción. En la pestaña Enrollment Agents de la CA, restrinja cada agente a plantillas y grupos de destino concretos en lugar del valor predeterminado «todos, todas las plantillas».

Los cambios en los objetos de plantilla se replican a través de la partición de configuración como cualquier otro cambio de AD, así que hágalos en un controlador de dominio y deje que la replicación los distribuya.

Verificar

Vuelva a ejecutar ambos scripts de auditoría: ninguna plantilla publicada apta para autenticación debe tener a la vez SuppliesSubject y un derecho Enroll Broad, y no debe quedar ninguna fila WRITE (ESC4) para titulares no administradores.

Confirme quién usa realmente una plantilla antes y después de cada cambio, a partir de la base de datos de la CA:

PowerShell
# Certificados emitidos a partir de una plantilla en los últimos 90 días (ejecutar en la CA)
$since = (Get-Date).AddDays(-90).ToString('MM/dd/yyyy')
certutil -view -restrict "Disposition=20,NotBefore>=$since" `
    -out "RequestID,RequesterName,CommonName,CertificateTemplate,NotBefore" csv > issued-90d.csv

CertificateTemplate se registra como el OID de la plantilla en las plantillas v2 o superiores; relaciónelo con la salida de certutil -template. Después active la auditoría de cambios de plantilla para que las desviaciones sean visibles. EDITF_AUDITCERTTEMPLATELOAD hace que la CA registre el evento 4898 cuando carga una plantilla y el 4899 cuando una plantilla ha cambiado, y una SACL en el contenedor Certificate Templates le proporciona eventos 5136 con el atributo modificado:

PowerShell
certutil -setreg policy\EditFlags +EDITF_AUDITCERTTEMPLATELOAD
Restart-Service certsvc

Reenvíe los eventos 4886, 4887, 4899 y 5136 a su SIEM y genere una alerta cuando se emita un certificado con un SAN que no coincida con el solicitante. El pilar de auditoría y detección cubre la parte de recopilación.

Qué se rompe

  • Despublicar una plantilla: los certificados existentes siguen siendo válidos hasta que caducan, pero la renovación falla. Los equipos con inscripción automática registrarán errores de inscripción en el registro Application (origen CertificateServicesClient-AutoEnrollment) cuando intenten renovar, así que revise ese registro en una muestra de clientes tras cada cambio.
  • Eliminar la inscripción de Domain Users o Domain Computers: la inscripción automática se detiene sin avisar para cualquiera que no esté en el nuevo grupo. Rellene el grupo de sustitución antes de eliminar la ACE antigua, no después.
  • Eliminar la marca de sujeto proporcionado: los sistemas de aprovisionamiento, conectores de MDM, balanceadores de carga y scripts que envían un CSR con su propio sujeto recibirán certificados con el sujeto derivado de AD, o fallarán directamente. Proporcióneles una plantilla dedicada sin EKU de autenticación de cliente.
  • Aprobación del administrador: las solicitudes quedan pendientes hasta que actúa un administrador de certificados, lo que rompe la inscripción desatendida. Úsela solo en plantillas de bajo volumen.
  • Restringir los agentes de inscripción: el personal que aprovisiona tarjetas inteligentes solo puede inscribir para las plantillas y grupos que usted indique, así que los nuevos tipos de tarjeta requieren un cambio de configuración en la CA.

Lecturas relacionadas: el tema Servicios de certificados de AD, asignación fuerte de certificados para la parte del KDC en la autenticación con certificados, y gestión de rutas de ataque para encontrar quién puede alcanzar indirectamente un derecho de inscripción.

Preguntas frecuentes

¿Sigue importando una plantilla de certificado no publicada?

Su configuración no importa hasta que una CA la publica, porque nadie puede inscribirse en una plantilla que ninguna CA ofrece. Su ACL sí importa: cualquiera con acceso de escritura puede modificarla, y cualquiera con derechos Manage CA puede publicarla. Trate las plantillas no publicadas como de baja prioridad para corregir marcas, pero limpie igualmente los permisos de escritura y elimine las plantillas que nunca vaya a usar.

¿Basta la aprobación del administrador para neutralizar una plantilla ESC1?

Convierte la plantilla en un flujo de trabajo controlado en lugar de abierto, lo que supone una gran mejora, pero solo es tan sólida como los aprobadores. Un administrador de certificados que aprueba solicitudes sin leer el SAN solicitado seguirá emitiendo un certificado de Domain Admin. Es preferible eliminar la marca «el solicitante proporciona el sujeto» y usar la aprobación como segunda capa en las plantillas que realmente necesitan un sujeto proporcionado.

¿Debo ejecutar Certify o Certipy contra producción?

Ambos son de solo lectura en sus modos de enumeración, pero son herramientas ofensivas y pueden disparar alertas del EDR. Para una auditoría defensiva, Locksmith y PSPKIAudit están diseñados para administradores, y el PowerShell nativo de esta guía cubre las mismas comprobaciones de plantillas. Si ejecuta una herramienta ofensiva, hágalo desde un equipo autorizado, con la gestión de cambios informada, y compare los resultados con su propio inventario.

Auditar las plantillas de certificado de AD CS (ESC1-ESC4)

Guías relacionadas