Журнал LinuxFormat - перейти на главную

LXF84:Безопасность

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Новая: {{Цикл/Безопасность}} ==Безопасность: Стойкие пароли == ''ЧАСТЬ 1: Первая линия обороны Linux-системы – меха...)

Версия 15:42, 20 декабря 2008

Содержание

Безопасность: Стойкие пароли

ЧАСТЬ 1: Первая линия обороны Linux-системы – механизм пользовательских паролей. Д-р Крис Браун объяснит, как он работает и как ещё можно укрепить защиту системы.

«Уверенность», по словам Гекаты в трагедии Шекспира «Макбет», «несет погибель смертным». Она хотела сказать, что чрезмерная вера Макбета в себя в конце концов его погубит: ведь считая себя неуязвимым, он необоснованно рисковал. Прямо как вы! Вообразили, что ваш Linux неуязвим? Вы идете к пропасти…

Есть немало свидетельств, что работать в Linux куда безопаснее, чем в Windows. Я сам видел цифры: Linux «из коробки» подхватывает заразу за три месяца, тогда как Windows – за три часа (см. http://www.honeynet.org). Но это не повод относиться к безопасности своей системы спустя рукава.

В данной серии, состоящих из пяти уроков по безопасности Linux и соответствующим открытым утилитам, мы рассмотрим, как обнаруживать уязвимости и прикрывать их. В первой части мы рассмотрим пароли и поговорим о контроле над привилегиями, даваемом sudo.

Между безопасностью и удобством всегда существует компромисс. Машина, запертая в комнате, где нет подключения к сети, конечно, намного сохраннее, чем машина с доступом в Интернет посреди проходного двора, однако настолько же и бесполезнее. Попробуем облечь убытки от уязвимостей в наукообразный вид – получится такая формула:

Ожидаемые убытки = (вероятность успешного вторжения) x (цена этого вторжения)

На этих уроках я буду говорить об уменьшении вероятности взлома, но важно также уменьшить потери от успешного вторжения. Например, как можно скорее обнаружить вторжение гораздо лучше, чем на много дней оставить его безнаказанным. Регулярное создание резервных копий существенно сократит возможные потери данных. Распределение сервисов на несколько машин (не кладите все яйца в одну корзину) поможет предотвратить простои в работе организации из-за единичного взлома. И так далее.

Хэшируй это!

Начнем с начал: Linux – многопользовательская операционная система. Когда вы входите в нее, вам предложат ввести имя пользователя и пароль для подтверждения того, что вы – это вы. Выбор хорошего пароля – ключевая часть сохранения безопасности системы.

Вот как работает механизм паролей в Linux. Информация о пользовательских учетных записях хранится в двух файлах: /etc/passwd и /etc/shadow. Файл passwd содержит имя пользователя, его числовой идентификатор (User ID, UID) и домашнюю директорию, но (вопреки названию) пароля-то в нем и нет: он укрылся в файле shadow (далее мы увидим, зачем нужно разделение на два файла). Файлы passwd и shadow параллельны – каждой учетной записи пользователя соответствует строка в одном файле и строка в другом. Когда пользователь устанавливает пароль, пароль хэшируется, а результат хэширования помещается в /etc/shadow.

(thumbnail)
Аутентификация с хэшем

Хэширование похоже на шифрование, в том смысле что из внятного текста получается полная белиберда; однако, в отличие от шифрования, хэширование – операция необратимая. Каждый раз, когда вы вводите пароль, он хэшируется, и полученный хэш сравнивается с тем, что прописан в /etc/shadow. Linux не хранит пароли в чистом виде.

В зависимости от вашей Linux-системы, у вас есть выбор из трех путей хэширования:

  1. Функция crypt от Unix, болтающаяся в системе уже много лет. Команда crypt реализует алгоритм DES (Data Encryption Standard) и генерирует 13-символьный хэш.
  2. MD5, который, как вы имели шанс заметить, используется для верификации ISO-образов компакт-дисков и передаваемых по сети файлов, а также в цифровых подписях. MD5 генерирует 34-символьный хэш.
  3. Blowfish (или, скорее, хэш-функция, выведенная по алгоритму Blowfish), генерирующий 60-символьный хэш.

Все эти алгоритмы используют «соль» (salt) – случайное число, генерируемое при установке пароля. Соль и указанный пользователем пароль комбинируются и хэшируются. Соль и хэш сохраняются в /etc/shadow. Если вы проверите свой /etc/shadow на системе, использующей хэши MD5, то ясно разглядите соль и хэш. Например, в строке пароля $1$Ue1yZO5i$.6G/4l1AYliPdkTh1AkBi/ восемь символов после $1$ – соль, а 22 после последнего $ – хэш. Мы увидим, что соль делает взлом паролей гораздо труднее.

Отчасти стойкость пароля зависит от качества хэш-алгоритма. Хороший хэш-алгоритм в теории делает невозможным вычисление пароля по хэшу. Конечно, зная хэш, вы всегда можете попробовать метод грубой силы – хэшировать каждую возможную последовательность из (допустим) восьми символов в надежде найти соответствие. Но существует около 90 отображаемых ASCII-символов, а это значит, что перебрать придется 90 в восьмой степени вариантов – то есть 4,304,672,100,000,000.

Если ваша машина способна вычислять 10000 хэшей в секунду, то на весь перебор понадобится 13650 лет, а это, вероятно, дольше, чем вам хотелось бы ждать. Соль еще более усложняет взлом, делая невозможным простое сравнение со списком хэшей для наиболее часто употребляемых паролей, так что взломщики могут искать совпадение только с одним паролем за раз.

Наш анализ немного наивен, поскольку длина хэша тоже влияет на интервал поиска, но по крайней мере будьте уверены – атаки грубой силой (перебором) слишком медленны. (Более глубокий анализ можно найти в книге Брюса Шнайдера «Прикладная криптография», более поверхностный – в «Цифровой крепости» Дэна Брауна). К сожалению, реальный интервал поиска гораздо меньше, поскольку многие люди выбирают для пароля простые слова или имена: любимого супруга или собаки, или, того хуже, собственное имя пользователя.

Потрошим колбасу

Программы-взломщики паролей автоматизируют атаки, выбирая из словаря пароль, из которого получается данный хэш. Они пользуются информацией из вашей базы данных паролей, и, увы, добиваются успеха пугающе часто. Возьмем, к примеру, популярную утилиту John the Ripper [Джон-Потрошитель, – прим. ред.].

Вы можете скачать «Джона» с http://www.openwall.com. Перед запуском слейте содержимое /etc/passwd и /etc/shadow в один файл. Это делает команда unshadow (включенная в пакет John the Ripper):

# unshadow /etc/passwd /etc/shadow > passwdcombo

В результате получится файл, где хэши будут вставлены во второе поле файла passwd (как это было до изобретения shadow). Для выполнения описанной команды вы должны иметь привилегии суперпользователя, поскольку только он может читать /etc/shadow. Теперь запускайте John. Опций командной строки для настройки поиска хватает, но благодаря разумным установкам по умолчанию John будет работать, если ему просто указать имя полученного выше файла:

# John passwdcombo

Не ждите, что результаты появятся сразу. Для тестирования я создал десять пользовательских учетных записей со следующими паролями: user1pw; secret; terces; secret42; Secret; ducttape; England; pit; coat; milewide; sausages [те самые колбасы, – прим. ред.]. Из них John нашел secret, terces и Secret в течение нескольких минут. В течение ночи он нашел England и sausages. Пять из десяти, хотя, конечно, некоторые из этих паролей были нарочито слабыми.


В тесте участвовала версия John the Ripper 1.6-4 на Fedora Core 5 с MD5-хэшами. Если угодно, настраивается John несколькими способами: подключением к нему разных списков паролей; указанием правил по трансформации паролей из списка; через файл John.ini; через аргументы командной строки.

Успех программ-взломщиков паролей поясняет, почему пароли не хранятся в /etc/passwd: этот файл могут читать все пользователи (он часто используется для поиска соответствия между пользователем и UID), так что если бы хэши хранились здесь, любой пользователь мог бы начать подбор паролей. Перемещение хэшей в /etc/shadow (который может читать только root) блокировало эту линию атаки.

Наши результаты должны также укрепить в вас сознание необходимости выбирать сильные пароли. Те, кто использует слова, имеющегося в словаре, просто нарываются на неприятности. С другой стороны, использование слишком сложного для запоминания и набора пароля также неблагоразумно. (У одних моих клиентов пароль root был наклеен на терминал).

Один из способов составления хорошего пароля – выбрать два несвязанных слова и склеить их каким-нибудь знаком пунктуации; например так: pico:drip или tiny-duck. Другой способ – взять слово, заменить часть букв на заглавные, а часть – на цифры: B33rMats (beermats), a1rcr4FT (aircraft).

Добиться того, чтобы ваши пользователи использовали сильные пароли – вопрос обучения. Объясните, как выбрать хороший пароль, и регулярно запускайте взломщик, выявляя тех, кто не слушает советов. Если вы хотите автоматизировать принудительный выбор сильных паролей, рассмотрите как вариант установку модуля PAM pam_passwdqc. Этому модулю можно поручить установку паролей, а заодно настроить его на проверку паролей по длине и смешиваемости символов (верхнего/нижнего регистра, цифр и других знаков). Модуль доступен на http://www.openwall.com.

Установка пароля Grub

Взлом пароля – не единственный способ проникнуть в Linux-систему. Большинство систем в качестве загрузчика используют Grub. Grub достаточно гибок в настройке и включает опции вмешательства в процесс загрузки и редактирования команд загрузки (или даже добавления новых команд).

Grub умеет передавать аргументы ядру Linux, и один особо интересный трюк заключается в добавлении аргумента init=/bin/sh в конец команды загрузки ядра. Этот аргумент скажет ядру, что вместо команды init нужно запустить /bin/sh, и вы получите полный доступ к системе без ввода пароля суперпользователя.

Атаки такого рода можно предотвратить, установив пароль на Grub. Тогда интерактивные опции Grub не включатся до тех пор, пока не будет введен верный пароль. Пароль нужен не на загрузку согласно имеющемуся файлу конфигурации Grub, а на редактирование и интерактивный ввод команд.

Пароль для Grub установить легко. Откройте файл /boot/Grub/menu. lst и добавьте в глобальные настройки (в начале файла) строку вроде этой:

password --md5 $1$H06141$PTIpTGW7fNKspluqd1Mdk.

Мы опять видим MD5-хэш (вместе с солью), который мы уже встречали ранее. Есть несколько способов его генерации. Во-первых, можно просто скопировать хэш существующей учетной записи из файла /etc/shadow. Естественно, тот, для которого вы знаете пароль. Во-вторых, можно запустить Grub из командной строки и ввести команду md5crypt. Программа попросит вас ввести пароль и выведет хэш. Диалог выглядит так:

# Grub
GNU Grub version 0.95 (640K lower / 3072K upper memory)
Grub> md5crypt
Password: *********
Encrypted: $1$H06141$PTIpTGW7fNKspluqd1Mdk.
Grub> quit

(Теперь можно вставить этот хэш в /boot/Grub/menu.lst) Если вы теперь загрузите машину, имея эту строку в файле конфигурации Grub, то сможете только выбирать ОС из предопределенных в menu.lst, клавишами «вверх» и «вниз», а для других действий придется нажать p и ввести пароль.

В мультизагрузочной системе можно также заблокировать определенные пункты меню, и доступ к ним получат только знающие пароль, причем пароль у каждого пункта может быть своим. Для этого ознакомьтесь с руководством по Grub, доступном на http://www.gnu.org/software/Grub/manual.

Контроль доступа

Не сомневаюсь: вы уже знаете, что в Linux есть специальная учетная запись, называемая суперпользователем. Общепринятое имя для этой записи – root, однако ключевой момент – числовой пользовательский идентификатор, UID: для root он равен нулю. Если вы вошли в систему как root, считайте все проверки пройденными, а все права доступа вашими – вы всемогущи. Как модель безопасности, понятие root вызывает примитивное чувство все-или-ничего.

К примеру, если вы хотите позволить кому-нибудь подстраивать системные часы, дайте ему пароль root, который позволит ему влезть в секреты своего начальника. С точки зрения ролевой системы, по контролю доступа ролей только две: смертный человек и Бог. Для потенциального взломщика получение пароля root на вашей системе – абсолютная победа.

Команда sudo позволяет системным администраторам распределять ответственность между пользователями более гибко. Sudo контролируется конфигурационным файлом /etc/sudoers. Пытаясь произвести впечатление на хорошенькую девушку на вечеринке, я могу сказать что-то вроде «sudo предоставляет контролируемое повышение привилегий» (мне никогда не удавалось стать душой вечеринки). Или, говоря проще, он позволяет указать, кому что разрешается делать.

Освоение sudo в значительной степени означает освоение синтаксиса файла /etc/sudoers. К сожалению, документация для sudoers описывает синтаксис файла с использованием расширенной формы Бэкуса-Наура, нотации для формального описания грамматик: если вы не так давно получили ученую степень по компьютерным наукам, все будет отлично, в противном случае – оставьте надежду. Тем не менее, несколько примеров прояснят ситуацию.

В качестве простого примера допустим, что я хочу разрешить пользователю harry изменять системное время и дату из командной строки, используя команду date. Команда date позволяет любому пользователю, запустившим ее без аргументов, узнать текущее время и дату:

$ date
Thu Sep 15 07:56:52 BST 2006

А вот если вы попытаетесь изменить время и дату, не будучи root, это вам не удастся:

$ date 09150755
date: cannot set date: Operation not permitted
Thu Sep 15 07:55:00 BST 2006

Чтобы harry мог изменять дату и время, вы должны сообщить sudo, что на запуск date у него есть права root. Для этого поместите такую строку в /etc/sudoers:

harry snowhite=(root) /bin/date

В терминологии sudo это называется спецификацией привилегий. Давайте рассмотрим каждое поле:

  • harry Первое поле – учетная запись, которой мы даем особые привилегии.
  • snowhite Второе поле – имя машины, к которой имеют отношения эти привилегии. Указание конкретного имени позволит вам держать данные sudoers на целую когорту машин в одном файле (через NFS, например), и настройка будет у каждой своя. Часто в этом поле можно видеть ALL.
  • =(root) Эта запись указывает пользователя, чьи права используются для запуска команд.
  • /bin/date Последнее поле – имя команды, которую может запускать пользователь. Полный путь указывать обязательно.

Для редактирования файла sudoers вы должны быть root и использовать при этом команду visudo (а не обычный редактор). Наш друг visudo заблокирует файл от одновременных обновлений и проверит его синтаксис перед сохранением.

С этой строкой в sudoers harry может менять время и дату так:

$ sudo date 09150755

У harry спросят пароль. Некоторые дистрибутивы Linux включают в /etc/sudoers строку вроде этой:

Defaults targetpw

При наличии этой строки harry должен будет вводить не свой пароль, а пароль того пользователя, от лица которого запускается команда (обычно root). Вы должны удалить эту строку из sudoers, что-бы пользователь вводил свой пароль, а не root’а. Иначе будет потеряна вся гибкость ролевой системы. Вы также должны удалить такую строку, если у вас она найдется:

ALL ALL=(ALL) ALL

Когда harry воспользуется sudo и введет пароль, sudo на какое-то время позволит ему выполнять команды без проверки пароля. По умолчанию этот промежуток времени равен пяти минутам; вы можете его изменить, добавив в sudoers такую строку: Defaults timestamp_timeout=0 Нулевое значение означает, что sudo будет спрашивать пароль всегда.

Ролевая игра

Давайте рассмотрим другие особенности sudoers. Ключевое слово ALL используется в некоторых местах файла. Например:

isaac ALL=(ALL) ALL

Эта строка говорит о том, что пользователь isaac может запускать любую программу от лица любого пользователя на любой машине (конечно, если он укажет свой пароль или пароль соответствующего пользователя на нужной машине).

Вы также можете определять псевдонимы (alias). Псевдонимы – это просто именованные списки пользователей, машин или команд. Сами по себе псевдонимы ничего не делают, зато они облегчают написание привилегий для множества пользователей. Покажу вам на примере.

Пусть вы хотите дать определенному пользователю права на управление пользовательскими учетными записями. Для этого есть множество утилит – useradd, groupadd и т.д. В sudoers вы можете определить командный псевдоним (назовем его USERMGMT):

Cmnd_Alias USERMGMT=/usr/sbin/useradd,/usr/sbin/usermod,\
/usr/sbin/groupadd,/usr/sbin/groupmod,\
/usr/sbin/userdel,/usr/sbin/groupdel

Обратите внимание на символ \, означающий, что строка имеет продолжение. Определив псевдоним, мы можем дать пользователю isaac возможность запускать любую из этих программ таким образом:

isaac ALL=(root) USERMGMT

Вы можете рассматривать USERMGMT как роль (хотя в документации к sudo этот термин не используется), определяющую команды, которые играющий эту роль может выполнить.

Можно определять псевдонимы пользователей (имя перечня пользователей) и присвоить им роли:

User_Alias ADMINS tom,joe,sue
ADMINS ALL=(root) USERMGMT

Таким способом мы объявили, что tom, joe и sue могут играть роль USERMGMT. Так же можно определить и список машин, используя диапазон IP-адресов или имена хостов:

Host_Alias LOCALNET 192.168.0.0/255.255.255.0
Host_Alias TRUSTEES snowhite,happy,sneezy

Теперь мы можем дать определенным пользователям привилегии только на определенных машинах:

ADMINS TRUSTEES=(root) USERMGMT

Что ж, на сегодня хватит. Вы узнали о том, как работает механизм паролей в Linux, и, надеюсь, до вас дошло, почему необходимо придумывать сильные пароли. Вы увидели, как можно защититься от тривиальной атаки с физическим доступом, установив пароль на Grub. Вы узнали, как избежать раздачи пароля root кому попало и использовать sudo для того, чтобы позволить определенным пользователям запускать определенные программы с ограниченными привилегиями.

Персональные инструменты
купить
подписаться
Яндекс.Метрика