Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
ctl_ctloutput-leak — CVE-2017-13868: Fuga de información de datos no inicializados del heap del kernel en XNU. | Kitploit
Herramientas/GitHubGitHub/bazad/ctl_ctloutput-leak
Forensia de MemoriaAnálisis de VulnerabilidadesExplotaciónRecopilación de InformaciónExplotación de Binarios
GitHubbazad/ctl_ctloutput-leak

ctl_ctloutput-leak

CVE-2017-13868: Fuga de información de datos no inicializados del heap del kernel en XNU.

Ver Repositorio
2752hace 8 añosRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

ctl_ctloutput-leak

La función ctl_ctloutput en macOS High Sierra 10.13 ignora el valor de retorno de una llamada a sooptcopyin, lo que abre una ventana de carrera para filtrar datos no inicializados del heap del kernel al espacio de usuario. ctl_ctloutput-leak es un exploit de prueba de concepto que intenta desencadenar esta fuga de información. La explotación requiere privilegios de root.

Se ha confirmado que este exploit funciona en macOS High Sierra 10.13.1 Beta 17B25c e iOS 10.1.1 14B100 (bajo mach_portal).

La vulnerabilidad: CVE-2017-13868

Aquí está la parte relevante de ctl_ctloutput en macOS High Sierra 10.13:

root@kitploit:~
if (sopt->sopt_valsize && sopt->sopt_val) {
	MALLOC(data, void *, sopt->sopt_valsize, M_TEMP,	// (a) data is allocated
		M_WAITOK);					//     without M_ZERO.
	if (data == NULL)
		return (ENOMEM);
	/*
	 * 4108337 - copy user data in case the
	 * kernel control needs it
	 */
	error = sooptcopyin(sopt, data,				// (b) sooptcopyin() is
		sopt->sopt_valsize, sopt->sopt_valsize);	//     called to fill the
}								//     buffer; the return
len = sopt->sopt_valsize;					//     value is ignored.
socket_unlock(so, 0);
error = (*kctl->getopt)(kctl->kctlref, kcb->unit,		// (c) The getsockopt()
		kcb->userdata, sopt->sopt_name,			//     implementation is
			data, &len);				//     called to process
if (data != NULL && len > sopt->sopt_valsize)			//     the buffer.
	panic_plain("ctl_ctloutput: ctl %s returned "
		"len (%lu) > sopt_valsize (%lu)\n",
			kcb->kctl->name, len,
			sopt->sopt_valsize);
socket_lock(so, 0);
if (error == 0) {
	if (data != NULL)
		error = sooptcopyout(sopt, data, len);		// (d) If (c) succeeded,
	else							//     then the data buffer
		sopt->sopt_valsize = len;			//     is copied out to
}								//     userspace.

Este código hace lo siguiente:

  1. Asigna un búfer de heap del kernel para el parámetro data de getsockopt, sin especificar el indicador M_ZERO para poner a cero los bytes asignados.
  2. Copia los datos de getsockopt desde el espacio de usuario usando sooptcopyin, llenando el búfer de datos recién asignado. Se supone que este copyin sobrescribe por completo los datos asignados, razón por la cual no se necesitaba el indicador M_ZERO. Sin embargo, el valor de retorno de sooptcopyin no se comprueba, lo que significa que es posible que el copyin haya fallado, dejando datos no inicializados en el búfer. El copyin podría fallar si, por ejemplo, el programa pasara una dirección no asignada a getsockopt.
  3. El código entonces llama a la implementación real de getsockopt para este socket de control del kernel. Esta implementación debería procesar el búfer de entrada, posiblemente modificándolo y acortándolo, y devolver un código de resultado. Sin embargo, la implementación es libre de asumir que el búfer proporcionado ya ha sido inicializado (ya que teóricamente proviene del espacio de usuario), y por lo tanto varias implementaciones no modifican el búfer en absoluto. La función NECP necp_ctl_getopt, por ejemplo, simplemente devuelve 0 sin procesar el búfer de datos en absoluto.

Por lo tanto, al especificar una dirección de datos no asignada a getsockopt, podemos hacer que se asigne un búfer de heap de tamaño controlado, impedir que el contenido de ese búfer sea inicializado, y luego alcanzar una llamada a sooptcopyout que intenta escribir ese búfer de vuelta a la dirección no asignada. Todo lo que necesitamos para que el copyout tenga éxito es reasignar esa dirección entre las llamadas a sooptcopyin y sooptcopyout. Si podemos hacer eso, entonces filtraremos datos no inicializados del heap del kernel al espacio de usuario.

Resulta que esta es una carrera bastante fácil de ganar. Durante las pruebas en mi Macbook Pro de 2015, el número medio de intentos para ganar la carrera nunca fue superior a 600, y la mediana nunca fue superior a 5. En iOS 10.1.1 en un iPhone 7 la carrera era aún más fácil de ganar, normalmente no requería más de 2 intentos. (Estas pruebas se realizaron con DEBUG desactivado, ya que los printfs ralentizan drásticamente el exploit.)

Uso

Para compilar, ejecuta make. Consulta la parte superior del Makefile para las distintas opciones de compilación.

Ejecuta el exploit especificando el tamaño de fuga objetivo en la línea de comandos:

root@kitploit:~
$ sudo ./ctl_ctloutput-leak 128
000000:  ef be ad de ef be ad de  00 00 00 00 00 00 00 00
000010:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000020:  00 00 00 00 00 00 00 00  01 00 00 00 40 80 00 00
000030:  de 28 45 00 04 00 00 00  a0 ff 4a 26 80 ff ff ff
000040:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000050:  08 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000060:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
000070:  00 00 00 00 00 00 00 00  ef be ad de ef be ad de

Cronología

Informé de este problema a Apple el 7 de octubre de 2017. Se le asignó CVE-2017-13868. Apple corrigió los problemas en macOS 10.13.2 y iOS 11.2.

Licencia

El código de ctl_ctloutput-leak se publica en el dominio público. Como cortesía, pido que si haces referencia o usas parte de este código, me lo atribuyas a mí.

Descargar herramienta
  • Finalmente, si la implementación real de getsockopt no devuelve un error, ctl_ctloutput llama a sooptcopyout para copiar el búfer de datos de vuelta al espacio de usuario.