Початок PAM

Stanislav Ievlev, [email protected] Перша публікація відбулася на linux.ru.net

0. Про статтю

Ця стаття розвивалася довго і нудно. Перша версія з'явилася на linux.ru.net і становила лише першу частину цієї праці. Але час минав, знань додавалася і захотілося прокладання. Систематизувати свої знання так цікаво. Приєднуйтесь.

1. PAM з погляду користувача

Як було раніше. Бажаючи увійти в систему ви були змушені пообшатися з програмою-охоронцем гордо іменованої login. Вона запитувала ваше ім'я, потім пароль шифрувала відомим алгоритмом і звіряла абракадабру з записом у файлі /etc/passwd. Якщо все збігалося, то вам дозволялося увійти, інакше пропонувалося почати все з початку.

Невідомо скільки ще раз довелося б переписувати цю програму, та й не тільки її (з паролюванням у системі пов'язані ще й passwd, і su), якби не спала комусь на думку відокремити програми від механізму аутентифікації. Ця система отримала назву PAM (Pluggable Authentication Modules), що по-українськи означає Підвантажувані Модулі Аутентифікації (ПМА).

Тепер якщо програма (зокрема login) шкодує зробити аутентифікацію користувача вона більше не займається цим, а звертається до PAM'у з відповідним проханням. Останній виконує всі перевірки і повідомляє тому, хто викликав його про результати-пускати або не пускати. Всі турботи про вибір алгоритму та особливості аутентифікації тепер лежать на PAM'і програма і не здогадується через які кола пекла проходить користувач, щоб його прийняли.

Формально PAM виконаний у вигляді бібліотек-модулів, що розділяються, комфортно розташувалися в каталозі /lib/security/. Кожен модуль по-особливому пропускає через себе користувача, реалізуючи свій особливий механізмавтентифікації. Тобто, запускаючи той чи інший набір модулів, ми як із цегли складаємо сценарій автентифікації згідно з нашими звичками та бажаннями.

Заглянемо усередину цього файлу. вміст може виглядати, наприклад, так:

Кожен рядок означає, що для успішної автентифікації користувач повинен пройти через зазначений модуль. Взагалі формат запису:

Тип-Модуля Прапор-Контролю Шлях-К-Модулю Параметри-Модуля

Тип-модуль повинен бути одним з наступних:

  • auth:Такий модуль перевіряє наявність користувача в системі, запитує його ім'я, дозволяє доступ до тієї чи іншої групи (незалежно від записів у файлі /etc/groups) і взагалі здатний давати привілеї (звичайно спеціально призначені для цього).
  • account: Цей модуль не займається автентифікацією, а дозволяє контролювати розподіл ресурсів системи для тих чи інших бюджетів користувача.
  • session:А цей пов'язаний з речами, які можуть відбуватися перед тим як користувач отримає доступ до тієї чи іншої служби. Наприклад, ведення записів у системних журналах.
  • password:Модуль, як випливає з назви, що займається безпосередньо перевіркою паролів на справжність, слабкість і т.д.

Прапор-контролю вказує як система реагуватиме при вдалому або невдалому проходженні відповідного модуля. Оскільки модулі запускаються послодно один за одним, то спеціальним розташуванням прапорів можна визначити значущість кожного з них. Можлива проста та складна форма запису подібних прапорів, але в рамках нашого знайомства цілком достатньо буде простою. Як прапори можуть бути використані такі ключові слова:

  • required: Удача цього модуля потрібна для всієї аутентифікації взагалом. Невдача модуля з подібним прапором не проявиться для користувача поки не виконаються всі модулі, що залишилися.
  • requisite:Таке саме, але тільки у випадку провалу управління тут же буде повернено додатку.
  • sufficient:Вдале проходження подібного модуля вважається достатнім для визнання всієї автентифікації вдалою, якщо не провалилася перевірка на попередніх модулях з прапором required. Невдача цього модуля не вважається фатальної для всієї наступної аутентифікації.
  • optional:Цей модуль не є критичним для автентифікації і використовується як додатковий. Тобто, наприклад, може обмежитися виведенням на екран попередженням про слабкість пароля.

Крім файлів-сценаріїв, деякі модулі можуть використовувати додаткові файли конфігурації. Всі вони розташовані в каталозі /etc/security, і кожен файл призначений для певної групи налаштувань.

time.conf- Тут ви зможете обмежити час доступу користувачів з різних терміналів до різних сервісів. Наприклад, заборонити входити до системи з першої віртуальної консолі адміністратору під час вихідних. Ці налаштування обслуговує модуль pam_time і, відповідно, якщо ви бажаєте, щоб ваші обмеження отримали модуль повинен бути прописаний у відповідному сценарії.pam_env.conf-А тут вам під силу обмежити можливості зміни окремих змінних середовища користувачами. Працює під керівництвом модуля pam_env.limits.conf- Якщо ви злісний адміністратор або у вас недобросовісні користувачі, то цей файл для вас. Тут ви можете індивідуально або для групи обмежити: розмір core-файлу, максимальний допустимий розмір файлу, максимальна кількість відкритих файлів, запущених процесів, скількираз можна одночасно зайти до системи тощо. Керівний модуль pam_limits.access.conf-Оскільки PAM має засоби аутентифікації по мережі, то подібні налаштування є корисними бо контролюється не тільки хто може або не зайти, але й звідки. Контролюється pam_access.group.conf- Можна вказати якій групі належатиме служба запущена певним користувачем, у певний час з певного терміналу. Господарі pam_time та pam_group.console.perms-Кілька вибивається своєю назвою, але не функціями. Тут визначаються права, одержувані привілейованими користувачами до консолі під час входу до системи та повертаються під час виходу. Модуль pam_console.

2. Робимо власний PAM-модуль

Після теорії подивимося вглиб PAM. Спробуємо розібратися як воно працює.

Приклад1: Новий вхід до системи.

Ви вже напевно уві сні бачите рядки, що добряче дістали.

Ця схема, придумана багато років тому, продовжує служити і зараз. Але не єдиним паролем жива людина. Давайте зробимо щось нове, незвичайне. Буде і самому цікаво, і шкідників введе в оману, бо такого не буде не на одній іншій машині.

До PAM'а нам довелося б переписувати весь login, а тепер ми просто зробимо новий модуль, зберемо його як бібліотеку та припишемо до сценарію автентифікації /etc/pam.d/login. Модуль буде називатися просто pam_test.

Але спочатку про те, що ж ми робитимемо. Є така цікава схема аутентифікації: система видає користувачеві кілька випадкових чисел. Користувач бере певні з них, постачає в ТІЛЬКИ ЙОМУ відомий багаточлен, наприклад,

і замість пароля вводить відповідь. Комп'ютер теж вважає за цим алгоритмом і якщо відповідь правильна, пускає всистему.

Схема ідеальна: підвищується математичний рівень співробітників, пароль вводиться завжди інший, закономірність вловити за непрямими даними практично неможливо (коефіцієнти багаточлена також змінюються від часу, можливих багаточленів темрява).

Є звичайно очевидні недоліки: важко вважати, можна піддивитися як користувач вважає на папірці, складні питання зберігання багаточленів. Але ми не будемо так засмучуватися, адже ми перш за все вчимося, чи не так.

Як ви прочитали раніше, модулі розрізняються за класами. Наш буде класу AUTH. Тобто відповідатиме за аутентифікацію.

От і все. Просто. Справа в тому, що ми описуємо процедуру аутентифікації і тільки її - позитивний ефект від грамотного поділу обов'язків. Повторимо всі основні етапи. У модулі, зрозуміло, повинні існувати функції, що експортуються. У нашому випадку це pam_sm_authenticate та pam_sm_setcred. Для кожного класу модулів набір функцій. Далі, всередині функцій знаходиться основний алгоритм прийняття рішення відповіддю є лише "так" чи "ні". Якщо ж для прийняття такого відповідального рішення необхідно дізнатися додаткову інформацію від користувача, можна дізнатися покажчик на діалогову функцію програми.

Робота з іншими класами модулів є абсолютно ідентичною. Тож спробуйте зробити ще щось своє.

3. Робимо власний PAM-додаток

Давайте тепер подивимося як бачать систему PAM-програми. Нудну і нудну документацію ви самі потім прочитаєте (або я все-таки зроблю це колись сам), а зараз звернемося до практики.

Приклад2: позбавляємося SUID-програм.

Чи прочитали назву? Страшно? Все гаразд, мова в цьому розділі не йтиме про щось незвичайне. Просто кілька теоретичнихроздумів та приклад їх реалізації.

Одним з основних архітектурних недоліків UNIX з точки зору захищеності є наявність SU Навіщо це потрібно. Справа в тому, що іноді для доступу до тих чи інших системних даних прав користувача недостатньо. Так, наприклад, програмі passwd необхідно мати права root для доступу до файлів /etc/passwd та /etc/shadow. Але будучи запущеною користувачем (адже може він поміняти пароль самому собі), вона не в змозі це зробити. Тут і відбувається фокус зі зміною власника. Запускаючи процес passwd отримує права свого власника (root) і тепер може спокійно працювати з раніше забороненими даними. Виходить, що користувач не отримує прав адміністратора, а програма спокійно з ними працює. Все геніально, просто та безпечно. Стоп, ось тут ми і не маємо рації. Більшість атак, спрямованих на переповнення буфера якраз і користуються цією можливістю процесів розширювати свої можливості. Ну і що, що права отримує лише процес, якщо його належним чином накачати, він запустить нам оболонку. Остання успадкує права процесу – права адміністратора. Була в тебе оболонка з правами користувача – стала від імені адміністратора.

Відразу зазначу, що у прикладах не описано процес аутентифікації клієнта. Зрозуміло, що він має бути досить хитромудрим, бажано із застосуванням криптографії. Крім того, сервер обробляє лише один запит. В ідеалі він повинен або постійно висіти в системі як daemon, або викликатись через якийсь wrapper. Всі програми нижче виглядатимуть максимально спрощеними. Краще розуміння, ніж повага без нього.

Отже, сказано-зроблено. Пишемо клієнт (власне passwd який викликатиме користувач).

Ну от і все. Все просто. Але так і має бути.приклад навчальний. Для реального втілення ідеї треба чимало попрацювати. Важливе зауваження. Клієнт ніде не використовує жодних функцій, пов'язаних з автентифікацією в ОС - те, чого ми і домагалися.

А от із сервером справи трохи гірші. Він використовує бібліотеку PAM, хоча може робити всі зміни та вручну. Але навіщо нам винаходити велосипед?

Ось і весь сервер. Функцій автентифікації помітно побільшало, хоча вони й зникли за трьома могутніми літерами PAM. Отже, повторимо побачене.

Для програми важливо запустити PAM (pam_start) та отримати деякий дескриптор. Потім визначитися з діалоговою функцією. Сам PAM вона не хвилює, а хвилює тільки відповідь, що видається нею, у спеціальній формі. Зробивши це, запускаємо потрібну функцію: аутентифікації (pam_authentificate), зміни даних користувача (pam_chauthtok) або яку ще. Зрештою, урочисто завершуємо концерт функцією pam_end. На мою думку все просто і зрозуміло, а тепер вперед до комп'ютера.

Чи не правда PAM це здорово. :))