Jake Hildreth Consultor principal de seguridad

En mi investigación más reciente, he estado revisando sin mucha prisa los documentos de diseño de la Infraestructura de Clave Pública (PKI) de Microsoft y los RFC relacionados (en particular el RFC 4556), con el objetivo de encontrar un método fiable para escalar privilegios desde un usuario normal con pocos privilegios hasta cualquier cuenta arbitraria, sin que se produzcan errores de configuración. (Sí, así es como paso mi tiempo libre. Estas cosas son importantes para mí y para las personas con las que trabajo cuando elaboramos planes de preparación cibernética.)

Por desgracia, a pesar de haber investigado en ámbitos similares, no he encontrado ningún rastro del ataque «Certighost» en la documentación, aunque se trata de una vulnerabilidad conocida de los Servicios de Certificados de Active Directory (AD CS).

De hecho, no encontré ningún método para ampliar privilegios.

Sin embargo, sí que encontré un método de persistencia tras la explotación basado en una configuración errónea que, aunque no es tan llamativo como Certighost, resulta casi igual de inquietante.

  • No requiere acceso a la clave privada de una autoridad de certificación (un requisito previo para un ataque de «certificado dorado» o «billete dorado» ).
  • Esto va en contra de las recomendaciones generalizadas sobre cómo recuperar el acceso a cuentas comprometidas.
  • A diferencia de Certighost, esta vulnerabilidad no se corregirá mediante un parche, ya que se basa en una configuración documentada por Microsoft y diseñada para realizar pruebas y solucionar problemas.

Si te encargas de prevenir y gestionar las infracciones de seguridad relacionadas con los sistemas de identidad en tu entorno, te interesará estar al tanto de esto.

Hoy os voy a hablar de los «certificados zombi»: ¡certificados de autenticación que no se pueden eliminar!

«¿Quién es?» El proceso de autenticación de PKINIT

En un entorno típico de Active Directory (AD), la forma principal de credencial de autenticación es la conocida combinación de nombre de usuario y contraseña. Tu nombre de usuario es una afirmación de quién eres; tu contraseña verifica esa afirmación.

Sin embargo, AD también admite el uso de certificados de clave pública como credenciales de autenticación, a menudo en forma de tarjetas inteligentes. Este proceso de autenticación basado en certificados se denomina «Criptografía de clave pública para la autenticación inicial» ( PKINIT, por sus siglas en inglés). La implementación de PKINIT por parte de Microsoft se describe detalladamente en MS-PKCA, pero, en resumen, en lugar de cifrar los tickets relacionados con la autenticación (AS-REP/AS-REQ) con tu contraseña, utilizas una clave privada, controlada por ti, para cifrar dichos tickets.

Al analizar la sección 6.3.3 del RFC 5280, encontré la definición del algoritmo sobre lo que ocurre cuando un verificador no puede determinar el estado de revocación:

Tras procesar dichas CRL, si aún no se ha determinado el estado de revocación, devuelve el estado del certificado como «UNDETERMINED».

«¿Te conozco?» PKINIT en Active Directory

Cuando intentas autenticarte en AD con un certificado a través de PKINIT, interactúas con un controlador de dominio (DC) que actúa como centro de distribución de claves de Kerberos (KDC). Durante el proceso de PKINIT, el KDC comprueba si el certificado que estás utilizando es válido en ese momento para la autenticación.

El KDC comprueba varios atributos del certificado antes de afirmar «sí, te reconozco», entre los que se incluyen (entre otros):

  • Emisor: El KDC debe confiar en la autoridad de certificación (CA) que emitió el certificado. Si el KDC no confía en el emisor del certificado, no podrás acceder.
  • Uso previsto: Los certificados incluyen información que explica cómo se pueden utilizar (más detalles al respecto a continuación). Si intentas autenticarte con un certificado destinado a la firma de código, no podrás acceder.
  • Período de validez: Si intentas autenticarte hoy con un certificado que no es válido hasta 20X6, no vas a poder entrar. Y si intentas autenticarte hoy con un certificado que caducó en 1666, tampoco vas a poder entrar.
  • Estado de revocación: Un emisor puede revocar un certificado incluyéndolo en una lista de certificados revocados (CRL). Si intentas utilizar un certificado que figura en una CRL, lo más probable es que —como habrás adivinado— no puedas acceder.

Pero ese último punto es un poco complicado…

