Документация по ОС FreeBSD Вторник, 23.04.2024, 18:06
Приветствую Вас Гость | RSS
Меню сайта

Категории каталога
Мои статьи [0]
Установка и настройка [281]
X Window [25]
Man pages [30]
Ports & Packages [26]
cvs [18]
Multimedia [20]
Нововсти в мире Unix [0]
RFC [4]
RFC (Request for Comments, Запрос на комментарии) - серия документов, публикуемая сообществом исследователей и разработчиков, руководствующихся практическими интересами, в которой описывается набор протоколов и обобщается опыт функционирования Интернет.
Безопасность [52]
Работа с железом [58]
Книги по FreeBSD [17]
Сеть [505]
Программирование [40]
FireWall [58]
Темы экзамена BSDA [14]
Официальные темы экзамена BSDA, включая подробноые описания и советы по обучению.

Главная » Статьи » Безопасность

Сверхдержавный сервер - Защищаем веб-сервисы грамотно [2006]

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

Tеория::About

Немного утрируя, можно сказать что хакер отличается от скрипткидиса не только тем, что умеет мыслить нестандартно, но и тем, что хорошо знаком с теорией предмета. То же можно сказать и про хорошего крэкера – нужно не только хорошо уметь пользоваться дизассемблером, а еще и знать, например, как устроен тот или иной тип бинарика, что такое коллгейт (нет, не паста :)) и из чего он состоит. Поэтому самый первый кирпичик в основе грамотного системного администрирования – изучение матчасти. Невозможно достойно противостоять напору взломщиков, не понимая, как работает твоя система, и что происходит при вызове того или иного процесса. При разработке защиты так же важно понимать, что хороший хакер, имеющий конкретную цель, взломает любой сервер. C’est la vie. Если кто-то очень сильно захочет посмотреть пару файлов на твоем сервере – он это сделает. Поверь, на Пентагон и ФБР работают не самые плохие специалисты, и, тем не менее, их ломали. И неоднократно. Идеальную защиту можно сравнить с вечным двигателем – теоретически она есть, но пока ее еще никто не создал.

Теория::основные принципы

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

Теория::организация

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

В данном случае машины A, B, и C являются веб-серверами. На них бегают только веб и фтп-демоны. D - почтовый сервер, обслуживающий наших клиентов. Сервер E представляет из себя кластер БД, а F - бэкапный сервер. Как видно на схеме, все сервера хостинга соединены между собой в локалку, причем таким образом, что сервер E и F не имеют доступа в Инет. Эта схема имеет довольно серьезные преимущества в плане безопасности – все запросы внутри локальной сети происходят в одностороннем порядке, а значит ситуацию уже намного легче контролировать. Разумеется, и у такой схемы есть недостатки – например, время запроса к MySQL возрастает, так как запрос выполняется через TCP, а не через (локальный) unix socket.

Таких вариантов построения хостинга - сотни, и каждый из них имеет свои преимущества и недостатки. Систему, описанную выше, использует, например, весьма солидный хостинг ipowerweb.com, о взломе которого я уже рассказывал полтора года назад. Тогда мне помогла лишь полная беспечность админа, оставившего суидный скрипт после инсталляции какого-то софта. Скажу честно: если бы не эта неосторожность с его стороны – я врядли бы достиг цели. Поэтому помни: на систему надейся, а сам не плошай!

System

Теперь попробуем реализовать на практике вышеописанные теоретические доводы. Первым делом мы займемся системой. Рассмотрим простой пример – пользователь купил у нас хостинг и запустил мега-движок на PHP, который написал ему приятель-школьник за 100 рублей. Кроме основного действия скрипта функция N зацикливается, попутно вычисляя некое сложное действие. Как результат – высокая загрузка процессора. Это очень типичная ситуация для хостинга. Чтобы предотвратить подобные ненамеренные (и намеренные) атаки, необходимо ограничивать юзера в плане ресурсов. У *BSD для таких целей существует система профилей пользователей. Это значит, что мы можем легко ограничить ресурсы каждого пользователя в отдельности. Открываем /etc/login.conf:

