cabecera blog BlackArrow

AD CS: automatizando el ataque ESC7

Introducción a AD CS ESC7

El pasado año, SpecterOps hizo pública una concienzuda investigación sobre la seguridad en el Servicio de Certificados del Directorio Activo (AD CS) que aún a día de hoy sigue siendo objeto de debate y comentario.  En un extenso documento técnico, detallaron diversas maneras de abusar de fallos de configuración en los distintos elementos que componen el entorno tanto para obtener persistencia como para escalar privilegios en el dominio. 

Junto con estos nuevos vectores de ataque también se publicaron mecanismos de defensa y detección contra los mismos, así como varias herramientas tanto para llevar a cabo la explotación de estos fallos de configuración (Certify y ForgeCert) como para auditar un entorno de AD CS en busca de estas configuraciones incorrectas (PSPKIAudit).  

Desde el Red Team hemos hecho uso de estos nuevos vectores de ataque en diversos ejercicios a lo largo de los últimos meses, sobre todo con el objetivo de escalar privilegios a nivel de dominio y obtener persistencia. En este sentido, los ataques ESC1 y ESC8 son probablemente los que más hemos utilizado, siendo estos vectores de ataque también los más comentados y documentados en distintos artículos que se pueden encontrar por Internet.   

En esta publicación vamos a centrar el foco en el ataque ESC7, utilizando para ello una situación real que nos hemos encontrado recientemente en uno de nuestros ejercicios de Red Team. Los puntos principales que se abordarán en este artículo son los siguientes: 

  • Profundizaremos en el abuso de los permisos ManageCA y ManageCertificates para comprometer el entorno de Directorio Activo. 
  • Se detallarán los nuevos módulos que hemos implementado para la herramienta Certify, que permitirán la explotación automática de este vector de ataque. 

Planteamiento del ataque ESC7

Durante la ejecución del ejercicio en la red del cliente, Certify nos indicó la existencia de una CA (Certificate Authority) que otorgaba los permisos ManageCA y ManageCertificate al grupo de Usuarios Autentificados, lo que en otras palabras significa proporcionar dichos permisos a cualquier usuario del dominio.

Según la publicación de SpecterOps, otorgar estos permisos a usuarios no privilegiados es peligroso por diversos motivos:  

  • El permiso ManageCA permite a un usuario modificar la configuración de la CA lo que, entre otras cosas, permite activar a nivel de CA el uso de SANs (Subject Alternative Name), sobrescribiendo de esta manera la configuración de todas las plantillas gestionadas por la Autoridad Certificadora. Un SAN es una extensión que permite ligar a un certificado otras identidades aparte de la del usuario que esté solicitando dicho certificado. Esto es lo que se utiliza para ejecutar el vector de ataque ESC1, dado que si una plantilla permite esta extensión se puede solicitar un certificado válido para cualquier otro usuario del dominio, con la diferencia de que el privilegio ManageCA te permite activar esta extensión para todas las plantillas (lo que habilita la ejecución del ataque ESC6), independientemente de que estas lo permitan o no en su configuración individual.  
  • Por otro lado, el permiso ManageCertificates tiene menos implicaciones en cuanto a riesgos de seguridad, si bien permite a cualquier usuario que lo posea emitir certificados pendientes de aprobación.   

De esta manera, lo único que habría que hacer para llevar a cabo el ESC7 es activar el uso de la extensión SAN a nivel de CA y buscar una plantilla válida para autenticación en la que cualquier usuario no privilegiado pudiera inscribirse (enroll), permitiéndonos de esta manera obtener un certificado ligado a cualquier usuario del grupo Administradores del Dominio. 

Sin embargo, la publicación de SpecterOps apuesta por utilizar el módulo PSPKI para llevar a cabo el ataque, el cual es demasiado grande y con demasiadas dependencias como para poder ser cargado de manera funcional en el entorno del cliente sin generar una gran cantidad de ruido y levantar sospechas.  

Por lo tanto, decidimos implementar por nuestra cuenta la funcionalidad deseada como un nuevo módulo de Certify para facilitar la explotación en entornos reales donde existe monitorización activa.