¿Qué ocurre si la CRL no está disponible? Al fin y al cabo, las CRL suelen publicarse como direcciones URL HTTP en servidores web, y estos casi nunca tienen un tiempo de actividad perfecto.

Como ya hemos visto, los RFC son claros al respecto. Cuando una CRL no está disponible, el KDC debe marcar el estado de revocación del certificado como «INDETERMINADO». Lo que no queda tan claro en los RFC ni en la documentación de Microsoft es qué significa «INDETERMINADO» en el contexto del proceso PKINIT.


Forzar lo desconocido

Al crear las detecciones de ESC16 para Cerrajero y Cerrajero 2 (herramientas de código abierto que se pueden encontrar en GitHub), descubrí el DisableExtensionList Configuración de las autoridades de certificación (CA) de Servicios de certificados de AD (AD CS). Extensiones son pequeños fragmentos de información que se añaden a un certificado y que explican a qué sirve dicho certificado y cómo puede y debe utilizarse.

En una CA de AD CS, el DisableExtensionList Esta configuración se utiliza para evitar que no se añadan determinadas extensiones a los certificados emitidos por una CA. Por lo general, esta lista permanece vacía, pero se pueden añadir extensiones a la misma (y, por lo tanto, eliminarlas de los certificados emitidos) con fines de prueba, para mejorar la compatibilidad, para aumentar la seguridad, etc.

Una de las extensiones que suelen añadirse a un certificado es la extensión «Punto de distribución de CRL» (CDP), también conocida como OID 2.5.29.31. La extensión CDP indica a un KDC (o a cualquier otra entidad verificadora) exactamente dónde encontrar el estado de revocación de un certificado.

Pregunta: ¿Qué ocurre si añado la extensión CDP al DisableExtensionList? ¿Emitiría una CA de AD CS un certificado sin la extensión CDP?

Respuesta: Pues resulta que… ¡sí! Cuando el OID 2.5.29.31 existe en el DisableExtensionList, todos los certificados emitidos por la CA carecen de la extensión CDP, ya que Figura 1 espectáculos.

Figura 1: Un certificado típico y un certificado que carece de la extensión CDP

Ahora, la pregunta más importante: ¿Podría utilizar un certificado sin extensión CDP para ejecutar correctamente PKINIT?

Por desgracia, no.

Durante el proceso PKINIT, el KDC intenta comprobar el estado de revocación del certificado presentado. Sin la extensión CDP, el KDC no sabe dónde comprobar el estado del certificado. Responde con KDC_REVOCATION_UNKNOWN, y la solicitud de autenticación es rechazada. El certificado ha caducado… por ahora.

Esta respuesta de «cierre por fallo» es la configuración predeterminada de AD, pero este comportamiento no es inamovible.


Hacer caso omiso de lo desconocido

A medida que profundizaba en el tema, me di cuenta de que Microsoft ya había tenido en cuenta la situación de las CRL inaccesibles y había creado un valor de registro para solucionarla: UseCachedCRLOnlyAndIgnoreRevocationUnknownErrors. Como sugiere el nombre del valor, cuando UseCachedCRLOnlyAndIgnoreRevocationUnknownErrors está configurado en 1, se utilizan las CRL almacenadas en caché para comprobar el estado de revocación (¡mejor que nada!) y se ignoran los errores de «revocación desconocida».

Entonces me pregunté: si este valor del Registro está configurado y puedo provocar un error desconocido, ¿funcionaría PKINIT?

Querido lector, me siento a la vez muy triste y súper emocionado al comunicarte que la respuesta es un rotundo SÍ.

Un único valor del registro cambia todo el proceso PKINIT de «fail-closed» a «fail-open».

Figura 2: ¿Eres un «Good Cert» o un «Bad Cert»?

Este comportamiento me perturba profundamente. Pero también tiene todo el sentido del mundo. Según la documentación de varios proveedores (entre ellos Microsoft), este valor del Registro puede utilizarse para relajar los controles de seguridad en situaciones como las pruebas y la resolución de problemas.

No está pensado para un uso permanente. En efecto, le indica al KDC que mantenga la puerta desbloqueada para cualquier cosa que no pueda demostrar que está realmente inactiva.


Ocultar lo desconocido

Existe un efecto secundario interesante e inesperado asociado a un certificado sin extensión CDP: puede revocarse e incluirse en la lista CRL de una CA como cualquier otro certificado, pero su inclusión en dicha lista carece, en esencia, de sentido.

