Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> Security —> Бронированный FreeBSD

Защищаем FreeBSD (defender +1)

Автор: Raven2000.


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

Да и на будущее я не претендую на аса в построение защиты и т.д. т.п. а
лишь попробую (для себя, чтобы не забыть :) и друзей) описать некоторые моменты
защиты, а остальное будет дополняться по мере просьб и необходимости.
Т.к. невозможно охватить все, да и абсолютно защищенный сервер, которого невозможно
сломать это как вечный двигатель в теории есть но на практике, увы :).
Хотя я знаю такой - это тот, который на глубине 100 метров под землей в фольге
и с вырубленным питанием :) Статья будет дополнятся и изменятся по ходу обсуждений.
Ну ладно, попробуем немного защитится от спецов :)

Защиту разделим по двум видам:
I) Защита от внешних атак
II) Защита от внутренних атак

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

Теперь определим фронт защиты:

I) Атака извне:
1.1) Apache - http.conf + mod_security
1.2) PHP - php.ini + mod_security + отключение опасных функций + Ограничения ресурсов
1.3) FTP – Разделение привилегий + chroot + квоты + отдельный HDD
1.4) Firewall – грамотно настроенный фаервол
1.5) Сhroot

II) Атака внутри:
2.1) Ограничения ресурсов - /etc/login.conf + /etc/sysctl.conf
2.2) Разделение привилегий - /etc/sysctl.conf + chmod + структура папок
2.3) Логии (logcheck)
2.4) top/ps

III) Общие меры
3.1) Разбор fstab
3.2) Доступ к серверу
3.3) DNS – chroot + noroot

Теперь пройдем по пунктам (некоторые пункты будут вкратце описаны т.к. обший принцип
защиты пересекается с другими пунктами) как и чем можно защитить и ограничить:

I) Прикрытие внешних дыр.

1.1) Apache + виртуальные хосты + mod_security
Прикроем дырки этого сервиса для начала нам необходимо задать ограничения
в конфиге для каждого вхоста. Добавляем следующие параметры:
<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)+>"
# SQL injection, куда же без него :)
SecFilter "<[[:space:]]*script"
SecFilter "delete[[:space:]]+from"
SecFilter "insert[[:space:]]+into"
SecFilter "select.+from"
# Перекрываем возможность передачи переменных PHP
SecFilterSelective ARG_b2inc "!^$"
# Исключаем возможность раскрытия пути
SecFilterSelective OUTPUT "Fatal error:"

Для и для apache 1.x в httpd.conf закоментите:
#SecFilterScanOutput
#OUTPUT
#OUTPUT_STATUS

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

1.2) PHP
В дополнение смотри пункт – 2.1
Рассмотрим самое уязвимое место хостинговой системы – выполняемые файлы, в частности,
PHP скрипты. Открываем конфиг PHP:
# ee /usr/local/etc/php.ini

Меняем следующие параметры:
magic_quotes_gpc = Off			    # Экранирование спецсимволов
disable_functions = system, exec, passthru  # Выключаем опасные функции:

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

1.3) FTP
Настройка Proftpd установите далее по разделение привилегий смотрим -2.1
в котором я указал то что вам нужно, а по Chroot см раздел 1.5 Желательно ftp
ставить на отдельный HDD чтобы непроизошло переполнения раздела и все
шайтан майфун :) а если у вас он на /etc или /var находился все хана логам и тд :)

1.4) IPFW - штатный файрволл FreeBSD

1.5) Chroot
Chroot  - песочница это конечно с одной стороны хорошо с другой – потеря
производительности, для некоторых программ лишний дополнительный
модуль + конфиг к нему. Я считаю грамотный chmod дает тот же результат , но без
заморочек и потерь ресурсов. В основном к chroot прибегают, когда нужно обезопасить
сервис, который не совсем безопасный как например BIND(о нем ниже).
Jail - мы не будем это рассматривать ось внутри оси довольно заморочено и плохо
документировано, а если все вхосты придется загонять в jail то мало непокажется.
Я пока небуду jail рассматривать :)

II) Настраиваем тыл внутренние защитные меры.