Листинг файла /etc/login.conf

# Имя профиля
hosting:\
:copyright=/etc/COPYRIGHT:\
:welcome=/etc/motd:\
:setenv=MAIL=/var/mail/$,BLOCKSIZE=K:\
:path=~/bin /bin /usr/bin /usr/local/bin:\
:manpath=/usr/share/man /usr/local/man:\
:nologin=/var/run/nologin:\
# Максимальное время использования процессора 
:cputime=1h30m:\
# Максимальное кол-во памяти, выделяемой программе под данные
# Сам код программы и стэк не учитываются
:datasize=10M:\
# Сколько выделяем для стека программы
:stacksize=3M:\
# Максимальный размер физической памяти, выделяемой процессу
:memoryuse=16M:\
# Максимальный размер файла
:filesize=50M:\
# Максимальный размер core файлов
:coredumpsize=1M:\
# Сколько файлов может открывать каждый процесс
:openfiles=128:\
# Сколько процессов может запускать пользователь
:maxproc=64:\
# Пускать юзера в систему только если его домашняя дира существует и доступна
# юзеру
:requirehome:true\
# Время устаревания пароля
:passwordtime=90d:\
# Остальное берем из профиля default
:tc=default:

Здесь я указал лишь основные параметры. Список всех параметров и их описание можно найти в Handbook (см. врезку)

Hard

Теперь к вопросу о файловой системе. Самый важный файл настроек в данном случае - /etc/fstab. Он применяется при загрузке, и указывает системе, как работать с тем или иным разделом файловой системы, что с ним может делать пользователь, а что - нет. Открываем /etc/fstab и приводим его примерно в такой вид:

/dev/ad1s1b none swap sw 0 0
/dev/ad1s1a / ufs rw 1 1
/dev/ad1s1e /tmp ufs rw,noexec 2 2
/dev/ad1s1f /usr ufs rw 2 2
/dev/ad1s1g /usr/home ufs rw,nosuid,nodev 2 2
/dev/ad1s1d /var ufs rw,nodev 2 2
/dev/acd0 /cdrom cd9660 ro,noauto 0 0

Очень важно поставить параметр noexec на /tmp. Данная опция запрещает запускать что-либо на файловой системе, даже если на файле установлен chmod 777. Я лично видел очень много взломов отлично защищенных серверов именно из-за этой ошибки, которую, почему-то, очень многие допускают. Нельзя забывать, что в /tmp может писать почти любой процесс в системе. Опция nosuid говорит системе игнорировать suid-биты файлов, а nodev запрещает создание/существование в разделе специальных устройств.

System::sysctl

Теперь перейдем к тюнингу самой операционной системы. Открываем /etc/sysctl.conf и пишем туда следующее:

Листинг файла /etc/sysctl.conf

# Запрещает юзерам видеть процессы соседа, и, разумеется рутовые.
security.bsd.see_other_uids=0
# Пускаем запросы на закрытые порты в черные дыры
net.inet.tcp.blackhole=2
net.inet.udp.blackhole=1
# Указываем размер очереди сокета
kern.ipc.somaxconn=1024
# Отрубаем ip-редиректы
net.inet.icmp.drop_redirect=1
net.inet.icmp.log_redirect=1
net.inet.ip.redirect=0
# Назначаем размеры буфера для TCP-подключений. Если на сервер ожидается большая # нагрузка, и у него много памяти – лучше поставить 65535. Значение выше 65535 
# не рекомендуется.
net.inet.tcp.sendspace=32768
net.inet.tcp.recvspace=32768
# Обновляем ARP-таблицу каждые 20 минут
net.link.ether.inet.max_age=1200
# Запрещаем отвечать на все лишние запросы.
net.inet.icmp.maskrepl=0
net.inet.ip.sourceroute=0
net.inet.ip.accept_sourceroute=0
net.inet.icmp.bmcastecho=0