Imagina que la CRL es un cementerio y que cada entrada de revocación es una lápida. El certificado «zombi» tiene una lápida con su nombre, pero el certificado no incluye indicaciones para llegar al cementerio, por lo que nadie va nunca a comprobarlo.

Parece que está muerto, pero no lo está. ¡Es un certificado zombi!

Esto supone un verdadero problema durante la respuesta a incidentes. A veces, durante la respuesta a incidentes, es necesario restablecer o revocar todas las credenciales asociadas a una cuenta comprometida, incluidas las contraseñas y todos los certificados de autenticación.

¿Qué ocurre cuando, en realidad, no se puede revocar un certificado de autenticación?


Encajar las piezas para lograr una persistencia sigilosa

En esta fase de mi investigación, había observado varios comportamientos distintos:

  1. Los certificados de autenticación se pueden crear sin una extensión CDP.
  2. Es imposible comprobar el estado de revocación de un certificado que no cuente con una extensión CDP.
  3. Sin una extensión CDP, un certificado puede parecer revocado para la CA y sus administradores, pero esa apariencia carece de sentido si no se puede comprobar el estado de revocación.
  4. Si un verificador no puede consultar el estado de revocación de un certificado (por cualquier motivo), el estado del certificado es «desconocido», y no «revocado» ni «válido».
  5. De forma predeterminada, la implementación de PKINIT por parte de Microsoft rechaza los certificados cuyo estado de revocación se desconoce.
  6. El comportamiento predeterminado de «cierre por fallo» se puede cambiar a «apertura por fallo» modificando un único valor del registro.

Todas las piezas estaban ahí. Solo tenía que dejar de intentar que caminaran.

Me pasé demasiado tiempo intentando encajar estos elementos de comportamiento para formar una cadena completa de escalada de privilegios, pero al final me rendí. Me parecía simplemente imposible. Sin acceso administrativo al servidor de la CA o al servicio de la CA, es imposible editar DisableExtensionList. Modificar el UseCachedCRLOnlyAndIgnoreRevocationUnknownErrors Para modificar un valor del Registro en los servidores de dominio, normalmente es necesario pertenecer al grupo BUILTIN\Administrators (BA) del dominio. Ninguna de estas operaciones es posible sin los permisos y privilegios previos necesarios.

Pero, ¿y si dejara de centrarme en las ESC (técnicas de escalada) y, en su lugar, empezara a pensar en las PERSIST (técnicas de persistencia)?

En el informe técnico de SpecterOps de 2021 titulado «Certified Pre-Owned», los autores enumeraron varias opciones de persistencia a nivel de dominio, de usuario y de equipo basadas en AD CS. La persistencia no es tan llamativa como la escalada de privilegios y rara vez se destaca en una prueba de penetración típica. Sin embargo, los atacantes utilizan la persistencia para recuperar el acceso a un entorno que ya han comprometido anteriormente.

¡Es un aspecto importante a tener en cuenta!


Poniéndolo todo en contexto: cómo los atacantes crean los «certificados zombis»

Cuando cambié mi forma de pensar de «¡Tengo que encontrar un nuevo ESC!» a «¡PERSIST también da miedo!», la situación se me hizo más clara y, la verdad, me asustó un poco. Imagina que un atacante sigue los siguientes pasos:

  1. Consiguen un acceso con amplios privilegios a tu entorno de Active Directory: BA, administradores de dominio (DA) o administradores de empresa (EA). (Este paso es, a propósito, muy impreciso. ¡Tendrás que conformarte con ello!)
  2. El atacante comprueba que existe una infraestructura de clave pública (PKI) de AD CS en el bosque y que es compatible con PKINIT, verificando si hay una o más autoridades de certificación (CA) en el bosque’s NtAuthCertificates objeto.
  3. Mediante RemoteRegistry o la modificación directa del registro, el atacante configura el UseCachedCRLOnlyAndIgnoreRevocationUnknownErrors valor a 1 en uno o varios centros de datos.
  4. Añaden el OID 2.5.29.31 a una CA DisableExtensionList, ya sea a través de certutil.exe o la modificación directa del registro del servidor de la CA.
  5. El atacante solicita un certificado de autenticación para un usuario que controla, probablemente la cuenta BA/DA/EA que está utilizando en ese momento.
  6. Confirman que el «Zombie Certificate» funciona con PKINIT.