2.1) Ограничения ресурсов
Бывает так кроме основного действия PHP скрипта функция N зацикливается, попутно
вычисляя некое сложное действие. Как результат – высокая загрузка процессора.
Это очень типичная ситуация для хостинга. Чтобы предотвратить подобные ненамеренные
(и намеренные) атаки, необходимо ограничивать юзера в плане ресурсов. У *BSD для
таких целей существует система профилей пользователей. Это значит, что мы можем
легко ограничить ресурсы каждого пользователя в отдельности.
Открываем /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.
Теперь перейдем к настройке операционки. Открываем /etc/sysctl.conf и пишем туда
следующее:
# Запрещает юзерам видеть процессы соседа&root
security.bsd.see_other_uids=0
# Запрещает видеть групповые процессы
security.bsd.see_other_gids=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 остальные смотримMAN SYSCTL(8)
Есть статья Некоторые опции sysctl но она еще не совсем дописана (просьба просить lissyara чтобы доконца перевел ;)).
Многие параметры для sysctl можно изменять и динамически:
sysctl <параметр>=<значение>

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

Должно быть похоже на
# sysctl kern.maxprocperuid=1000
kern.maxprocperuid: 3546 -> 1000

Теперь необходимо продублировать часть настроек в /etc/rc.conf:
Дублируем настройки sysctl
icmp_drop_redirect="YES"
icmp_log_redirect="YES"
icmp_bmcastecho="NO"
tcp_drop_synfin="YES"


2.3) Логи
Очень важным аспектом системного администрирования является слежение за сервера.
Но ковырять логии самому заморочено тогда для ленивых  существует отличная утилита
logcheck ее и поставим.
# cd /usr/ports/security/logcheck && make install clean

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

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

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

Запускаем скрипт по крону, хотя бы раз в сутки. Дописываем в cron:
0 4 * * * /bin/sh /usr/local/etc/logcheck.sh

При большой активности хостящихся сайтов, логи веб-сервера начнут
занимать немало места. И в то же время их надо сохранять.
Можно использовать утилиту logrotate
# /usr/ports/sysutils/logrotate && make install clean


III) Общие меры

3.1) HDD
Сделаем в fstab некоторые изменения для предотвращения нехороших действий.
Укажем где и что можно и нельзя делать системе.

/dev/ad4s3b		none		swap	sw			0 0
/dev/ad4s3a		/		ufs	rw			1 1
/dev/ad4s3e		/tmp		ufs	rw,noexec		2 2
/dev/ad4s3f		/usr		ufs	rw			2 2
/dev/ad4s3f		/usr/home	ufs	rw,nosuid,nodev	        2 2
/dev/ad4s3d		/var		ufs	rw,nodev		2 2

noexec – эта опция дает понять что на данном разделе запрещено запускать что
либо даже правах на файл chmod 777 (Я знаю что некоторые защищенные сервера ломали
именно через /tmp :) в последствии админы советовали прикрывать эту дыру.
И незабываем, что в /tmp может писать почти любой сервис в системе)

nosuid – при этом значении система игнорирует suid-биты. Юзер не сможет сделать
#su и подняться до рута, даже если он знает его пароль рута и находится в группе
wheel (но необходимо понять что нужным юзверям которым нужно #su домашняя директория
будет /usr, а тем кого нужно ограничит директория будет /usr/home)

nodev – запрещаем создание\существование в данном разделе специальных устройств.

3.2) Доступ
Доступ к серверу следует ограничить. Т.е. серверы убрать в недоступное простым
смертным людям и закрыть на ключ. В дополнение не забываем, снять с них все причиндалы
мониторы клавы мышки и т.д. Для чего это должно быть понятно, например если я вижу
общедоступный \ физически сервер FreeBSD я тут же по любопытности хочу в него залезть
и поковыряться в нем. Но вы скажете, а как же пароль root и т.д. то слушаем дальше,
если вы забыли чужой пароль :) а так бывает то делаем так:

А) Загружаемся в однопользовательском режиме , для этого в приглашении загрузчика
введите boot –s
Б) Смонтируйте командой mount –u / корневой раздел в режим чтения-записи.
Затем с помощью mount –a примонтируем все что есть (т.е. только что указанно
в fstab без опции noauto)
B) Теперь меняйте пароль рута. :)

