Хакнутый Syslog на страже порядка Will Barrent & Andrey Matveev Xakep, номер #067, стр. 067-052-1 (andrushock@real.xakep.ru) & (barrent@hotbox.ru) Защищаем систему журналирования Мы так много пишем о взломе Unix-like систем, что ты уже, наверное, наизусть выучил несколько стандартных "ScriptKiddies" схем: изучение сервисов системы, поиск багов, компиляция эксплойта, рутшелл; или: получение локальных привилегий, изучение системы, поиск уязвимостей, рутшелл. Сегодня предлагаю все наши усилия направить на то, чтобы запутать взломщика еще на стадии изучения системы и направить его по заведомо ложному пути, не предоставляя достоверных сведений о конфигурации основных сервисов. Для этого мы самостоятельно изменим некоторые функции ядра. Разборки с сисколами Для начала нужно научиться скрывать куски файловой системы, проще говоря, создавать "невидимые" директории. Это очень полезная фишка, и она не раз тебе пригодится. Обычно такие вещи делает сам взломщик, пытающийся закрепиться на порутанной тачке. Теперь же мы поменяемся с ним местами. Итак, пораскинем мозгами, что же нужно сделать... Самое простое, что приходит в голову - расковырять исходник утилиты ls и внести туда необходимые изменения. Но это как раз и не входит в наши планы: во-первых, кроме ls существует масса других способов посмотреть содержимое директории, например, find, а во-вторых, это не элитно ;). Мы модифицируем ядро! Что-то мне подсказывает, что твои отношения с внутренностями ядра FreeBSD носят далеко не интимный характер, поэтому постараюсь растолковать все поподробнее. Все программы, показывающие содержимое директории, используют одну и ту же системную функцию getdirentries(2), которая специфицирована следующим образом: int getdirentries(int fd, char *buf, int nbytes, long *basep), где fd - файловый дескриптор, buf - указатель на буфер, куда складываются записи с содержимым директории, nbytes - размер буфера, basep - текущая позиция указателя. Таким образом, мы можем занести в буфер сведения о содержимом директории в виде массива структур dirent (сокращение от "directory entry"). Чтобы получить описание этой структуры, давай посмотрим на системный заголовочный файл /usr/include/sys/dirent.h: Структура dirent в комментариях struct dirent { __u_int32_t d_fileno; /* номер файла */ __u_int16_t d_reclen; /* длина записи */ __u_int8_t d_type; /* тип файла */ __u_int8_t d_namlen; /* длина имени файла */ char d_name[MAXNAMLEN + 1]; /* имя файла */ } Со значением константы MAXNAMLEN все просто: она определена в этом же файле и равна 255. Все записи в буфере не обязательно идут подряд, часто между ними бывают промежутки. Именно поэтому нам необходима длина записи d_reclen. Зачем так хитро сделано, знают только писавшие BSD студенты-наркоманы из института Berkeley ;). Теперь пора посмотреть на код этого вызова. Берем в зубы любимый текстовый редактор (фанаты лямбда-исчисления и Лиспа могут использовать Emacs) и открываем файл /usr/src/sys/kern/vfs_syscalls.c, в котором свалены в кучу все системные вызовы, связанные с файловой системой. Находим вот это место: int getdirentries(p, uap) struct proc *p; register_t struct getdirentries_args *uap; |