En un entorno típico, las fases de reconocimiento, modificación del registro, solicitud de certificados y validación de PKINIT de este ataque pueden automatizarse mediante scripts y llevarse a cabo en cuestión de segundos, ya que muchos de estos elementos son bien conocidos o extremadamente fáciles de detectar utilizando binarios integrados y código .NET obsoleto presente en cualquier ordenador moderno con Windows.

A menos que se relacionen los sucesos de varias fuentes en un único conjunto de indicadores, simplemente no se detectará este ataque.

Sin embargo, imaginemos que nuestros valientes defensores se dan cuenta de la intrusión y toman rápidamente medidas para contenerla. Ellos:

  • Cierra todas las sesiones de inicio de sesión activas de la cuenta comprometida
  • Restablecer la contraseña de Active Directory de la cuenta comprometida
  • Revocar los certificados de autenticación de la cuenta comprometida
  • Haz otras cosas… No formo parte del equipo de relaciones con los inversores de Semperis, así que confío en su experiencia…

A pesar de estas medidas, el atacante puede utilizar el «certificado zombi» que solicitó en el paso 6 anterior para ejecutar PKINIT y recuperar el acceso a la cuenta que controlaba anteriormente.

¿Cómo? Porque se desconoce el estado de revocación del certificado, y el atacante modificó el proceso PKINIT para que adoptara un comportamiento de «fail-open» cuando se desconoce dicho estado.


Y la cosa se pone aún más espeluznante: la reanimación de los zombis

La respuesta de gestión de incidentes que he descrito anteriormente era intencionadamente incompleta: la cuenta comprometida debería haberse desactivado y sustituido por completo por una nueva. Sin embargo, en medio del caos que supone un incidente, es posible que se pasen por alto algunas medidas correctivas.

¡La contención incompleta es algo real!

Sin embargo, un atacante más previsor podría haber introducido algunos cambios en su procedimiento para que su acceso fuera aún más persistente. En lugar de utilizar una plantilla ya existente para solicitar un certificado de autenticación para la cuenta que había comprometido, el atacante podría:

  • Crea una nueva plantilla que incluya la configuración errónea del ESC1
  • Utiliza la plantilla ESC1 para solicitar un certificado que incluya el SAN de otra cuenta con privilegios.

Ahora bien, si se desactiva o se elimina al usuario que se vio comprometido inicialmente, el atacante seguiría conservando el control de la cuenta con privilegios incluida en el SAN.

Este zombi tiene un segundo latido. Si matas al huésped, seguirá caminando con una identidad diferente.

Nota al margen: Hay varias formas maliciosas adicionales de hacer que este ataque sea más sigiloso, pero mi conciencia no me permite detallarlas aquí.


Cómo detectar certificados «zombi»

¿Cómo sabes si tienes una plaga de zombis? Empieza por los cerebros.

El «cerebro» de un certificado zombi es el UseCachedCRLOnlyAndIgnoreRevocationUnknownErrors valor del Registro. Comprueba todos los controladores de dominio de tu bosque y cualquier bosque de confianza. La ruta completa del Registro es:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kdc\UseCachedCRLOnly AndIgnoreRevocationUnknownErrors

Si algún DC tiene este valor establecido en 1, considéralo un indicio claro de manipulación hasta que se demuestre lo contrario. Investiga a fondo tomando las siguientes medidas:

  • Comprueba si hay certificados de autenticación emitidos a usuarios con privilegios, aunque parezcan revocados.
  • Busca cualquier certificado de autenticación que incluya el SAN de un usuario con privilegios, independientemente de si el solicitante está habilitado o deshabilitado.
  • Comprueba todas las CA’s DisableExtensionList ejecutando el siguiente comando: certutil -config <CA-HOST-FQDN\CAName> -getreg policy\DisableExtensionList

Si ves el siguiente resultado, significa que ha cambiado algo que no debería haber cambiado:

Figura 3: El atacante está dentro de la casa

Cómo matar al zombi