Чтобы люди не cмогли зайти без пароля рута в однопользовательском режиме делаем так:
# ee /etc/ttys

Измените в строчке console пункт secure на insecure. Если вы сделаете это,
FreeBSD даже при загрузке в однопользовательском режиме будет запрашивать пароль root.
Будьте осторожны при изменении этого значения на insecure. Если вы забудете пароль
root, загрузка в однопользовательский режим сильно усложнится.
Это все еще возможно, но несколько более сложно.
# name  getty                           type    status          comments
#
# If console is marked "insecure", then init will ask for the root password
# when going to single-user mode.
console none                            unknown off insecure


3.3) DNS
Засунем DNS в песочницу
# named –u 53 –t /var/named

-u – значение UID присваемое процессу named
-t – указывает корневой каталог для демона
Незабываем, что корневой каталог недолжен, быть пустым, он должен содержать все файлы
необходимые для нормальной работы демона. Если named скомпилирован так чтобы
библиотеки компоновались статически и не нужно было думать что ему надо еще в корневую
положить чтобы он запустился :) Так же некоторые советуют в конфиге DNS убрать строчку
об версии демона дескать оно сможет помочь атакующему и т.д. я не считаю это критически
она может подсказкой и самому админу.

Литература:
1) Unix руководство системного администратора (3 изд.)
2) Хакер спец 07/68/июль/2006
3) Жизнь :)

Статья дорабатывается все пожелания\дополнения на сюда.



размещено: 2007-05-13,
последнее обновление: 2007-05-22,
автор: Raven2000


sergei vasilyev, 2007-05-23 в 13:14:18

1) Нелишне было бы дописать, что noexec на /tmp не позволит выполнить апдейт системы и поэтому перед make installworld нужно выполнить mount -u -o exec /tmp

2) Я рекомендовал бы / и /usr  монтировать в ro, а /usr/local вынести на отдельный раздел.

tux, 2007-07-20 в 7:17:32

Статья толи из Хакера, толи из Спец-Хакера. Неплохо бы копирайты ставить...

Raven2000, 2007-07-23 в 13:48:20

to tux читать умеешь? см список Литература:
>Статья толи из
она то ли из хенбука толи и тд и тп она из всякой литературы + свое так что тема везде во всякой лит-ре светится так что я точно не первый :) ну и не последний :)

maserg, 2007-07-31 в 12:58:51

а кто сказал что можно в .htaccess воткнуть
php_flag safe_mode off  ?

из доки:
safe_mode - тип PHP_INI_SYSTEM  

PHP_INI_SYSTEM=Entry can be set in php.ini or httpd.conf

Andrew Kolchoogin, 2007-08-01 в 10:32:19

===
nosuid – при этом значении система игнорирует suid-биты. Юзер не сможет сделать
#su и подняться до рута, даже если он знает его пароль рута и находится в группе
wheel (но необходимо понять что нужным юзверям которым нужно #su домашняя директория
будет /usr, а тем кого нужно ограничит директория будет /usr/home)
===
Нет.

При наличии этого флага в fstab'е система будет игнорировать setuid-бит у бинарников, на этой файловой системе находящихся. 'su' там не лежит, и даже если у пользователя домашняя директория на этом разделе, всё будет прекрасно работать.

Viktorich, 2007-11-08 в 15:11:27

/dev/ad4s3d        /var        ufs    rw,nodev        2 2

nodev – запрещаем создание\существование в данном разделе специальных устройств.
# named –u 53 –t /var/named
разве bind в чруте не создаёт устройства ?

qbic, 2008-05-06 в 0:02:07

Что-то nodev у меня на /home и /var в седьмой версии фри
не пошел.... При загрузке ругается...

qbic, 2008-05-06 в 11:31:29

В FreeBSD 7.0 Release у mount отсутсвует опция nodev
увы и ах.

qbic, 2008-05-06 в 11:40:50

Более того при установке этой опции nodev на /home -
система перестает нормально грузиться - приходится в однопользовательском режиме монтировать / в режиме rw
и монтировать /usr чтобы убрать в fstab эту строчку.
После этих действий все начинает жить штатно.

Serj7770, 2009-01-21 в 22:40:50