Para ello, se ha hecho uso del método DCOM ICertAdmin2::SetConfigEntry para modificar remotamente la configuración de la CA y activar el atributo EDITF_ATTRIBUTESUBJECTALTNAME2, el cual habilita el uso de la extensión SAN para todas las plantillas. Esta actividad modifica la clave EditFlags en el registro de la CA:  

CERTADMINLib.ICertAdmin2 objCertAdmin = new CERTADMINLib.CCertAdmin();

try
{
  if (enableSAN)
  {
    // read the current configuration 
	var entry = objCertAdmin.GetConfigEntry(CA, @"PolicyModules\CertificateAuthority_MicrosoftDefault.Policy", "EditFlags");

	// 0x00040000 ==  EDITF_ATTRIBUTESUBJECTALTNAME2 
	if (((int)entry & 0x00040000) == 0x00040000)
	{
		Console.WriteLine("\r\n[*] EDITF_ATTRIBUTESUBJECTALTNAME2 is already enabled. No changes required.");
	}
	else
	{
		// flip the EDITF_ATTRIBUTESUBJECTALTNAME2 bit
		var newValue = (int)entry | 0x00040000;
		objCertAdmin.SetConfigEntry(CA, @"PolicyModules\CertificateAuthority_MicrosoftDefault.Policy", "EditFlags", newValue);
		Console.WriteLine("\r\n[*] EDITF_ATTRIBUTESUBJECTALTNAME2 enabled!");
	}
  }
}

Tras modificar la configuración y haciendo pruebas en nuestro laboratorio, nos dimos cuenta de que seguíamos sin poder solicitar certificados a nombre de otros usuarios, lo que nos llevó a percatarnos de que es necesario reiniciar la CA para que los cambios se apliquen adecuadamente. Por suerte, el permiso ManageCA también otorga la posibilidad de llevar a cabo este reinicio: 

ServiceController sc = new ServiceController("CertSvc", computerName);

try
{
	if (sc.Status == ServiceControllerStatus.Running)
	{
		sc.Stop();
		sc.WaitForStatus(ServiceControllerStatus.Stopped);
	}

	sc.Start();
	sc.WaitForStatus(ServiceControllerStatus.Running);

	Console.WriteLine("\r\n[*] CertSvc service restarted!");

}
catch (Exception e)
{
	Console.WriteLine($"[X] Error restarting CA service (CertSvc): {e}");
	return;
}

Con esto, todo parecía estar listo para realizar el ataque sobre el cliente, por lo que escogimos la plantilla por defecto User para llevar a cabo la inscripción, con el objetivo de solicitar un certificado a nombre de un usuario Administrador del Dominio. Esta plantilla permitía la inscripción a cualquier usuario, servía para autenticación y en principio no requería la aprobación por parte de un administrador, por lo que se cumplían todos los requisitos para ejecutar el ataque: 

Datos de la plantilla User
Datos de la plantilla User

Por lo tanto, y tras modificar satisfactoriamente la configuración de la CA en la red del cliente para permitir de manera global el uso de la extensión SAN, procedimos a solicitar un certificado ligado a la identidad de un usuario Administrador del Dominio, obteniendo la siguiente respuesta por parte de Certify: 

Emisión del certificado pendiente de aprobación
Emisión del certificado pendiente de aprobación

Inexplicablemente, la solicitud del certificado se quedaba pendiente de aprobación a pesar de que la plantilla indicaba que la aprobación estaba desactivada. Probamos con otras de las plantillas que cumplían nuestros requisitos para llevar a cabo el ESC7, pero obtuvimos el mismo resultado para todas ellas, por lo que volvimos al laboratorio a investigar este comportamiento para averiguar qué ocurría y cómo podíamos sortear el problema. 

Aprobación de Certificados 