Конечно же здесь указаны не все параметры sysctl. Для полного описания всех возможностей не хватило бы и журнала, поэтому я указал самые основные и необходимые. Многие параметры для sysctl можно изменять и динамически:

sysctl <параметр>=<значение>

Например: sysctl kern.maxprocperuid=1000

Теперь необходимо продублировать часть настроек в /etc/rc.conf:

# Дублируем настройки sysctl
icmp_drop_redirect="YES"
icmp_log_redirect="YES"
icmp_bmcastecho="NO"
tcp_drop_synfin="YES"

Логи

Очень важным аспектом системного администрирования является слежение за поведением сервера. Для этого существует отличная утилита logcheck. Устанавливаем:

# cd /usr/ports/security/logcheck
# make install clean

Утилита написана на sh скриптах, и занимает всего 29 Кб в архиве. После установки в /usr/local/etc у тебя появятся четыре конфига: переименуй их, убрав из названия файла «sample»:

logcheck.hacking – о каких странностях сообщать;
logcheck.violations – о каких попытках взлома сообщать; 
logcheck.ignore – какие странности игнорировать;
logcheck.violations.ignore – какие попытки взлома игнорировать.

В целом и общем, первый файл от второго ничем не отличается, равно как и третий от четвертого :). Просто разработчики скрипта решили разнести сообщения о подозрительной активности и сообщения о явной атаке в разные конфиги. Затем необходимо перенести файл logcheck.sh:

# mv logcheck.sh /usr/local/sbin
# chmod 0700 /usr/local/sbin/logcheck.sh
# chown root:wheel /usr/local/sbin/logcheck.sh

Теперь можно запускать скрипт по крону, хотя бы раз в сутки:

0 4 * * * /usr/local/sbin/logcheck.sh

Так же следует учесть тот факт, что, при большой активности хостящихся сайтов, логи веб-сервера начнут занимать немало места. И в то же время их надо сохранять. Тут есть два варианта. Можно использовать утилиту logrotate (/usr/ports/sysutils/logrotate), но я использую небольшой самописный скрипт. Его основной конфиг я поясню, а скрипт целиком можно найти на диске (rLog.sh).

# Где лежат логи вхостов?
logs_dir=/var/log/www
# Куда складывать архивы с логами?
arc_logs=/var/wwwlogs
# Кого устанавливать владельцем архивов?
user=root
group=wheel
# Темп-файл
rLog_l=/tmp/rLog.log

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

0 6 * * * /usr/local/sbin/rLog.sh 

Apache

К сожалению, на сегодняшний день не существует хотя бы близкой к безупречности модели защиты Apache. Любая конфигурация этого веб-сервера так или иначе оставляет возможности для взлома, даже при использовании suexec или cgi врапперов. Единственный более-менее интересный вариант – это модуль PerUser для Apache 2. Он позволяет запускать Апач с привилегиями пользователя, который указан в конфиге виртуального хоста. Это значит, что каждый вхост (читай домен) на сервере запускается из-под отдельного системного юзера. Даже если поломают один сайт то, чтобы добраться до других, хакеру нужно будет поднимать привилегии до рута. А на хорошо настроенной BSD-системе сделать это намного сложнее, нежели залить веб-шелл через багу в скрипте. Однако у модуля PerUser есть три серьезных недостатка. Во-первых, он существует только для Apache второй версии, которая еще не совсем стабильна, во-вторых – проект уже довольно долгое время находится в стадии альфа-тестинга, и в-третьих – модуль (по второй причине) невозможно установить из портов, а значит веб-сервер придется собирать из исходников, а это не только дополнительная возможность наделать ошибок, но и немалый геморрой с апдейтами. Думаю, что если разработчики все же разродятся стабильным релизом этого модуля – это решит множество проблем для админов хостинговых серверов.

Scripting

Рассмотрим самое уязвимое место хостинговой системы – выполняемые файлы, в частности, PHP скрипты. Открываем конфиг PHP:

# vi /usr/local/etc/php.ini

Меняем следующие параметры:

