RFC (Request for Comments, Запрос на комментарии) - серия документов, публикуемая сообществом исследователей и разработчиков, руководствующихся практическими интересами, в которой описывается набор протоколов и обобщается опыт функционирования Интернет.
PAM'ятка матерого юниксоида. Модули аутентификации на все случаи жизни [2009]
Сегодня система подключаемых модулей аутентификации PAM поставляется в
комплекте практически с любым UNIX'ом. Но немногие знают, что с ее помощью можно
получить просто безграничный контроль над юзерами и способами входа в систему. К
примеру, организовать аутентификацию по отпечаткам пальцев и USB-ключам,
поместить пользователей в chroot-окружение и защитить хост от брутфорс-атак.
Введение в PAM
Мы уже рассматривали PAM (Pluggable Authentication
Modules) в одном из предыдущих выпусков журнала (речь идет о статье
«Система безопасности PAM изнутри», опубликованной в февральском номере ][ за
2006 год, - Прим.ред.) Для тех, кто пропустил, объясню в двух словах. Система
подключаемых модулей аутентификации представляет собой специальную модульную
библиотеку, возможности которой может использовать любое приложение,
осуществляющее аутентификацию и/или авторизацию пользователей. Хороший пример -
системная утилита /bin/login, отвечающая за вход пользователя в ОС. До появления
PAM она должна была сама находить пользователя в базе /etc/passwd и сверять хеш
введенного им пароля с хранящимся в базе хешем. Сегодня все эти действия
осуществляет PAM, а /bin/login только вызывает ее из своего кода и проверяет
возвращаемый статус. Но это пустяк, потому что настоящая мощь PAM заключается в
ее модульности, благодаря которой можно легко изменить используемый метод
аутентификации (хочешь входить по отпечаткам пальцев - нет ничего проще!) и
авторизации (пользователь должен уйти в chroot после логина - легко!) путем
редактирования всего лишь одного конфигурационного файла.
PAM использует закрепленные за приложениями конфиги для получения информации
о том, какие модули следует использовать для аутентификации/авторизации
пользователя. Все они располагаются в каталоге /etc/pam.d. Рассмотрим пример
одного из них - файл /etc/pam.d/login, закрепленный за утилитой /bin/login:
# vi /etc/pam.d/login
auth sufficient pam_self.so no_warn auth include
system account requisite pam_securetty.so account required
pam_nologin.so account include system session include system password
include system
Формат конфигурационного файла PAM был подробно описан в вышеназванной
статье, поэтому сейчас я скажу только о том, что существует четыре стека
PAM-модулей, модули каждого из которых вызываются поочередно. Первый столбец как
раз и указывает на используемый стек:
auth - сюда помещаются модули, проводящие аутентификацию;
account - модули, определяющие, можно ли пользователю зайти;
session - выделение ресурсов для пользователей (например, монтирование
домашнего каталога);
password - модули, обеспечивающие обновление учетной записи пользователя и
его пароля (этот стек использует команда /usr/bin/passwd).
Второй столбец - это флаг, который определяет, что делать в случае
(не)успешной отработки модуля. Третий столбец - имя модуля, четвертый - его
аргументы (также модуль может иметь конфигурационный файл, располагающийся в
каталоге /etc/security). Обрати внимание на особую директиву include, которая не
вписывается в общий синтаксис и позволяет подключать другой конфиг (чтобы не
дублировать содержимое). В нашем случае для каждого стека указан включаемый файл
system (также расположенный в каталоге /etc/pam). Это специфика FreeBSD;
Linux-дистрибутивы Debian и Ubuntu используют для тех же целей файлы common-*
(common-auth, common-session и т.д.), а Gentoo и Mandriva - system-*. В одном из
этих файлов ты обязательно найдешь строку с запуском PAM-модуля, ответственного
за поиск пользователя в базе /etc/passwd и сравнение хешей:
Уберем ее, и двери захлопнутся, больше в систему не войдешь. А теперь немного
магии. Как я уже говорил, изменяя несколько строк в конфигурационных файлах, мы
можем сделать с методом аутентификации и авторизации все, что угодно (в рамках
возможностей доступных модулей, конечно). Возьмем, к примеру, файл
/etc/pam.d/su, стек модулей auth которого выглядит так:
# vi /etc/pam.d/su
auth sufficient pam_rootok.so no_warn auth sufficient
pam_self.so no_warn auth requisite pam_group.so no_warn group=wheel root_only
fail_safe auth include system
Сначала вызывается модуль pam_rootok, который проверяет UID пользователя,
запустившего приложение, и успешно завершается, если он равен нулю. Все
остальные модули в этом случае пропускаются (флаг sufficient). Если первый
модуль завершился неудачно (пользователь не root), стартует модуль pam_self,
который проверяет, совпадает ли UID вызывающего пользователя с UID'ом
пользователя, для которого осуществляется авторизация. Если это так, остальные
модули не запускаются (поясню на примере: если пользователь vasya делает «su
vasya», модуль возвращает «да», и su выполняется успешно, не спрашивая пароля).
Далее с помощью модуля pam_group происходит проверка на членство вызывающего
пользователя в группе wheel, и, если это не так, пользователя отфутболивают
(флаг requisite). В конце выполняются модули, помещенные в стек auth в файле
/etc/pam.d/system (вызов pam_unix, сверяющего пароль).
Приведу несколько примеров. Хочешь сделать так, чтобы su не смог пользоваться
никто? Тогда удали все эти строки и впиши на их место «auth sufficient
pam_deny.so». Модуль pam_deny - это аналог команды false. Он всегда выполняется
неудачно, поэтому su не сможет воспользоваться ни один пользователь, включая
root. Антипод ему - модуль pam_permit, всегда исполняющийся удачно. Запиши в
/etc/pam.d/su строку «auth sufficient pam_permit.so», и su смогут использовать
все, кому не лень, не вводя пароль. Но все это игрушки в сравнении с тем, что
нас ждет дальше.
USB-ключи и отпечатки пальцев
Стандартная комплектация Linux-PAM и OpenPAM уже включает в себя несколько
модулей аутентификации, которые следует помещать в стек auth. Это, например,
модуль pam_guest, который позволяет использовать для аутентификации специальные
гостевые аккаунты, pam_ftpusers, впускающий пользователя только если его имя
присутствует в файле /etc/ftpusers, или pam_securetty, разрешающий
суперпользователю логиниться лишь с терминалов, которые помечены как secure в
файле /etc/ttys (или просто перечислены в файле /etc/securetty в Linux). Все они
задействованы в системах аутентификации различных приложений, но для нас особого
интереса не представляют.
В большинстве систем среди штатных модулей есть такие, которые позволяют
производить аутентификацию с помощью USB-ключей, смарт-карт и даже отпечатков
пальцев. Возьмем, к примеру, модуль pam_usb. Он считывает ключ с USB-брелка и на
его основе делает вывод о правомочности пользователя войти в систему. Вставил
брелок - вошел, вынул - система заблокирована. Интересно? Тогда вперед.
В портах FreeBSD pam_usb нет, поэтому все описанное ниже пригодится только
пользователям Linux (примеры даны для Debian/Ubuntu). Установим pam_usb и нужные
для его настройки утилиты:
# apt-get install libpam-usb pamusb-tools
Подключим USB-брелок и запустим pamusb-conf, чтобы добавить флешку в
конфигурационный файл:
# pamusb-conf --add-device любое_имя
Утилита попросит выбрать нужное устройство, раздел, используемый для хранения
ключа, и спросит о том, следует ли заносить устройство в конфигурационный файл.
Следует ответить «да», то есть «y».
Добавим пользователей, которые смогут войти в систему с помощью этого
USB-брелка:
# pamusb-conf --add-user root
Выбираем уже добавленный в конфиг брелок, нажимаем «y» и проверяем
правильность произведенных настроек:
# pamusb-check root
На этом настройка pam_usb завершена. Осталось добавить pam_usb в стек auth
необходимых приложений и насладиться результатом. Не будем утомлять себя
редактированием всех конфигурационных файлов PAM, закрепленных за каждым
приложением, и внесем изменения во включаемый файл /etc/pam.d/common-auth. Для
этого откроем его в редакторе и перед строкой, содержащей имя pam_unix.so,
добавим строку «auth sufficient pam_usb.so». Теперь любое приложение,
конфигурационный файл PAM которого включает в себя common-auth, будет пытаться
аутентифицировать пользователя с помощью ключа, записанного на USB-брелок, и
только в случае неудачи запросит пароль.
С отпечатками пальцев дело обстоит еще проще. Уже год как существует
замечательный проект fprint (www.reactivated.net/fprint/wiki/Main_Page), смысл которого в
разработке унифицированной библиотеки для работы с различными сканерами
отпечатков (подключаемых к USB-порту) и набора утилит для работы с ней. Кроме
прочего, в комплект утилит входит и нужный нам модуль pam_fprint.
Связка libfprint и pam_fprint уже включена по умолчанию в новые релизы Ubuntu
и Fedora и доступна через систему портов FreeBSD
(/usr/ports/security/pam_fprint). Поэтому вручную устанавливать ничего не
потребуется, а для настройки необходимо выполнить всего два шага. Первый -
создать слепок пальца с помощью следующей команды:
$ pam_fprint_enroll --enroll-finger 6
Цифра 6 означает большой палец правой руки. Система fprint нумерует пальцы
обеих рук слева направо, от одного до десяти, так что 1 - это мизинец левой
руки, а 8 - средний палец правой.
Второй шаг. Добавить pam_fprint в стек auth необходимых приложений. Для этого
открываем уже знакомый нам /etc/pam.d/common-auth (или /etc/pam.d/system во
FreeBSD) и вставляем в начало строку «auth sufficient pam_fprint.so». При
необходимости указываем флаг required вместо sufficient, чтобы без отпечатка
вообще нельзя было войти (но не рекомендую этого делать; современные
потребительские системы распознавания отпечатков пальцев далеки от
совершенства).
Черные списки, беспарольные пользователи и альтернативные базы паролей
Процесс помещения пользователей в черные и белые списки до появления PAM
обычно превращался в какое-то шаманство, сопровождаемое многочисленными
экспериментами, а конечная цель достигалась за счет использования костылей.
Сегодня пользователям и системным администраторам живется намного легче:
существует несколько PAM-модулей, позволяющих реализовать блэклистинг и
автоматизацию входа пользователя в систему.
Возьмем, к примеру, модуль pam_listfile (доступный только в пакете
Linux-PAM). С его помощью легко настроить систему беспарольного входа
пользователей. Просто добавь следующую строку в конфигурационный PAM-файл
нужного приложения и запиши беспарольных пользователей в файл
/etc/users.allow:
Причем, в качестве значения опции item можно использовать также tty, user,
rhost, ruser, group, shell. Это дает возможность запрещать/позволять вход не
только на основе имен пользователей, но и имени терминала, с которого происходит
вход, имени удаленного хоста/пользователя, группы и т.д. Другой похожий
модуль называется pam_access. Он использует более гибкий и сложный формат
конфигурационного файла и предназначен для помещения в стек account (проверка,
может ли пользователь войти, осуществляется уже после того, как он представился,
то есть ввел правильные логин и пароль). Модуль удобно использовать в связке с
ssh для выставления за дверь неугодных. Для этого надо поместить модуль в стек
account: «account required pam_access.so» и создать файл
/etc/security/access.conf примерно с таким содержимым:
# vi /etc/security/access.conf
+ : ALL : 192.168.1 + : good_guy : ALL - : ALL : ALL
Это означает, что получить доступ через ssh могут все из подсети 192.168.1.0
и парень с логином good_guy. Остальные идут лесом. На просторах всемирной
паутины можно найти и более простой модуль pam_lockout (ostatic.com/pam-lockout). Он позволяет перечислить имена
неугодных пользователей прямо в конфигурационном файле PAM: «auth requisite
pam_lockout.so user=bad_guy».
Для организации беспарольной системы входа пользователей с консоли удобно
использовать модуль pam_alredyloggedin (ilya-evseev.narod.ru/posix/pam_alreadyloggedin). Он
запрашивает пароль только в случае, если пользователь еще не залогинился в
другой консоли (идеальное решение, когда используешь сразу несколько консолей,
переключаясь между ними с помощью <Alt+Fx>). Для настройки просто помещаем
следующие две строки на самый верх стека auth (в начало файла):
Возвращаясь к спискам пользователей, нельзя не упомянуть о довольно
интересном модуле pam_pwdfile (cpbotha.net/software/pam_pwdfile). Его задача - предоставить
приложениям альтернативную базу пользователей и паролей, которую они смогут
использовать вместо системного файла /etc/passwd. Это своего рода плагин для тех
приложений и демонов, которые не способны вести подобную базу самостоятельно.
Яркий пример: минималистичный FTP-сервер vsftpd. Запусти его от
непривилегированного пользователя, и клиенты не смогут получить доступ к
серверу. Выход: использовать pam_pwdfile, который будет вести отдельный файл
логинов и паролей специально для vsftpd. Для использования достаточно добавить
следующие две строки в начало /etc/pam.d/vsftpd:
И добавить пользователей в базу с помощью утилиты chpwdfile
(eclipse.che.uct.ac.za/chpwdfile) – либо руками заполнив его
строками вида: «логин:MD5-хеш-пароля». На закуску я оставил вкуснейший модуль
pam_abl (hexten.net/pam_abl), самостоятельно ведущий и обновляющий
черные списки пользователей-брутфорсеров. Это отличная портабельная между
UNIX'ами альтернатива блэклистингу на основе правил брандмауэра. Модуль
вычисляет тех, кто слишком настойчиво пытается пройти аутентификацию, и
блокирует аккаунт или вызывающий хост на определенное время. Для настройки
открываем /etc/pam.d/sshd и добавляем в начало строку «auth required pam_abl.so
config=/etc/security/pam_abl.conf». По умолчанию модуль настроен на блокировку
аккаунта. Это правильно, если твой хост подвергся распределенному брутфорсу, но
вызовет проблемы для легальных пользователей, которые попытаются войти в систему
сразу после проведения безуспешной попытки «взлома». В обычной ситуации для
борьбы со скрипт-кидди лучше настроить блокировку на основе имени вызывающего
хоста. Поэтому открываем файл /etc/security/pam_abl.conf и пишем в него:
# vi /etc/security/pam_abl.conf
// Черный список host_db=/var/lib/abl/hosts.db //
Блокировка сроком на два дня host_purge=2d // Блокировка любого хоста
после 10 неудачных попыток за 1 час host_rule=*:10/1h
Пространства имен, автомонтирование, chroot
Как было сказано выше, стек PAM-модулей session предназначен для модулей,
подготавливающих окружение для только что вошедшего пользователя. Это может быть
любое действие, связанное с выделением или ограничением доступных пользователям
ресурсов. Наиболее показательный пример - модуль pam_limits из пакета Linux-PAM
(но не OpenPAM). Он ограничивает ресурсы приложений вошедшего пользователя на
основе конфигурационного файла /etc/security/limits.conf.
Если говорить о сторонних разработках, то в первую очередь следует упомянуть
полезнейший модуль pam_chroot (sourceforge.net/projects/pam-chroot), единственная задача
которого - помещать вошедших пользователей в песочницу. Модуль незаменим, когда
требуется организация shell-, ftp- или какого-либо другого хостинга и любых
конфигураций, предусматривающих вход в систему сомнительных лиц. Модуль очень
прост в использовании. Для настройки достаточно выполнить две команды:
Все, теперь vasya, вошедший с помощью ssh-клиента, будет помещен в каталог
/usr/chroot и не сможет из него выбраться. На втором месте в рейтинге – модуль
pam_mkhomedir из пакета Linux-PAM, просто создающий домашний каталог для
прошедшего аутентификацию пользователя. Поначалу полезность модуля может
показаться сомнительной, но администраторы гетерогенных сетей, состоящих
вперемешку из машин Windows/UNIX, ценят его дороже своих потертых джинсов. Дело
в том, что в таких сетях принято использовать Active Directory для хранения
учетных данных пользователей, коих может быть не одна сотня. Вместо того чтобы
создавать многочисленные каталоги для каждого пользователя, зарегистрированного
в AD, они просто выполняют приведенную ниже команду на всех UNIX-машинах и
удаляются в серверную порезаться в «контру»:
Модуль обычно используется в связке с модулем pam_winbind, осуществляющим
аутентификацию в AD, или с pam_ldap, аутентифицирующим пользователей, используя
сервер LDAP.
Почетное третье место занимает завязанный на возможностях Linux-ядра модуль
pam_namespace. Его задача - незаметное создание изолированной копии
общедоступного каталога (/tmp, например) для каждого пользователя. Другими
словами, вошедший пользователь получает доступ только к своей версии каталога
/tmp и не видит файлов других пользователей. Нужно это для борьбы с методами
взлома, основанными на использовании состояний гонок (race condition),
символических ссылок и просто для ограждения возможного нарушителя от любых
файлов легальных пользователей.
Модуль использует простой конфигурационный файл /etc/security/namespace.conf
для принятия решения о том, какие каталоги должны быть подменены. Вот простая
инструкция для изолирования каталога /tmp:
Результат: индивидуальный каталог /tmp для каждого пользователя, за
исключением root'а (на самом деле файлы будут храниться в каталоге
/tmp-inst/юзер). Конфигурационная строка для изолирования каталога /home (чтобы
злоумышленник не смог увидеть и получить доступ к каталогам пользователей)
должна выглядеть так:
$HOME $HOME/$USER.inst/ user root
Автоматизированная проверка паролей на стойкость
Плагины PAM-стека password вызываются каждый раз, когда пользователь меняет
реквизиты своей учетной записи. Поэтому туда принято помещать любые модули, так
или иначе связанные с проверкой введенных пользователем данных. Один из немногих
таких модулей называется pam_cracklib и предназначен для проверки паролей на
стойкость с помощью следующих техник:
Отброс слишком коротких паролей;
Запрещение пароля, совпадающего или очень похожего на предыдущий;
Запрещение пароля, отличающегося от предыдущего только регистром символов
(UnixOid, UnIxOiD);
Принуждение пользователя включать в пароль символы верхнего регистра, числа
и другие знаки.
Практически единственное место, куда можно включить вызов pam_cracklib - файл
/etc/pam.d/passwd, используемый командой passwd. Вот его содержимое после
внесения изменений:
Аргументы модуля говорят о следующем: длина пароля должна составлять минимум
6 символов, из которых два должны быть числами, один - символом верхнего
регистра и еще один - неалфавитным знаком (тире, например).
Выводы
Благодаря PAM и большому количеству его сторонних модулей, жизнь
пользователей, системных администраторов и создателей дистрибутивов стала
намного проще. Практически для любой задачи, требующей аутентификации и
настройки окружения пользователя, можно найти готовый модуль PAM, а при
необходимости – написать его самому (это просто). Для дальнейшего изучения
рекомендую обратиться к страничке www.kernel.org/pub/linux/libs/pam/modules.html. Она содержит
ссылки на все доступные на данный момент модули PAM, способные работать в связке
с Linux-PAM.
История PAM
Идея PAM принадлежит Sun Microsystems, двое сотрудников которой разработали
первую версию системы в 1995 году. Впервые PAM появился в Solaris 2.3, а сегодня
входит в поставку большинства UNIX-подобных ОС, включая Linux, FreeBSD, NetBSD и
Mac OS X. API системы PAM был включен в спецификацию XSSO. Это стандартизовало
PAM и привело к появлению нескольких совместимых между собой реализаций
системы:
Оригинальная реализация, поставляемая в составе Solaris;
Linux-PAM, используемый в дистрибутивах Linux;
OpenPAM, разработанный для BSD-систем.
INFO
Авторство системы Linux-PAM принадлежит компании Red Hat, впервые включившей
ее в дистрибутив RedHat 3.0.4 (1996 год).
Руководство проекта FreeBSD перевело ОС на OpenPAM только с выходом пятой
ветки. «Четверка» использовала Linux-PAM.
До появления идеи разделения настроек PAM в каталоге /etc/pam.d все
приложения использовали единый конфигурационный файл /etc/pam.conf.