El requisito de aprobación de un certificado habitualmente se configura a nivel de plantilla, y permite retener la emisión de un certificado hasta que lo apruebe un usuario administrador (es decir, un usuario con el permiso ManageCertificates). En nuestro caso, ya contábamos con dicho permiso sobre la CA, por lo que para poder aprobar nuestros propios certificados decidimos implementar un nuevo módulo en Certify que automatizase este proceso.  

Esto es relativamente sencillo de ejecutar, dado que únicamente es necesario utilizar el método DCOM ICertAdmin2::ResubmitRequest pasándole como parámetro el identificador de la petición (Request ID) recibido anteriormente al solicitar el certificado con Certify: 

// issues a pending for approval certificate. ManageCertificates right required
public static void IssuePendingCertificate(string CA, int requestId)
{
	CERTADMINLib.ICertAdmin2 objCertAdmin = new CERTADMINLib.CCertAdmin();

	var result = objCertAdmin.ResubmitRequest(CA, requestId);

	if (result == 3)
	{
		Console.WriteLine("\r\n[*] Certificate issued!");
	}
	else
	{
		Console.WriteLine("[X] Error issuing pending certificate.");
	}
}

Sin embargo, esto no explicaba por qué los certificados solicitados requerían de aprobación a pesar de que en su configuración se explicitaba que no era necesario este trámite.

Por lo tanto, investigamos el asunto en nuestro laboratorio hasta finalmente descubrir el origen de este comportamiento: existe una configuración en la CA que permite retener todas las peticiones de certificados para su aprobación, independientemente de lo que se indique en la configuración de las plantillas.

De manera similar a lo que ocurría con el atributo EDITF_ATTRIBUTESUBJECTALTNAME2, esta configuración tiene preferencia y sobrescribe la configuración de las plantillas. Y, además, Certify ignora esta configuración, por lo que en ningún momento emite ningún mensaje de advertencia que permita conocer de antemano esta situación. 

Para forzar a nivel de CA la necesidad de aprobación de los certificados solicitados, simplemente se ha de utilizar la interfaz gráfica integrada en Windows y activar la configuración que se muestra en la siguiente imagen:  

Configuración que permite activar la necesidad de aprobación de certificados a nivel de CA
Configuración que permite activar la necesidad de aprobación de certificados a nivel de CA

Si bien en la mayoría de los casos, la capacidad de aprobar certificados individualmente es más que suficiente para llevar a cabo los diferentes ataques (solicitas un certificado y, si queda en estado pendiente, te lo apruebas a ti mismo), en algunas situaciones puede ser necesaria la desactivación de esta configuración a nivel de CA. En la siguiente sección se describe una de estas situaciones, si bien también podría ser útil si necesitas obtener el certificado en una sola operación o estás usando una herramienta que no tiene en cuenta certificados pendientes.  

Por lo tanto, decidimos integrar también esta funcionalidad en Certify haciendo uso nuevamente del método DCOM ICertAdmin2::SetConfigEntry para modificar la clave de registro RequestDisposition (requiere el reinicio de la CA para que los cambios se apliquen adecuadamente), deshabilitando de esta manera el atributo REQDISP_PENDINGFIRST

if (removeApproval)
{
	// read the current configuration 
	var entry = objCertAdmin.GetConfigEntry(CA, @"PolicyModules\CertificateAuthority_MicrosoftDefault.Policy", "RequestDisposition");

	// 0x00000100 ==  REQDISP_PENDINGFIRST
	if (((int)entry & 0x00000100) ==  0)
	{
		Console.WriteLine("\r\n[*] The CA is not forcing the approval of requested certificates. No changes required.");
	}
	else
	{
		// Edit the registry entry RequestDisposition to remove the mandatory approval for requested certificates
		var newValue = (int)entry & 0x11111011;
		objCertAdmin.SetConfigEntry(CA, @"PolicyModules\CertificateAuthority_MicrosoftDefault.Policy", "RequestDisposition", newValue);
		Console.WriteLine("\r\n[*] Approval for requested certificates has been removed.");
	}
}

Ejecución del ataque ESC7