; Экранирование спецсимволов
magic_quotes_gpc = On
; Выключаем опасные функции:
disable_functions = system, exec, passthru

Выключить эти функции очень важно. Хоть они и недоступны при включенном safe mode, пользователь может без труда провести успешную атаку, указав в файле .htaccess:

php_flag safe_mode off

Виртуальные хосты

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

<IfModule mod_php4.c>
# Включаем Safe mode
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid on
# Папка, выше которой скрипт не может видеть
php_admin_value open_basedir /home/domain.ru 
php_admin_value safe_mode_exec_dir /home/domain.ru
# Temp дира юзера
php_admin_value upload_tmp_dir /home/domain.ru/tmp
# Не начинать PHP сессию автоматически
php_admin_flag session.auto_start off
# Где сохранять файлы сессий
php_admin_value session.save_path /home/domain.ru/tmp
</IfModule>

Как известно, немалая часть взломов (SQL Injection, XSS атаки, инклюдинг) происходит по сути посредством хитрого HTTP запроса. Логично предположить, что эти самые запросы неплохо было бы фильтровать. Решение проблемы существует в виде модуля к Апачу, и называется оно mod_security. Ставим:

# cd /usr/ports/www/mod_security/
# make install clean

После установки – идем конфигурировать. Открываем любой конфиг виртуального хоста, например 001.admin.hosting.ru, над которым мы уже экспериментировали. Все значения надо вводить между тегами

 <Virtualhost *:80> и </Virtualhost>.
# Включаем mod_security
SecFilterEngine On
# Проверяем запросы
SecFilterScanPOST On
# Проверяем ответы
SecFilterScanOutput On
# Проверяем, правильно ли закодирован URL
SecFilterCheckURLEncoding On
# Включаем этот параметр, если сайт в Unicode
SecFilterCheckUnicodeEncoding Off
# Задаем диапазон байтов
SecFilterForceByteRange 1 255
# Сохраняем в лог только срабатывания механизма
SecAuditEngine RelevantOnly
# Где живет лог :)
SecAuditLog logs/audit_log
# Возвращаем ошибку 500 при срабатывании
SecFilterDefaultAction "deny,log,status:500"
# Перекрываем dots-bug
SecFilter "\.\./"
# Не забываем про XSS
SecFilter "<(.|\n)+>"
SecFilter "<[[:space:]]*script"
# SQL injection, куда же без него :)
SecFilter "delete[[:space:]]+from"
SecFilter "insert[[:space:]]+into"
SecFilter "select.+from"
# Перекрываем возможность передачи переменных PHP
SecFilterSelective ARG_b2inc "!^$"
# Исключаем возможность раскрытия пути
SecFilterSelective OUTPUT "Fatal error:"

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

Firewall

Ну и, разумеется, ключевой момент защиты – файрвол. Открываем конфиг файрвола (/etc/rc.firewall) и приводим нужную секцию примерно в следующий вид:

ip="123.31.123.123" # IP сервера
myip="90.90.90.90" # Твой статический ип

Листинг файла /etc/rc.firewall

# С этих диапазонов ничего хорошего за всю историю РуНета не приходило.
${fwcmd} add deny log logamount 1000 ip from 217.17.248.0/24 to any
${fwcmd} add deny log logamount 1000 ip from 62.149.64.0/18 to any
${fwcmd} add deny log logamount 1000 ip from 212.93.192.0/19 to any
${fwcmd} add deny log logamount 1000 ip from 212.106.64.0/19 to any
${fwcmd} add deny log logamount 1000 ip from 62.215.0.0/16 to any
${fwcmd} add deny log logamount 1000 ip from 200.0.0.0/8 to any
# Сервисы
# Пропускаем фтп
${fwcmd} add pass tcp from any to ${ip} 21 setup
# Открываем ssh только для себя
${fwcmd} add pass tcp from ${myip} to ${ip} 22 setup
# Веб
${fwcmd} add pass tcp from any to ${ip} 80 setup
# Https
${fwcmd} add pass tcp from any to ${ip} 443 setup
# Разрешаем трафик для всех уже установленных соединений
${fwcmd} add pass tcp from any to any established
# Пропускаем IP-фрагменты
${fwcmd} add pass all from any to any frag
# Разрешаем исходящие TCP
${fwcmd} add pass tcp from ${ip} to any setup
# А теперь все идут лесом
${fwcmd} add deny tcp from any to any setup
# Разрешаем DNS-трафик
${fwcmd} add pass udp from ${ip} to any 53 keep-state
# Разрешаем NTP-запросы
${fwcmd} add pass udp from ${ip} to any 123 keep-state

