Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
ctl_ctloutput-leak — CVE-2017-13868: Divulgazione di informazioni su dati non inizializzati dell'heap del kernel in XNU. | Kitploit
Strumenti/GitHubGitHub/bazad/ctl_ctloutput-leak
Memory ForensicsAnalisi delle VulnerabilitàExploitRaccolta InformazioniBinary Exploitation
GitHubbazad/ctl_ctloutput-leak

ctl_ctloutput-leak

CVE-2017-13868: Divulgazione di informazioni su dati non inizializzati dell'heap del kernel in XNU.

Vedi Repository
275128 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

ctl_ctloutput-leak

La funzione ctl_ctloutput in macOS High Sierra 10.13 ignora il valore di ritorno di una chiamata a sooptcopyin, il che apre una finestra di race condition per divulgare dati non inizializzati dell'heap del kernel allo spazio utente. ctl_ctloutput-leak è una prova di concetto che tenta di innescare questa fuga di informazioni. Lo sfruttamento richiede privilegi di root.

Questo exploit è stato confermato funzionante su macOS High Sierra 10.13.1 Beta 17B25c e iOS 10.1.1 14B100 (sotto mach_portal).

La vulnerabilità: CVE-2017-13868

Ecco la parte rilevante di ctl_ctloutput su macOS High Sierra 10.13:

if (sopt->sopt_valsize && sopt->sopt_val) {
	MALLOC(data, void *, sopt->sopt_valsize, M_TEMP,	// (a) data viene allocato
		M_WAITOK);					//     senza M_ZERO.
	if (data == NULL)
		return (ENOMEM);
	/*
	 * 4108337 - copia dei dati utente nel caso in cui il
	 * controllo del kernel ne abbia bisogno
	 */
	error = sooptcopyin(sopt, data,				// (b) sooptcopyin() viene
		sopt->sopt_valsize, sopt->sopt_valsize);	//     chiamata per riempire
}								//     il buffer; il valore di
len = sopt->sopt_valsize;					//     ritorno viene ignorato.
socket_unlock(so, 0);
error = (*kctl->getopt)(kctl->kctlref, kcb->unit,		// (c) L'implementazione di
		kcb->userdata, sopt->sopt_name,			//     getsockopt() viene
			data, &len);				//     chiamata per elaborare
if (data != NULL && len > sopt->sopt_valsize)			//     il 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) Se (c) ha avuto
	else							//     successo, il buffer
		sopt->sopt_valsize = len;			//     dati viene copiato
}								//     nello spazio utente.

Questo codice fa quanto segue:

  1. Alloca un buffer nell'heap del kernel per il parametro data di getsockopt, senza specificare il flag M_ZERO per azzerare i byte allocati.
  2. Copia i dati di getsockopt dallo spazio utente usando sooptcopyin, riempiendo il buffer dati appena allocato. Questo copyin dovrebbe sovrascrivere completamente i dati allocati, motivo per cui il flag M_ZERO non era necessario. Tuttavia, il valore di ritorno di sooptcopyin non viene controllato, il che significa che è possibile che il copyin sia fallito, lasciando dati non inizializzati nel buffer. Il copyin potrebbe fallire se, ad esempio, il programma passasse un indirizzo non mappato a getsockopt.
  3. Il codice chiama poi la vera implementazione di getsockopt per questo socket di controllo del kernel. Questa implementazione dovrebbe elaborare il buffer di ingresso, eventualmente modificandolo e accorciandolo, e restituire un codice di risultato. Tuttavia, l'implementazione è libera di presupporre che il buffer fornito sia già stato inizializzato (poiché in teoria proviene dallo spazio utente), e quindi diverse implementazioni non modificano affatto il buffer. La funzione NECP necp_ctl_getopt, ad esempio, restituisce semplicemente 0 senza elaborare affatto il buffer dati.
  4. Infine, se la vera implementazione di getsockopt non restituisce un errore, ctl_ctloutput chiama sooptcopyout per copiare il buffer dati di nuovo nello spazio utente.

Quindi, specificando un indirizzo dati non mappato a getsockopt, possiamo causare l'allocazione di un buffer nell'heap di dimensione controllata, impedire che il contenuto di quel buffer venga inizializzato, e poi raggiungere una chiamata a sooptcopyout che tenta di scrivere quel buffer di nuovo all'indirizzo non mappato. Tutto ciò che dobbiamo fare perché il copyout abbia successo è rimappare quell'indirizzo tra le chiamate a sooptcopyin e sooptcopyout. Se riusciamo a farlo, allora faremo trapelare dati non inizializzati dell'heap del kernel nello spazio utente.

Si scopre che questa è una race condition piuttosto facile da vincere. Durante i test sul mio Macbook Pro del 2015, il numero medio di tentativi per vincere la race non è mai stato superiore a 600, e la mediana non è mai stata superiore a 5. Su iOS 10.1.1 su un iPhone 7 la race era ancora più facile da vincere, richiedendo in genere non più di 2 tentativi. (Questi test sono stati condotti con DEBUG disattivato, poiché le printf rallentano drasticamente l'exploit.)

Utilizzo

Per compilare, esegui make. Vedi l'inizio del Makefile per varie opzioni di compilazione.

Esegui l'exploit specificando la dimensione della fuga da tentare sulla riga di comando:

$ 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

Cronologia

Ho segnalato questo problema ad Apple il 7 ottobre 2017. Gli è stato assegnato CVE-2017-13868. Apple ha corretto il problema in macOS 10.13.2 e iOS 11.2.

Licenza

Il codice di ctl_ctloutput-leak è rilasciato nel pubblico dominio. Per cortesia chiedo che, se fai riferimento o usi parte di questo codice, me lo attribuisca.

Scarica lo strumento