Личный блог Suvan`a.

Работая и играя с Linux... И что из этого иногда получается.

Защита DNS: продолжение.

Рубрика: Безопасность -> Защита сервисов
Метки: | |
Среда, 9 сентября 2009 г.
Просмотров: 6428
Подписаться на комментарии по RSS

     Запуск BIND от имени непривилегированного пользователя.

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

     Начиная с версии 8.1.2, появилась возможность запуска BIND от имени простого пользователя. Прежде BIND стартует от имени root - для того, чтобы сесть на 53 порт, а затем сбрасывает полномочия root и принимает полномочия указанного с помощью опции -n пользователя:

# named -n named
     Для запуска named нужно создать новую учетную запись, а не запускать от имени nobody, от имени которого и так запущено много процессов.


     Так как BIND считывает файл конфигурации /etc/named.conf перед тем, как сбрасывает полномочия root, то не надо изменять права доступа к этому файлу. Однако придется модифицировать права доступа и владельца для каталога /var/named и для всех файлов, которые в нем содержатся:

сhown -R named /var/named

chmod 700 /var/named

chmod 600 /var/named/*

     BIND протоколирует свой PID в /var/run/named/named.pid. Нужно убедится, что владельцем /var/run/named представляется пользователь named, и установить права 700.

     BIND и chroot.

     Кроме запуска BIND от имени непривилегированного пользователя, желательно еще и запустить его в chroot-окружении. Концепция создания chroot-окружения описана здесь, поэтому сейчас можно приступить к ее практической реализации для BIND.

     Сначала нужно создать структуру каталогов. Chroot-дерево для BIND поместим в каталог /chroot/named:

mkdir /chroot/named/

cd /chroot/named

mkdir -p dev etc lib usr/sbin var/named var/run var/log usr/share

     Нужно скопировать файл конфигурации named в дерево chroot и создайть устройство /chroot/named/dev/null:

cр /etc/named.conf /chroot/named/etc

mknod /chroot/named/dev/null с 3 1

     Проверим, какие библиотеки требует named:

# ldd /usr/sbin/named

liblwres.so.l => /usr/lib/liblwres.so.l (0x4001b000) libdns.so.5 => /usr/lib/libdns.so.5 (0x4002a000) libcrypto.so.2 => /lib/libcrypto.so.2 (0x40114000) libisccfg.so.2 => /usr/lib/libisccfg.so.0 (0x401d8000) libidccc.so.O => /usr/lib/libisccc.so.0 (0x401e7000) libisc.so.4 => /usr/lib/libisc.so.4 (0x401e7000) libnsl.so.l => /iib/libnsl.so.l (0x4021f000) libpthread.so.0=> /lib/i686/libpthread.so.0 (0x40235000) libc.so.6 => /lib/i686/libc.so.6 (0x42000000) libdl.so.2 => /lib/libdl.so.2 (0x40249000) /lib/ld-linux.so.2 => /lib/ld-linux-so.2 (0x40000000)

     Нужно будет скопировать каждую из этих библиотек в chroot-окружение (набор библиотек может варьироваться в зависимости от версии BIND).

После этого надо отредактировать системный сценарий инициализации syslogd, добавив опцию -a /var/log/named.log - как это было сделано с Apache чуть раньше в данном разделе.

     Потом скопируйте исполнимые файлы BIND (обычно находятся в /usr/sbin) в chroot-окружение:

# ср /usr/sbin/named* /chroot/named/usr/sbin

     Теперь надо скопировать информацию о часовом поясе:

# ср /usr/share/zoneinfo/GMT /chroot/named/usr/share/zoneinfо

# ln -s /chroot/named/usr/share/zoneinfo/GMT /chroot/named/etc/localtime

     BIND поддерживает системный вызов chroot, поэтому вместо команды /sbin/chroot /chroot/named /usr/sbin/named можно просто записать:

# /chroot/named/usr/sbin/named -t /chroot/named

     Это избавляет от потребности копирования файлов /etc/passwd и /etc/shadow в «песочницу»: named прочитает их до вызова chroot().

     Если named запускается с помощью сценария /etc/rc.d/init.d/named, то нужно будет отредактировать функцию start(). Для лучшей читаемости рекомендуется добавить опции named в переменную OPTIONS, которая находится в самом начале сценария:

OPTIONS = "-u named -t /chroot/named" ПОДПИСИ

     Транзакции (TRANSACTION SIGNATURES, TSIG).

     Слабость BIND заключается в том, что он использует аутентификацию, основанную на IP-адреса узла, к примеру, на вторичном сервере указывается IP-адрес первичного сервера, а на первичном - IP-адреса вторичных серверов. Так как DNS-трафик передается по протоколу UDP (TCP применяется, только если сообщение слишком огромное для UDP) - по протоколу, не требующему соединения, адрес отправителя легко может быть подделан крекером.

     Если крекер подделал IP-адрес вторичного сервера, то он может получить всю информацию о зоне. А если он подделал адрес сервера, что более опасно, он сможет контролировать зоны вторичных серверов, добавляя нужные ему записи. Затем он использует DoS-атаку и делает первичный сервер недоступным. В результате данного все компьютеры сети будут употреблять вторичный сервер имен, а его информация о зоне уже будет «отравлена» хакером.

     Начиная с версии 8.2, BIND поддерживает концепцию подписей транзакции (TSIG) - это метод аутентификации DNS-серверов. TSIG добавляет криптографическую подпись к заголовку DNS-сообщения (само сообщения при данном не кодируется), которая обеспечивает целостность полезного DNS-сообщения, и тоже служит гарантией того, что отправитель этого сообщения действительно именно тот, кто нужен, а не кто-то другой. Для кодирования подписи применяется вариация 128-битного алгоритма MD5 - HMAC-MD5.

Заголовок TSIG тоже содержит время подписания сообщения, так как клиент настроен на прием сообщений только в пределах определенного временного окна, что позволяет избежать атаки повтора.

     Хотя теоретически возможно применение TSIG для подписания запросов клиентов, на практике TSIG применяется только между первичным и вторичными серверами имен.

     Генерация ключа.

     Для включения TSIG первым делом можно сгенерировать ключ для первичного и вторичных серверов. В RFC 2845 сказано, что имя ключа должно содержать имена серверов, между которыми он будет применяться, к примеру, если первичный сервер называется ns1.test.net, а вторичный - ns2.test.net, тогда ключ будет называться или ns1-ns2.test.net, или ns1_ns2.test.net.

     В BIND 9 для генерации ключей применяется утилита dnssec-keygen:

dnssec-keygen -а <алгоритм> -B <размер ключа> -n HOST <имя ключа>

     Опция -а прописывает употребляемый алгоритм (обычно HMAC-MD5), опция -B указывает размер ключа (RFC 2824 рекомендует употреблять размер ключа 128 битов). Параметр HOST в опции -n указывает на то, что создается ключ узла. Последний параметр - это имя ключа. Например:

# dnssec-keygen -a HMAC-MD5 -B 128 -n HOST ns1-ns2.test.net. Kns1-ns2.test.net.+357+64762

     Последняя точка - это конец имени ключа. Команда выводит имена файлов ключей, которые были сгенерированы (ключи будут записаны в текущий каталог):

# ls -l 

Kns1-ns2.test.net <http://Kns1-ns2.test.net>.+357+64762* -rw 1 root root 81 Aug 7 15:13

Kns1-ns2.test.net.+357+64762.private -rw 1 root root 63 Aug 7 15:13

Kns1-ns2.test.net.+357+64762.key

# cat Kns1-ns2.test.net.+357+64762.private

Private-key-format: v1.2

Algorithm: 157 (HMAC_MD5) Key: pdlOIv+OcOKdkeKJuzA+yQ==

# cat Kns1-ns2.test.net.+357+64762.key

ns1-ns2.test.net <http://ns1-ns2.test.net>. IN KEY 512 3 157 pdlOIv+OcOKdkeKJuzA+yQ==

     Добавление ключей в /etc/named.conf.

     Следующий шаг - добавление ключей в конфигурационные файлы (/etc/named.conf) обоих серверов имен. Синтаксис следующий:

key ns1-ns2.test.net.  

{ algorithm hmac-md5; secret "pdlOIv+OcOKdkeKJuzA+yQ==";

};

     Нужно убедиться, что ключ и имя ключа не перепутаны.

     Так как ключи - это очень важная информация, нельзя допустить, чтобы ее прочитал хакер. Ключи должны быть доступны только пользователю root - установите права 600 для named.conf (chmod 600 named.conf).

     Если это невозможно (к примеру, надо, чтобы остальные пользователи редактировали этот файл), нужно указать ключи в другом файле (для которого установлены права 600), а потом подключить этот файл к файлу конфигурации named.conf:

include "/etc/dhs.ns1-ns2.test.net.keys"

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

     Несколько ключей.

     На узле надо определить несколько ключей (для каждого компьютера, с которым устанавливается подписанная транзакция), поэтому надо указать BIND'y, какой ключ и для какого узла надо применять. В конкретном примере есть два сервера - первичный и вторичный. Первичный должен применять ключ для связи со вторичным, а вторичный должен применять ключ для связи с первичный сервером. Пусть 10.0.0.1 - это IP-адрес сервера ns1.test.net, a 10.0.0.2 - IP-адрес сервера ns1.test.net.

     Па первичном сервере надо добавить следующий код в файле /etc/named.conf:

server 10.0.0.2 { keys {

"/etc/dhs.ns1-ns2.test.net.keys";

};

     На вторичном сервере надо добавить этот код:

server 10.0.0.1 {

   keys {

   "/etc/dhs.ns1-ns2.test.net.keys";

   };

};

     После данного нужно перезагрузить оба сервера (kill -HUP), чтобы они перечитали заново файл конфигурации.

Оставьте комментарий!

Не регистрировать/аноним

Используйте нормальные имена.

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email.
(При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д.)



(обязательно)