В зависимости от того, как ты настроил passive-mode в конфиге pure-ftpd, не забудь открыть нужный диапазон портов.

Chroot

Когда ко мне прибежал очередной знакомый админ и с выпученными глазами сообщил, что теперь у него стоит mod_chroot для Апача – я задал ему вполне легитимный вопрос: «Зачем?». Ответ был стандартный – «Потому что секурно». Мы с ним рассмотрели минусы решения: потеря производительности, лишний немаленький модуль, дополнительный конфиг. Смотрим плюсы: а что дает модуль? А ничего он не дает. То же можно сказать и про обычный chroot – он ничего не дает в плане безопасности. Дело в том, что грамотно выставленные chmod’ы дают тот же эффект, но без потерь в ресурсах и дополнительных заморочек. Для системы, которую мы рассматриваем на примере, chroot не пригодится. Однако существует множество случаев, когда он необходим. В основном, к помощи chroot’а имеет смысл прибегать, когда требуется обезопасить отдельный сервис. Например, ISC BIND, который, мягко говоря, небезопасен – создавать ему «песочницу» необходимо, даже если DNS – это единственный сервис, запущенный на системе.

Jail

В связи с тем, что вопрос безопасности сегодня стоит очень остро, постоянно появляются все новые и новые решения. К сожалению, большинство из них далеки от идеала. Выбирая любое решение, необходимо сначала рассматривать его недостатки, и только потом – преимущества, так как обычно игра не стоит свеч. Например, Jail в BSD. С одной стороны – все замечательно и прекрасно, если походить по форумам – везде восторженные отклики «профессионалов» о том, как у них все теперь секурно. На примере того же хостинга давай посмотрим, что будет, если мы поставим туда jail’ы. Во-первых, в джейл нам придется загонять каждый вхост, а значит – мы серьезно теряем в производительности. Во-вторых, jail еще очень плохо документирован, а значит, уже нужно быть готовым к сюрпризам (не всегда приятным). В-третьих, jail еще мало кто использует, и я бы не был на 100% уверен в его стабильности, и, уж тем более, безопасности. В-четвертых, если хакер достаточно квалифицирован, чтобы поднять привилегии внутри джейла, то ему не составит большого труда вылезти из него в основную систему. А теперь рассмотрим плюсы: джейл позволяет нам создавать ОС внутри ОС. Круто. Но как показывают его минусы – в данном случае - бессмысленно. Существуют варианты, когда такие системы необходимы – это при раздаче шеллов или VDS пользователям. Например, проект firstvds.ru работает на основе модифицированного FreeBSD jail.

Резюме

Суть примеров с Chroot и Jail заключается в том, чтобы донести до нас одну из ключевых аксиом – ОС, софт и настройки следует выбирать исходя из задачи. Не стоит ставить ту или иную фишку, если она не помогает решить задач, которые выполняет сервер. Этим грешат очень многие системщики, и часто именно эти излишки и открывают хакеру лазейку в систему. В целом и общем можно сказать, что чем больше админ знает о функциях, которые будут выполнять процессы сервера – тем лучше он сможет защитить сервер.

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



Источник: http://www.xakep.ru/magazine/xs/068/052/1.asp
Категория: Безопасность | Добавил: oleg (27.03.2008) | Автор: _MIF_
Просмотров: 1585 | Рейтинг: 5.0/1 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа

Beastie

Друзья сайта

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
links

Copyright MyCorp © 2024