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

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

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

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

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

Категории

Все категории
Loading categories
freebsd-dirent-info-leak-bugs — CVE-2020-25578 и CVE-2020-25579: некоторые ошибки утечки информации в FreeBSD, найденные мной в 2020 году. | Kitploit
Инструменты/GitHubGitHub/farazsth98/freebsd-dirent-info-leak-bugs
Криминалистика памятиАнализ уязвимостейЭксплуатацияСбор информацииАнализ Бинарных Файлов
GitHubfarazsth98/freebsd-dirent-info-leak-bugs

freebsd-dirent-info-leak-bugs

CVE-2020-25578 и CVE-2020-25579: некоторые ошибки утечки информации в FreeBSD, найденные мной в 2020 году.

Репозиторий

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться
7225 лет назадЕщё не проверено

Как я нашел баги?

  1. Случайно решил провести аудит файловых систем FreeBSD
  2. Провел небольшое исследование и обнаружил, что используемая по умолчанию файловая система — это комбинация FFS и UFS
  3. Потратил некоторое время на аудит ufs_create и не нашел багов
  4. Перешел сюда и просмотрел историю коммитов функций файловой системы UFS
  5. Заметил этот коммит об утечке информации через выравнивающие байты в объектах struct dirent, выделенных в стеке
  6. Проанализировал патч и обнаружил, что исправление для msdosfs_readdir неполное. Они исправили один экземпляр ошибки, но не второй.
  7. Написал PoC, чтобы подтвердить, что могу извлечь 3 байта из выравнивания. Затем начал искать варианты.
  8. Нашел варианты в mqueuefs, autofs, smbfs и tmpfs, которые позволяют извлечь полный 8-байтовый указатель. Написал PoC для подтверждения.

Исходная ошибка

Как упоминалось выше, исходная ошибка, которую я нашел, находилась в msdosfs_readdir во время анализа патча для приведенного выше коммита.

Основной поток вызова readdir в FreeBSD выглядит следующим образом:

root@kitploit:~
#include <dirent.h>

int main(void) {
    struct dirent *dp;
    DIR *dirp;

    dirp = opendir("./somedir");
    dp = readdir(dirp);
}

В зависимости от файловой системы, в которой находится somedir, может быть вызвана любая из множества функций *_readdir в ядре FreeBSD.

Вышеупомянутый патч добавляет функцию под названием dirent_terminate, которая должна вызываться перед возвратом объекта struct dirent в пользовательское пространство (часто это делается с помощью функции uiomove). Эта функция обнуляет выравнивающие байты, а также оставшиеся байты в поле d_name структуры. Определение struct dirent находится здесь.

Глядя на патч, в строке 1562, можно увидеть, что dirent_terminate вызывается с переменной dirbuf в качестве аргумента. После этого uiomove вызывается для копирования содержимого dirbuf обратно в пользовательское пространство. Однако обратите внимание, что эти строки кода находятся внутри блока этого оператора if. Комментарий над этим оператором if объясняет, что эта ветвь выполняется только при вызове readdir на корне файловой системы MSDOS, поэтому мы можем просто пропустить этот оператор if, вызвав readdir в любой поддиректории за пределами корня файловой системы.

Далее мы видим еще один вызов uiomove в строке 1691. Однако, внимательно читая код, вы увидите, что в этом случае dirent_terminate не вызывается, что означает, что выравнивающие байты останутся неинициализированными. К сожалению, поле d_name было обнулено в начале этой функции (здесь), поэтому мы не можем получить большую утечку.

PoC

Сначала у меня не было USB-накопителя, поэтому мне пришлось придумать способ смонтировать файловую систему MSDOS. Следующее работает:

root@kitploit:~
$ dd if=/dev/zero of=test.img bs=512 count=256000
$ sudo mdconfig -a -t vnode -f test.img
$ sudo newfs_msdos -s 131072000 /dev/md1 # My mdconfig returned md1
$ mkdir ./temp
$ sudo mount -t msdosfs /dev/md1 ./temp
$ mkdir ./temp/test_dir

PoC можно найти в файле original_poc.c. Просто скомпилируйте с помощью clang и запустите из той же директории, что и команды выше, и вы увидите выведенные утекшие байты.

Варианты

Я начал искать варианты этой ошибки. Кажется, я просто использовал grep для uiomove\(&.*,, что дало около 15-20 результатов, и я вручную проверил их все. К сожалению, ни один из вариантов не существует в FreeBSD по умолчанию (файловые системы должны быть вручную включены / скомпилированы в ядро). Функции с вариантами следующие:

  1. mqfs_readdir
  2. tmpfs_dir_getdotdent
  3. tmpfs_dir_getdotdotdent
  4. smbfs_readvdir
  5. autofs_readdir_one

Ошибка абсолютно одинакова во всех этих функциях, поэтому я рассмотрю только mqfs_readdir.

  1. Во-первых, структура struct dirent entry выделяется в стеке
  2. Затем вызывается dirent_terminate для обнуления выравнивающих байтов и полей d_name структуры
  3. Наконец, вызывается vfs_read_dirent. Эта функция вызовет uiomove для копирования структуры в пользовательское пространство

Пока все выглядит хорошо, не так ли? Не обязательно. Мы должны убедиться, что все поля структуры инициализированы. Если вы внимательно посмотрите на код, вы увидите, что поле d_off остается неинициализированным. Тип этого поля — off_t, что по сути является int64_t. Когда структура копируется в пользовательское пространство, мы получаем неинициализированные данные в этом поле.

PoC

Этот же PoC будет работать для всех вариантов, вам просто нужно запустить его на другой файловой системе. Для mqueuefs сделайте следующее (требуется, чтобы mqueuefs была включена / скомпилирована в ядро):

root@kitploit:~
$ mkdir ./temp
$ sudo mount -t mqueuefs null ./temp

Сам PoC можно найти в файле variants_poc.c. Просто скомпилируйте с помощью clang и запустите из той же директории, что и команды выше. Вы увидите выведенные указатели ядра (предположительно, один указатель стека и один указатель секции кода/кучи, я не проверял).

Скачать инструмент