Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 128, АВГУСТ 2009 г.

PAM'ятка матерого юниксоида. Модули аутентификации на все случаи жизни

Евгений Зобнин (zobnin@gmail.com)

Сегодня система подключаемых модулей аутентификации 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 и сравнение хешей:

auth required pam_unix.so no_warn try_first_pass nullok

Уберем ее, и двери захлопнутся, больше в систему не войдешь. А теперь немного магии. Как я уже говорил, изменяя несколько строк в конфигурационных файлах, мы можем сделать с методом аутентификации и авторизации все, что угодно (в рамках возможностей доступных модулей, конечно). Возьмем, к примеру, файл /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:

auth sufficient pam_listfile.so item=user sense=allow file=/etc/users.allow onerr=fail

Немного изменив строку, можно добиться запрещения входа пользователей:

auth sufficient pam_listfile.so item=user sense=deny file=/etc/users.deny onerr=fail

Причем, в качестве значения опции 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 (в начало файла):

auth required /lib/security/pam_securetty.so
auth sufficient /lib/security/pam_alreadyloggedin.so no_root

Возвращаясь к спискам пользователей, нельзя не упомянуть о довольно интересном модуле pam_pwdfile (cpbotha.net/software/pam_pwdfile). Его задача - предоставить приложениям альтернативную базу пользователей и паролей, которую они смогут использовать вместо системного файла /etc/passwd. Это своего рода плагин для тех приложений и демонов, которые не способны вести подобную базу самостоятельно. Яркий пример: минималистичный FTP-сервер vsftpd. Запусти его от непривилегированного пользователя, и клиенты не смогут получить доступ к серверу. Выход: использовать pam_pwdfile, который будет вести отдельный файл логинов и паролей специально для vsftpd. Для использования достаточно добавить следующие две строки в начало /etc/pam.d/vsftpd:

auth required pam_pwdfile.so pwdfile /usr/local/etc/vsftpd/vsftpd.users
account required pam_pwdfile.so pwdfile /usr/local/etc/vsftpd/vsftpd.users

И добавить пользователей в базу с помощью утилиты 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- или какого-либо другого хостинга и любых конфигураций, предусматривающих вход в систему сомнительных лиц. Модуль очень прост в использовании. Для настройки достаточно выполнить две команды:

# echo 'session required pam_chroot.so' >> /etc/pam.d/ssh
# echo 'vasya /usr/chroot' >> /etc/security/chroot.conf

Все, теперь vasya, вошедший с помощью ssh-клиента, будет помещен в каталог /usr/chroot и не сможет из него выбраться. На втором месте в рейтинге – модуль pam_mkhomedir из пакета Linux-PAM, просто создающий домашний каталог для прошедшего аутентификацию пользователя. Поначалу полезность модуля может показаться сомнительной, но администраторы гетерогенных сетей, состоящих вперемешку из машин Windows/UNIX, ценят его дороже своих потертых джинсов. Дело в том, что в таких сетях принято использовать Active Directory для хранения учетных данных пользователей, коих может быть не одна сотня. Вместо того чтобы создавать многочисленные каталоги для каждого пользователя, зарегистрированного в AD, они просто выполняют приведенную ниже команду на всех UNIX-машинах и удаляются в серверную порезаться в «контру»:

# echo 'session required pam_mkhomedir.so skel=/etc/skel/ umask=027' >> /etc/pam.d/common-session

Модуль обычно используется в связке с модулем pam_winbind, осуществляющим аутентификацию в AD, или с pam_ldap, аутентифицирующим пользователей, используя сервер LDAP.

Почетное третье место занимает завязанный на возможностях Linux-ядра модуль pam_namespace. Его задача - незаметное создание изолированной копии общедоступного каталога (/tmp, например) для каждого пользователя. Другими словами, вошедший пользователь получает доступ только к своей версии каталога /tmp и не видит файлов других пользователей. Нужно это для борьбы с методами взлома, основанными на использовании состояний гонок (race condition), символических ссылок и просто для ограждения возможного нарушителя от любых файлов легальных пользователей.

Модуль использует простой конфигурационный файл /etc/security/namespace.conf для принятия решения о том, какие каталоги должны быть подменены. Вот простая инструкция для изолирования каталога /tmp:

# mkdir /tmp-inst
# chmod 0 /tmp-inst
# echo "/tmp /tmp-inst/ user root" >> /etc/security/namespace.conf
# echo "session required pam_namespace.so" >> /etc/pam.d/common-session

Результат: индивидуальный каталог /tmp для каждого пользователя, за исключением root'а (на самом деле файлы будут храниться в каталоге /tmp-inst/юзер). Конфигурационная строка для изолирования каталога /home (чтобы злоумышленник не смог увидеть и получить доступ к каталогам пользователей) должна выглядеть так:

$HOME $HOME/$USER.inst/ user root

Автоматизированная проверка паролей на стойкость

Плагины PAM-стека password вызываются каждый раз, когда пользователь меняет реквизиты своей учетной записи. Поэтому туда принято помещать любые модули, так или иначе связанные с проверкой введенных пользователем данных. Один из немногих таких модулей называется pam_cracklib и предназначен для проверки паролей на стойкость с помощью следующих техник:

  • Отброс слишком коротких паролей;
  • Запрещение пароля, совпадающего или очень похожего на предыдущий;
  • Запрещение пароля, отличающегося от предыдущего только регистром символов (UnixOid, UnIxOiD);
  • Запрещение «паролей-перевертышей» (старый пароль: unixoid, новый: dioxinu);
  • Принуждение пользователя включать в пароль символы верхнего регистра, числа и другие знаки.

Практически единственное место, куда можно включить вызов pam_cracklib - файл /etc/pam.d/passwd, используемый командой passwd. Вот его содержимое после внесения изменений:

password required pam_cracklib.so retry=3 minlen=8 dcredit=-2 ucredit=-1 ocredit=-1 lcredit=0
password required pam_unix.so use_authtok

Аргументы модуля говорят о следующем: длина пароля должна составлять минимум 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.

WWW

Ссылка на статью «Система безопасности PAM изнутри»: www.xakep.ru/magazine/xa/086/112/1.asp.

WARNING

  • В OpenBSD поддержка PAM полностью отсутствует.
  • С помощью PAM невозможно реализовать Kerberos.
Содержание
ttfb: 12.609958648682 ms