Хмм
Syntax error on line 19 of /usr/local/etc/apache22/vhosts/7770.net.ru.conf:
Invalid command 'SecFilterEngine', perhaps misspelled or defined by a module not included in the server configuration

anonymous, 2009-03-23 в 13:10:40

Serj7770, модуль подключите

shirker, 2009-06-06 в 13:05:30

Не зобывам, що для апача 2 и 22 у мод_секьюрити другой синтакс: http://www.modsecurity.org/documentation/ModSecurity-Migration-Matrix.pdf

   SecRuleEngine On
   SecRequestBodyAccess On
   SecResponseBodyAccess Off
   # Handling of file uploads
   # TODO Choose a folder private to Apache.
   # SecUploadDir /opt/apache-frontend/tmp/
   SecUploadKeepFiles Off
   # Debug log
   SecDebugLog /var/log/httpd/modsec_debug.log
   SecDebugLogLevel 0
   # Serial audit log
   SecAuditEngine RelevantOnly
   SecAuditLogRelevantStatus ^5
   SecAuditLogParts ABIFHZ
   SecAuditLogType Serial
   SecAuditLog /var/log/httpd/modsec_audit.log
   SecDefaultAction "deny,log,phase:1,status:500"
   # Maximum request body size we will
   # accept for buffering
   SecRequestBodyLimit 131072
   # Store up to 128 KB in memory
   SecRequestBodyInMemoryLimit 131072
   # Buffer response bodies of up to
   # 512 KB in length
   SecResponseBodyLimit 524288
   # Перекрываем dots-bug
      SecRule REQUEST_URI|QUERY_STRING "\.\./"
   # Не забываем про XSS
   SecRule REQUEST_URI|QUERY_STRING "<(.|\n)+>"
   # SQL injection, куда же без него :)
   SecRule REQUEST_URI|QUERY_STRING "<[[:space:]]*script"
   SecRule REQUEST_URI|QUERY_STRING "delete[[:space:]]+from"
   SecRule REQUEST_URI|QUERY_STRING "insert[[:space:]]+into"
   SecRule REQUEST_URI|QUERY_STRING "select.+from"

shirker, 2009-06-06 в 13:16:10

в последних строчках предыдущего поста ошибся :(
вот пример праильного правила:
# Blind SQL injection
SecRule REQUEST_FILENAME|ARGS|ARGS_NAMES|REQUEST_HEADERS|!REQUEST_HEADERS:Referer "(?:\b(??(?:ys\.(?:user_(??:t(?:ab(?:_column|le)|rigger)|object|view)s|c(?nstraints|atalog))|all_tables|tab)|elect\b.{0,40}\b(?ubstring|asci i|user))|m(?ys(??:queri|ac)e|relationship|column|object)s|ysql.user)|c(?nstraint_type|harindex)|attnotnull)\b|(?:locate|instr)\W+\()|\@\@spid\b) " \
"capture,t:replaceComments,ctl:auditLogParts=+E,log,auditlog,msg:'Blind SQL Injection Attack. Matched signature <%{TX.0}>',id:'950007',severity:'2'"

Моё имя, 2009-06-26 в 12:39:53

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

it, 2009-11-12 в 12:59:34

# Перекрываем возможность передачи переменных PHP
SecFilterSelective ARG_b2inc "!^$"

что-то мне показалось что тут только для b2 мы перекрываем, а не для всего php

BSD, 2011-06-18 в 22:44:28

Забросил автор это нужное дело похоже.. даже найденные ошибки так и не обновил... Грустно!

Raven2000, 2011-06-19 в 10:39:16

2BSD
Стыдно, буду переписывать к концу месяца. =)

Константин, 2011-06-22 в 15:57:50

Буду очень благодарен за обновление/оживление статьи.
Материал видно сырой, но если было актуальное такое пособие, было бы очень круто. Постарайся доделать ее толково, будем очень благодарны!!! :)

Мфынф, 2011-07-08 в 8:08:23

Хуйня полная.
А где же собствено защита от доса?



 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.0437 секунд
Из них PHP: 35%; SQL: 65%; Число SQL-запросов: 77 шт.
Исходный размер: 57362; Сжатая: 15451