Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
ctl_ctloutput-leak — CVE-2017-13868: Утечка информации из неинициализированных данных кучи ядра в XNU. | Kitploit
Инструменты/GitHubGitHub/bazad/ctl_ctloutput-leak
Криминалистика памятиАнализ уязвимостейЭксплуатацияСбор информацииЭксплуатация Бинарных Файлов
GitHubbazad/ctl_ctloutput-leak

ctl_ctloutput-leak

CVE-2017-13868: Утечка информации из неинициализированных данных кучи ядра в XNU.

Репозиторий
27528 лет назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

ctl_ctloutput-leak

Функция ctl_ctloutput в macOS High Sierra 10.13 игнорирует возвращаемое значение вызова sooptcopyin, что открывает окно состояния гонки для утечки неинициализированных данных кучи ядра в пользовательское пространство. ctl_ctloutput-leak — это proof-of-concept эксплойт, который пытается вызвать эту утечку информации. Для эксплуатации требуются права root.

Этот эксплойт подтверждён работоспособностью на macOS High Sierra 10.13.1 Beta 17B25c и iOS 10.1.1 14B100 (под mach_portal).

Уязвимость: CVE-2017-13868

Вот релевантная часть ctl_ctloutput на 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.

Этот код делает следующее:

  1. Выделяет буфер кучи ядра для параметра data в getsockopt без указания флага M_ZERO для обнуления выделенных байтов.
  2. Копирует данные getsockopt из пользовательского пространства с помощью sooptcopyin, заполняя только что выделенный буфер. Это копирование должно полностью перезаписать выделенные данные, поэтому флаг M_ZERO не требовался. Однако возвращаемое значение sooptcopyin не проверяется, что означает возможность сбоя копирования, оставляя в буфере неинициализированные данные. Копирование может завершиться неудачей, если, например, программа передала в getsockopt неотображённый адрес.
  3. Затем код вызывает реальную реализацию getsockopt для этого сокета управления ядра. Эта реализация должна обработать входной буфер, возможно, изменить его и укоротить, и вернуть код результата. Но реализация может полагать, что переданный буфер уже инициализирован (поскольку теоретически он приходит из пользовательского пространства), и поэтому многие реализации вообще не изменяют буфер. Например, функция NECP necp_ctl_getopt просто возвращает 0, не обрабатывая буфер данных.

Таким образом, указав неотображённый адрес данных в getsockopt, мы можем заставить выделить буфер кучи контролируемого размера, предотвратить инициализацию содержимого этого буфера, а затем вызвать sooptcopyout, который попытается записать этот буфер обратно по неотображённому адресу. Всё, что нам нужно для успешного копирования, — повторно отобразить этот адрес в промежутке между вызовами sooptcopyin и sooptcopyout. Если мы сможем это сделать, произойдёт утечка неинициализированных данных кучи ядра в пользовательское пространство.

Оказывается, эту гонку довольно легко выиграть. Во время тестов на моём Macbook Pro 2015 года среднее количество попыток для победы в гонке никогда не превышало 600, а медиана — 5. На iOS 10.1.1 на iPhone 7 гонка выигрывалась ещё легче, обычно за не более чем 2 попытки. (Тестирование проводилось без DEBUG, так как printfs сильно замедляют эксплойт.)

Использование

Для сборки выполните make. См. начало Makefile для различных опций сборки.

Запустите эксплойт, указав целевой размер утечки в командной строке:

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

Хронология

Я сообщил об этой проблеме Apple 7 октября 2017 года. Ей был присвоен номер CVE-2017-13868. Apple исправила уязвимость в macOS 10.13.2 и iOS 11.2.

Лицензия

Код ctl_ctloutput-leak выпущен в общественное достояние. В порядке вежливости я прошу указывать меня как автора, если вы ссылаетесь на этот код или используете его.

Скачать инструмент
  • Наконец, если реальная реализация getsockopt не возвращает ошибку, ctl_ctloutput вызывает sooptcopyout для копирования буфера данных обратно в пользовательское пространство.