El valor del registro es el golpe definitivo. Un certificado «zombi» solo es peligroso mientras haya al menos un servidor de dominios (DC) que acepte un estado de revocación desconocido. Lo primero es eliminar esa condición.

  1. En cada DC afectado, elimina UseCachedCRLOnlyAndIgnoreRevocationUnknownErrors y reinicia el Centro de Distribución de Claves de Kerberos. Esto restablece inmediatamente el comportamiento de «fail-closed». PKINIT rechazará cualquier certificado cuyo estado de revocación no pueda confirmarse.
  2. Eliminar OID 2.5.29.31 de la CA DisableExtensionList. Los nuevos certificados volverán a incluir la extensión CDP.
    Un punto fundamental: Los certificados ya emitidos sin una extensión CDP son inmunes de forma permanente a la revocación, independientemente de lo que figure en la CRL de la CA. La entrada de revocación existe, pero ningún verificador la encontrará jamás, ya que el certificado no contiene ningún puntero a la CRL. Estos certificados son inofensivos una vez que se haya corregido el registro, pero deben localizarse y sustituirse.
  3. Identifica todos los certificados emitidos durante el periodo en el que DisableExtensionList contenían el OID del CDP. Revócalos todos. Aunque ya han dejado de ser operativos una vez corregido el valor del registro, la revocación explícita cierra el ciclo y genera un registro de auditoría.
  4. Forzar la reinscripción de todas las cuentas afectadas, especialmente las que tienen privilegios. Emitir nuevos certificados que incluyan una extensión CDP válida.

Prevenir el próximo brote

No basta con matar al zombi activo. Tienes que detener al siguiente.

  • Supervisa el registro de cada controlador de dominio en el que confíes. Aviso en caso de cualquier cambio en UseCachedCRLOnlyAndIgnoreRevocationUnknownErrors en todos los centros de datos. Cualquier valor distinto de absent o 0 debería dar lugar a una investigación inmediata.
  • Auditoría DisableExtensionList según un horario. Debería estar vacío en todas las CA de tu bosque. Puedes comprobar la ruta del Registro directamente o consultarla a través de certutil: certutil -config <CA-HOST-FQDN\CAName> -getreg policy\DisableExtensionList
    Consejo de experto: En Plataforma Semperis Lightning ¡Puede supervisar el registro por ti!
  • Utiliza Locksmith 2. Tanto Locksmith como Locksmith 2 incluyen la detección de la configuración incorrecta de «DisableExtensionList». Ejecútalos periódicamente como parte de tus comprobaciones de estado de AD CS.

Para que se produzca un brote de «certificados zombis», deben darse simultáneamente dos condiciones:

  • Una CA que emite certificados sin la extensión CDP
  • Al menos un DC que se queda en estado abierto debido a un estado de revocación desconocido

Si se elimina cualquiera de estas dos condiciones, el ataque fracasa. Si se eliminan ambas, se consigue una PKI mucho más segura.


Prepárate para que los zombis vuelvan a levantarse… y mantente alerta

Los «certificados zombi» no son un caso extremo teórico. Se basan íntegramente en una funcionalidad de Microsoft documentada e intencionada.

Ningún CVE solucionará esto. No va a salir ningún parche. El ataque funciona porque los administradores a veces tienen que flexibilizar la comprobación de revocaciones, y los atacantes pueden aprovecharse de esa misma flexibilidad.

La buena noticia es que los requisitos previos son importantes. Un atacante necesita un acceso con privilegios elevados para que nada de esto sea posible, lo que significa que una buena gestión de los privilegios es fundamental. La mala noticia es que, una vez cumplidos esos requisitos previos, el ataque es rápido, se puede automatizar mediante scripts y burla la mayoría de los protocolos estándar de respuesta a incidentes.

Si utilizas AD CS en tu entorno, comprueba el valor del Registro y el DisableExtensionList en todos los CA de hoy. Si encuentras cualquiera de los dos de forma inesperada, tienes un problema que merece la pena investigar. Si encuentras ambos juntos, es posible que ya tengas un zombi merodeando por tu bosque.

Si necesitas ayuda para eliminar los «certificados zombis», ponte en contacto con Semperis. Nuestros expertos en respuesta a incidentes se dedican a esto a diario, y estamos aquí para ayudarte.

Descargo de responsabilidad

Este contenido se proporciona únicamente con fines educativos e informativos. Su objetivo es promover la concienciación y la corrección responsable de las vulnerabilidades de seguridad que puedan existir en los sistemas que usted posee o está autorizado a probar. El uso no autorizado de esta información con fines maliciosos, explotación o acceso ilegal está estrictamente prohibido. Semperis no respalda ni aprueba ninguna actividad ilegal y declina toda responsabilidad derivada del uso indebido del material. Además, Semperis no garantiza la exactitud o integridad del contenido y no asume ninguna responsabilidad por los daños derivados de su uso.


Más información sobre cómo prevenir y eliminar la persistencia en Active Directory y Entra ID