Llegados a este punto, la ejecución del ataque ESC7 para llevar a cabo la escalada de privilegios en dominio utilizando Certify podría seguir la siguiente línea de actuación: 

  1. Detección del permiso ManageCA (este permiso permite otorgarte cualquier otro, por lo que virtualmente te proporciona también el permiso ManageCertificates) otorgado a usuarios no privilegiados o bajo nuestro control: 
Localización de una CA vulnerable
Localización de una CA vulnerable
  1. Modificación de la configuración de la CA para habilitar el uso de la extensión SAN sobre cualquiera de las plantillas (ESC6): 
Activación de la extensión SAN a nivel de CA
Activación de la extensión SAN a nivel de CA
  1. Solicitud de un certificado con un usuario privilegiado como Alternative Name: 
Solicitud de un certificado con usuario privilegiado como SAN
Solicitud de un certificado con usuario privilegiado como SAN
  1. En el caso de que la emisión del certificado quede pendiente de aprobación, se puede aprobar el certificado abusando del permiso ManageCertificates y descargarlo a continuación: 
Emisión de certificado pendiente de aprobación
Emisión de certificado pendiente de aprobación
Descarga del certificado
Descarga del certificado
  1. De manera alternativa, también se podría deshabilitar la necesidad de aprobación para los certificados a nivel de CA y solicitar uno nuevo, el cual ya no requeriría de aprobación: 
Desactivación del requisito de aprobación de certificados a nivel de CA
Desactivación del requisito de aprobación de certificados a nivel de CA

Llevando a cabo estos pasos en la red del cliente, conseguimos explotar de manera satisfactoria el ataque ESC7, obteniendo así un certificado válido a nombre de un usuario Administrador del Dominio. Sin embargo, al utilizar Rubeus para solicitar un TGT a partir del certificado recibimos el siguiente mensaje de error: 

Error KDC_ERR_PDATA_TYPE_NOSUPP
Error KDC_ERR_PDATA_TYPE_NOSUPP

Investigando este comportamiento en nuestro laboratorio fuimos capaces de replicarlo al revocar y eliminar los certificados de los Controladores de Dominio por lo que, en nuestra opinión, este error probablemente se produzca cuando los DCs no cuenten con certificados para autenticación válidos (ya sea porque directamente no los tengan, porque hayan caducado o porque hayan sido revocados) y no sean capaces de obtener nuevos certificados de ninguna CA de confianza.

Esto concuerda con la situación detectada en la red del cliente dado que, al tener activado el atributo REQDISP_PENDINGFIRST, las solicitudes de inscripción que hayan podido generar los DC habrán quedado pendientes de aprobación y no se habrá completado la emisión de nuevos certificados.  

Tras listar las solicitudes de certificado pendientes de aprobación existentes en la CA, confirmamos que de manera automática los controladores de dominio intentaban obtener un certificado válido (aparentemente de forma mensual), por lo que es probable que desactivando el atributo REQDISP_PENDINGFIRST en la CA se hubiera solucionado el problema de autenticación mencionado. Sin embargo, por razones logísticas y para evitar dañar la operatividad del entorno del cliente, decidimos detenernos en este punto y no llevar a cabo ninguna modificación más. 

Para esta y otras situaciones en las que no sea posible el compromiso directo del Directorio Activo a través del ESC7, se plantearán en un próximo post varias maneras de comprometer el equipo donde se localiza la CA abusando del permiso ManageCA.

Conclusión 

En este artículo hemos ahondado en el vector de ataque ESC7, añadiendo diversos módulos a la herramienta Certify que permitirán la explotación automática de este ataque los cuales, de momento, están disponibles en nuestro repositorio.

En el próximo artículo publicaremos nuevas maneras de abusar del privilegio ManageCA para comprometer el equipo de la CA, abriendo la puerta a nuevos vectores de ataque contra AD CS que serán de especial relevancia en aquellos casos donde no sea posible solicitar certificados directamente.

Más artículos de la serie AD CS

Este artículo forma parte de una serie de articulos sobre AD CS

  1. AD CS: automatizando el ataque ESC7
  2. AD CS: de ManageCA a RCE