защита производственных Linux-систем: практическое руководство по основам безопасности

продолжение. начало в №2 (2005).

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

Во многих случаях будет полезно ограничить некоторым группам пользователей доступ к системе по определенным дням недели или в определенное время суток. Следующий пример призван показать, как запретить удаленный доступ для, например, подрядчиков. Они получат доступ к серверу с помощью SSH строго по будним дням (понедельник – пятница) с 8 00 до 17 00.
Для установки ограничений на любые логины по признаку даты и времени дополните /etc/pam.d/sshd модулем pam_time. Это делается так:
auth required /lib/security/$ISA/pam_env.so
auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
auth required /lib/security/$ISA/pam_deny.so
account required /lib/security/$ISA/pam_unix.so
account required /lib/security/$ISA/pam_time.so
account sufficient /lib/security/$ISA/pam_succeed_if.so uid< 100 quiet
account required /lib/security/$ISA/pam_permit.so
password requisite /lib/security/$ISA/pam_cracklib.so retry=3
password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow
password required /lib/security/$ISA/pam_deny.so
session required /lib/security/$ISA/pam_limits.so
session required /lib/security/$ISA/pam_unix.so

Кроме этого, добавьте к файлу /etc/security/time.conf строку
*;*;contractor1|contractor2|contractor3;Wk0800-1700

Первое поле определяет сервис (login, su и т.д.). Второе поле задает tty. Третье – перечисляет имена всех пользователей, чьи права на доступ должны быть ограничены. Последнее поле определяет временной промежуток: понедельник - пятница (Wk) с восьми утра до пяти вечера (0800-1700). Других пользователей данное ограничение не коснется. Постарайтесь не запретить по ошибке доступ руту!

запрет прямого доступа для системных и общих аккаунтов

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

В некоторых ситуациях вам все-таки может потребоваться разрешить прямой доступ к системным или общим аккаунтам. Например, в кластере Oracle вам необходимо разрешить прямые ssh-соединения для пользователя oracle. Однако в такой среде вы защищаете кластер от входящих ssh-соединений целиком, рассматривая его как единую систему. Таким образом, прямые соединения oracle не будут работать, если вы попытаетесь осуществить их с узла, не являющегося частью кластера. Далее мы рассмотрим подробный пример действий в такой ситуации.

Обычно у всех системных и общих аккаунтов есть объединяющая их черта: они не принадлежат к группе “users”. Следующий пример подразумевает, что все аккаунты пользователей находятся в группе “users”, а системные и общие к ней не относятся. Если вы захотите пойти еще дальше, неплохим решением будет создать новую группу пользователей logingroup, которая будет включать пользователей с определенным уровнем доступа.

Мы будем запрещать прямые соединения для:
- ssh-логинов(/etc/pam.d/sshd);
- сonsole-логинов(/etc/pam.d/login);
- графических Gnome-логинов (/etc/pam.d/gdm);
- всех остальных логинов(/etc/pam.d/system-auth).

Для достижения этой благой цели я предлагаю добавить к конфигурационному файлу PAM модуль pam_access. Этот модуль реализует контроль доступа на основе имен логинов, хостов, IP-адресов и других признаков. Тип модуля PAM, который будет использован в конфигурационных файлах – account. Данный тип модуля производит авторизацию. Это значит, что он принимает решение: может ли пользователь получить доступ? Не путайте данный модуль с модулем auth, который производит аутентификацию, то есть, например, проверяет пароль. Мы будем использовать контрольный флаг required. Для работы с ssh-логинами добавьте к файлу /etc/pam.d/sshd модуль pam_access:
auth required pam_stack.so service=system-auth
auth required pam_nologin.so
account required /lib/security/pam_access.so
account required pam_stack.so service=system-auth
password required pam_stack.so service=system-auth
session required pam_stack.so service=system-auth

Для обработки console-логинов добавьте модуль pam_access к файлу /etc/pam.d/login:
auth required pam_securetty.so
auth required pam_stack.so service=system-auth
auth required pam_nologin.so
account required /lib/security/pam_access.so
account required pam_stack.so service=system-auth
password required pam_stack.so service=system-auth
session required pam_selinux.so close
session required pam_stack.so service=system-auth
session optional pam_console.so
session required pam_selinux.so multiple open

Для графических Gnome-логинов добавьте pam_access к файлу /etc/pam.d/gdm:
auth required pam_env.so
auth required pam_stack.so service=system-auth
auth required pam_nologin.so
account required /lib/security/pam_access.so
account required pam_stack.so service=system-auth
password required pam_stack.so service=system-auth
session required pam_stack.so service=system-auth
session optional pam_console.so

Если вы просто желаете установить ограничения для всех логинов вашей системы, то вместо правки всего набора конфигурационных файлов PAM просто добавьте модуль pam_access к /etc/pam.d/system-auth:
auth required /lib/security/$ISA/pam_env.so
auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
auth required /lib/security/$ISA/pam_deny.so
account required /lib/security/$ISA/pam_access.so
account required /lib/security/$ISA/pam_unix.so
account sufficient /lib/security/$ISA/pam_succeed_if.so uid< 100 quiet
account required /lib/security/$ISA/pam_permit.so
password requisite /lib/security/$ISA/pam_cracklib.so retry=3
password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow
password required /lib/security/$ISA/pam_deny.so
session required /lib/security/$ISA/pam_limits.so
session required /lib/security/$ISA/pam_unix.so

Теперь добавьте в конфигурационный файл /etc/security/access.conf новую строку:
-:ALL EXCEPT users :ALL

Модуль pam_access читает конфигурационный файл /etc/security/access.conf, который определяет, что никакие пользователи, кроме пользователей из группы users не будут приняты системой. Поскольку в приведенном выше конфигурационном файле PAM модуль pam_access был настроен для работы в режиме “Authorization” (account), он запретит прямой доступ для всех аккаунтов, кроме упомянутых в группе users.

ВНИМАНИЕ: данный пример будет работать, только в том случае, если в системе еще не существует аккаунта users и он не прописан в файле /etc/passwd. Если это условие не соблюдается, удалите аккаунт users или же используйте для своей группы другое имя.
В некоторых системах, подобных кластерам Oracle RAC, для аккаунта oracle приходится включать возможность прямого ssh-соединения в пределах кластера. В таких случаях вы можете сделать это путем добавления или правки нескольких строк файла /etc/security/access.conf:
-:ALL EXCEPT users oracle:ALL
-:oracle:ALL EXCEPT rac1cluster rac2cluster rac3cluster

Первая строка разрешает для oracle прямые соединения. Вторая строка служит для уточнения – соединения будут приниматься только от узлов Oracle RAC (rac1cluster, rac2cluster и rac3cluster), которые входят в состав кластера.

запрет доступа посредством su к системе и общим аккаунтам

В данном разделе будет рассказано о запрещении подключения с помощью su к системным и общим аккаунтам даже в тех случаях, когда пользователю известен пароль. Как обычно, мы будем опираться на конкретный пример. В данном случае мы запретим определенной группе пользователей доступ с помощью su к аккаунтам root, oracle и postgres.
ВНИМАНИЕ: документация на модуль pam_wheel, включенная во многие дистрибутивы Linux, не совсем точна. Так, например, в Red Hat Advanced Server 2.1 модуль pam_wheel запрещает соединение посредством su не только к аккаунту root, как это было раньше, а к любому аккаунту.
Пример запрета доступа с помощью su к аккаунтам root, oracle и postgres.
Создайте новую группу для каждого подмножества пользователей, которым будет разрешено применять su для соединения с аккаунтами root, oracle и postgres:
# groupadd rootmembers
# groupadd oraclemembers
# groupadd postgresmembers

Добавьте к созданным группам всех пользователей, которым будет разрешен такой доступ. Далее необходимо составить условия на предоставление доступа с помощью su:
- только admin1 может использовать su для соединения с root, oracle и postgres;
- только oracledba1 может использовать su для соединения с oracle;
- только postgresdba1 может использовать su для соединения с postgres;
- никто другой на данной системе не может использовать su для доступа к какому-либо аккаунту.
Соответствующие команды таковы:
# usermod -G rootmembers adminuser1
# usermod -G oraclemembers oracleuser1
# usermod -G postgresmembers postgresuser1

Как вы, вероятно, заметили, я не добавлял adminuser1 к другим группам. Вместо этого я предоставил ему возможность соединения посредством su с аккаунтами oracle и postgres без добавления его в группы oraclemembers и postgresmembers. Я рассматриваю рутовые аккаунты администраторов в качестве исключения – их не надо добавлять ко всем группам пользователей системы.
Следующий шаг – добавление трех строк в файл /etc/pam.d/su (выделены жирным):
auth sufficient /lib/security/$ISA/pam_rootok.so
auth required /lib/security/$ISA/pam_stack.so service=system-auth
auth sufficient /lib/security/$ISA/pam_stack.so service=su-root-members
auth sufficient /lib/security/$ISA/pam_stack.so service=su-other-members
auth required /lib/security/$ISA/pam_deny.so
account required /lib/security/$ISA/pam_stack.so service=system-auth
password required /lib/security/$ISA/pam_stack.so service=system-auth
session required /lib/security/$ISA/pam_selinux.so close
session required /lib/security/$ISA/pam_stack.so service=system-auth
session required /lib/security/$ISA/pam_selinux.so open multiple
session optional /lib/security/$ISA/pam_xauth.so

Эти строки запрещают кому бы то ни было использовать su для работы с любым аккаунтом до тех пор, пока один из PAM-сервисов (su-root-members или su-other-members) не даст на это добро. Контрольный флаг sufficient означает, что это разрешение обойдет остальные аутентификационные модули и будет выдано общее разрешение на доступ. Отказ означает, что не прошедший аутентификацию сервис игнорируется. Если не будут пройдены оба аутентификационных сервиса, тогда запрашивается последний аутентификационный модуль pam_deny, что накладывает запрет на все запросы для всех доступных аутентификационных модулей. Это значит, что аутентификационная система не примет команду su.
Вам потребуется создать два новых конфигурационных файла. Это etc/pam.d/su-root-members и /etc/pam.d/su-other-members.
Файл etc/pam.d/su-root-members, ссылка на который создается в etc/pam.d/su, должен выглядеть так:
auth required /lib/security/pam_wheel.so use_uid group=rootmembers
auth required /lib/security/pam_listfile.so item=user sense=allow onerr=fail file=/etc/security/su-rootmembers-access

Ссылка на файл /etc/security/su-rootmembers-access ставится в /etc/pam.d/su-root-members, а сам файл должен содержать следующие строки:
root
oracle
postgres

Контрольный флаг required означает, что положительное значение («Success») должны вернуть оба модуля. В обратном случае данный PAM-сервис выдаст отрицательное значение PAM-сервису su, настроенному в /etc/pam.d/su. Первая строка вернет значение «Success» только если пользователь зарегистрирован в группах rootmembers. Вторая строка разрешает доступ (sense=allow) только к тем пользователям, которые обозначены в /etc/security/rootusername, то есть root, oracle и postgres. Только их имена будут приняты в качестве аргументов su. Аргумент item=user сообщает pam_listfile, что значения в /etc/security/rootusername – это имена пользователей. Если возникает ошибка, например, если не получится прочитать конфигурационный файл, то доступ запрещается (onerr=fail).
ВНИМАНИЕ: поскольку su-доступ к руту работает для пользователей rootmembers, я бы рекомендовал впоследствии не вносить какие бы то ни было правки в файл /etc/pam.d/su-root-members. Если вы допустите там ошибку, то можете запретить доступ к руту для всех пользователей системы. Чтобы избежать этого, я создал два файла PAM: /etc/pam.d/su-root-members для членов группы rootmembers и /etc/pam.d/su-other-members для всех остальных, поскольку довольно высока вероятность того, что вам придется добавлять в этот файл дополнительные группы.
Следующий этап – создание файла /etc/pam.d/su-other-members, на который есть ссылка в /etc/pam.d/su. Его содержание должно быть таким:
auth sufficient /lib/security/pam_stack.so service=su-oracle-members
auth sufficient /lib/security/pam_stack.so service=su-postgres-members
auth required /lib/security/pam_deny.so

Если один из двух PAM-сервисов вернет положительный ответ, то этот ответ передается PAM-сервису su, который сконфигурирован в /etc/pam.d/su. В противном случае будет вызван последний модуль, что приведет к выдаче отказов на все пользовательские запросы, то есть аутентификация пройдена не будет.
Далее необходимо создать PAM-сервисы su-oracle-members и su-postgres-members.
Файл /etc/pam.d/su-oracle-members, упомянутый в /etc/pam.d/su-other-members, должен выглядеть примерно так:
auth required /lib/security/pam_wheel.so use_uid group=oraclemembers
auth required /lib/security/pam_listfile.so item=user sense=allow onerr=fail file=/etc/security/su-oraclemembers-access

Файл /etc/security/su-oraclemembers-access, упомянутый в /etc/pam.d/su-oracle-members, должен содержать строку
oracle

Файл /etc/pam.d/su-postgres-members, упомянутый в /etc/pam.d/su-other-members, в свою очередь, должен включать следующие записи:
auth required /lib/security/pam_wheel.so use_uid group=postgresmembers
auth required /lib/security/pam_listfile.so item=user sense=allow onerr=fail file=/etc/security/su-postgresmembers-access

Наконец, файл /etc/security/su-postgresmembers-access, упомянутый в /etc/pam.d/su-postgres-members, должен выглядеть так:
postgres

Теперь следует убедиться, что adminuser1 сможет подключиться к root, oracle и postgres. Кроме него больше никто не должен обладать полномочиями на работу с root. Oracleuser1 должен иметь возможность соединяться только с oracle, а postgresuser1 - с postgres. Никто из других пользователей системы, даже зная пароль, не должен получить право использовать su для соединения с каким бы то ни было аккаунтом.

запрет доступа к системе других серверов и сетей

Для защиты сервера от воздействия внешних серверов и сетей обычно применяют файрволл. Кроме файрволла, в некоторых случаях вам может пригодится TCP wrapper.
Входящий в состав большинства дистрибутивов сервер Xinetd располагает собственным TCP wrapper’ом. Он может быть использован для точного определения сетевых сервисов, принимающих входящие соединения от заданных серверов и сетей. TCP wrapper контролирует доступ, руководствуясь сведениями из двух файлов: /etc/hosts.allow и /etc/hosts.deny. Обратите внимание на то, что файл hosts.allow обладает более высоким приоритетом по сравнению с файлом hosts.deny. Вам также потребуется изменить права доступа для конфигурационных файлов, поскольку прочитать их может любой желающий (они выставлены как world-readable).
Рекомендованная стратегия обеспечения безопасности состоит в блокировке по умолчанию всех входящих соединений с разрешением доступа для четко заданного перечня хостов и сетей. Именно такая схема и будет рассматриваться далее.
Для запрета по умолчанию всех соединений, добавьте в файл /etc/hosts.deny строку
ALL: ALL

Для разрешения приема входящих ssh-соединений от, например, узлов rac1cluster, rac2cluster и rac3cluster, добавьте к /etc/hosts.allow строку
sshd: rac1cluster rac2cluster rac3cluster

Для того чтобы разрешить входящие ssh-соединения от всех серверов определенной сети, добавьте ее имя в /etc/hosts.allow. Вот пример:
sshd: rac1cluster rac2cluster rac3cluster .subnet.example.com

Принимать входящие portmap-соединения с IP-адреса 192.168.0.1 и подсети 192.168.5 вы сможете после того, как добавите в /etc/hosts.allow еще одну строку:
portmap: 192.168.0.1 192.168.5.

Для того, чтобы принимать соединения от всех серверов подсети .subnet.example.com, но не принимать от сервера cracker.subnet.example.com, вам следует добавить в /etc/hosts.allow строку
ALL: .subnet.example.com EXCEPT cracker.subnet.example.com

Приведем еще несколько примеров, демонстрирующих некоторые возможности TCP wrapper’а.
Если вы просто желаете запретить ssh-соединения без настройки или вообще использования /etc/hosts.deny, то вы можете просто добавить в /etc/hosts.allow следующие строки:
sshd: rac1cluster rac2cluster rac3cluster
sshd: ALL: DENY

Версия TCP wrapper’а, включенная в состав Red Hat, поддерживает некоторые дополнительные функции, описанные в соответствующей документации. Для примера покажем, как в файле /etc/hosts.allow может быть вызвана дополнительная программа
sshd: ALL : spawn echo "Login from %c to %s" | mail -s "Login Info for %s" log@loghost

Просмотреть дополнительную информацию о расширениях вы сможете с помощью команды "man 5 hosts_access".
TCP wrapper – это довольно гибкая штука. Кроме того, xinetd располагает собственным набором функций контроля доступа, основанных на различных признаках (например, по хосту или по времени). Настоятельно рекомендую поискать в Сети и внимательно изучить документацию на xinetd.
предотвращение отказа в обслуживании (DoS)

Linux позволяет устанавливать ограничения на системные ресурсы, выделяемые пользователям и группам. Это весьма удобно, поскольку ошибки в отдельных прикладных программах, вызывавшие неожиданно высокое потребление ресурсов, не смогут привести к замедлению работы всей системы. Особенности производственной рабочей среды вызывают закономерный интерес к данной возможности.
Дополнительную информацию вы можете получить в одной из моих статей
(http://www.puschitz.com/TuningLinuxForOracle.shtml#SettingShellLimitsForTheOracleUser)– там содержится пример практического использования модуля pam_limits и настройки файла /etc/security/limits.conf.

проверка прав доступа и принадлежности файлов

настройка значений umask по умолчанию
Umask (user file-creation mode mask) – это встроенная в оболочку команда, определяющая права доступа, по умолчанию назначаемые всем новым файлам при их создании. Это значение может быть перезаписано системными вызовами многих программ и утилит, использующих umask.
По умолчанию Red Hat устанавливает для umask значение 022 или 002, что весьма неплохо. Если имя пользовательского аккаунта и группового аккаунта совпадают, а UID – 100 или больше, то значение umask будет установлено как 002, в других случаях – 022.
$ id
uid=509(test) gid=510(test) groups=100(users),510(test) context=user_u:system_r:unconfined_t
$ umask
0002
$
# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=root:system_r:unconfined_t
# umask
0022
#

Вот пример работы umask:
$ umask 000
$ touch file1
$ ls -l file1
-rw-rw-rw- 1 oracle oinstall 0 Dec 26 19:24 file1
$ umask 002
$ touch file2
$ ls -l file2
-rw-rw-r-- 1 oracle oinstall 0 Dec 26 19:24 file2
$ umask 022
$ touch file3
$ ls -l file3
-rw-r--r-- 1 oracle oinstall 0 Dec 26 19:25 file3
$


Настройки umask для оболочки bash вы можете найти в файле /etc/bashrc. Этот файл предназначен для общесистемных алиасов и функций и вызывается ~/.bashrc.

SUID и SGID
Когда в исполняемом файле установлены биты SUID или SGID, он выполняется с UID или GID владельца исполняемого файла, а не того, кто пытается его запустить. Это означает, что исполняемые файлы, у которых бит SUID установлен рутом и принадлежит руту, будут выполняться с UID рута. Хорошим примером будет команда passwd, которая позволит обычному пользователю обновить поле пароля в файле /etc/shadow, который, вообще-то принадлежит руту.
Однако при появлении дыры в безопасности суидного исполняемого файла значение битов SUID/SGID может быть неправильно истолковано. Поэтому вам потребуется произвести на своей системе поиск и документирование всех исполняемых SUID/SGID-файлов. Убедитесь, что ваши программисты устанавливают биты SUID/SGID в своих приложениях, только если это абсолютно и категорически необходимо. Зачастую применяются приемы вроде удаления исполняемых битов только для world/others. Однако, если это только возможно, лучше исправьте такую программу.
Поиск SUID- и SGID-файлов в системе проводится командой

find / -path /proc -prune -o -type f -perm +6000 –ls

Опция -prune в данном примере использована для пропуска файловой системы /proc.

world-writable файлы
Поскольку данные файлы могут быть изменены любым желающим, они представляют угрозу для безопасности системы. Кроме этого, во world-writable каталогах любой прохожий сможет создавать и удалять файлы.
Обнаружить такие файлы и каталоги можно с помощью команды
find / -path /proc -prune -o -perm -2 ! -type l -ls

Параметр "! -type l" пропускает все символические ссылки, поскольку они всегда являются world-writable. Это не представляет опасности, если объект ссылки не является world-writable, а это можно проверить уже приведенной выше командой find.
World-writable каталоги с промежуточным битом (sticky bit), например, /tmp, не дают посторонним возможности изменять или удалять принадлежащие им файлы. Он закрепляет файлы за создавшим их пользователем и предотвращает переименование либо удаление файлов другими пользователями. В зависимости от назначения, каталог с промежуточным битом обычно не создает проблем связанных с безопасностью. Пример – каталог /tmp:
$ ls -ld /tmp
drwxrwxrwt 18 root root 16384 Dec 23 22:20 /tmp

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

«ничейные» файлы
Файлы, не принадлежащие ни одному пользователю или группе, сами по себе не являются угрозой безопасности. Однако на проходящих аудит системах их быть не должно. Если, допустим, при создании нового пользователя он случайно получит UID, совпадающий с UID «ничейного» файл, то он автоматически станет его владельцем. Для того чтобы отыскать такие объекты, выполните команду
find / -path /proc -prune -o -nouser -o -nogroup

защита NFS

базовые сведения
Как и любой другой сетевой сервис, NFS (Network File System) может представлять угрозу безопасности системы. Вот несколько основных правил использования NFS:
- Не следует активировать NFS, если в ней нет насущной необходимости.
- Если вам надо применять NFS, используйте для запрета удаленного доступа TCP-упаковщик.
- Убедитесь, что вы работаете только с теми машинами, с которыми вам необходимо работать.
- Для затруднения попыток спуфинга используйте полностью определенные (fully qualified) доменные имена.
- Экспортируйте только те каталоги, которые нужно экспортировать.
- Где только возможно работайте в режиме read-only.
- Используйте NFS поверх TCP.
Если вы не планируете ничего экспортировать, удостоверьтесь, что NFS НЕ запущена:
# service nfs status
rpc.mountd is stopped
nfsd is stopped
rpc.rquotad is stopped
# chkconfig --list nfs
nfs 0:off 1:off 2:off 3:off 4:off 5:off 6:off
#

Возможно, что вам также не будет нужен сервис portmap, поскольку он используется NFS (демон portmap регистрирует сервисы, основанные на rpc для сервисов типа NFS и NIS):
# service portmap status
portmap is stopped
# chkconfig --list portmap
portmap 0:off 1:off 2:off 3:off 4:off 5:off 6:off
#


включение и запуск сервера NFS
Если вы решили использовать NFS, то активировать ее в Red Hat можно следующей командой:
chkconfig portmap on
chkconfig nfs on
service portmap start
service nfs start

Сервис "portmap" запускает демон portmap. В зависимости от дистрибутива и версии Linux, сервис “nfs” запускает демоны rpc.rquotad, nfsd, lockd, rpciod, rpc.mountd и rpc.idmapd. Это относится к Red Hat Fedora Core 3 на которой будет основан Red Hat Advanced Server 4. В Red Hat Advanced Server 3 сервис NFS запускает rpc.mountd, nfsd и rpc.rquotad.
Для проверки зеркалирования портов для всех RPC-программ, использующих NFS, можно запустить rpcinfo. В Red Hat Advanced Server 3 результат будет выглядеть так:
# rpcinfo -p
program vers proto port
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100011 1 udp 607 rquotad
100011 2 udp 607 rquotad
100011 1 tcp 610 rquotad
100011 2 tcp 610 rquotad
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100005 1 udp 623 mountd
100005 1 tcp 626 mountd
100005 2 udp 623 mountd
100005 2 tcp 626 mountd
100005 3 udp 623 mountd
100005 3 tcp 626 mountd
#


запрет входящих NFS-запросов
Как было сказано ранее в разделе «Запрет доступа к системе других серверов и сетей», оптимальная стратегия обеспечения безопасности – это блокировка по умолчанию всех входящих запросов с выдачей разрешения на соединение только конкретным хостам или сетям. В данном случае мы также будем придерживаться данного принципа.
Программа portmap и ряд других NFS-программ располагают встроенными TCP-wrapper'ами. Убедиться в этом можно так:
# strings /sbin/portmap | egrep "hosts.deny|hosts.allow|libwrap"
hosts_allow_table
hosts_deny_table
/etc/hosts.allow
/etc/hosts.deny
# strings /usr/sbin/rpc.rquotad | egrep "hosts.deny|hosts.allow|libwrap"
libwrap.so.0
# ldd /usr/sbin/rpc.rquotad | grep libwrap
libwrap.so.0 =>/usr/lib/libwrap.so.0 (0x00874000)
#

Если вы увидите в ответе hosts.deny, hosts.allow или же libwrap, это значит, что в программе есть встроенный TCP-упаковщик. Если ни одна из этих строк не была показана, добавление имени такой программы в /etc/hosts.deny и /etc/hosts.allow не даст никакого эффекта.
Для блокировки всех входящих запросов, если вы еще этого не сделали, добавьте в /etc/hosts.deny строку
ALL: ALL

С помощью удаленной машины убедитесь, что у вас отсутствуют какие-либо зарегистрированные RPC-программы:
# rpcinfo -p
No remote programs registered.
#

Для того чтобы разрешить работу с NFS только для тех серверов и сетей, которым вы доверяете, вам потребуется выставить соответствующие настройки для portmap и различных программ, работающих с NFS в /etc/hosts.allow. Посмотреть, какие NFS-программы активизируются при старте NFS-сервера можно в скрипте /etc/init.d/nfs. Затем выполните команду "strings| egrep "hosts.deny|hosts.allow|libwrap"", которая была рассмотрена выше.
В Red Hat Advanced Server 3 программа /usr/sbin/rpc.rquotad содержит встроенный TCP-упаковщик. В Red Hat Fedora Core 3 программа
/usr/sbin/rpc.mountd пока таковым не располагает.
Для того чтобы разрешить NFS-запросы от, допустим, серверов rac1pub, rac2pub, rac3pub и сети .subnet.example.com файл /etc/hosts.allow должен выглядеть примерно так:
portmap: rac1pub rac2pub rac3pub .subnet.example.com
rpc.mountd: rac1pub rac2pub rac3pub .subnet.example.com
rpc.rquotad: rac1pub rac2pub rac3pub .subnet.example.com

При использовании TCP-wrapper'a самым внимательным образом тестируйте доступ к NFS.
Вернемся к зеркалированию портов. Теперь вы можете проверить возможность доступа от серверов и сетей, которым вы доверяете, для чего используется команда rpcinfo.
# rpcinfo -p
program vers proto port
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100011 1 udp 607 rquotad
100011 2 udp 607 rquotad
100011 1 tcp 610 rquotad
100011 2 tcp 610 rquotad
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100005 1 udp 623 mountd
100005 1 tcp 626 mountd
100005 2 udp 623 mountd
100005 2 tcp 626 mountd
100005 3 udp 623 mountd
100005 3 tcp 626 mountd
#

Если вы попытаетесь выполнить эту команду от имени "подозрительного" сервера или сети, то вы должны получить следующий ответ:
# rpcinfo -p
No remote programs registered.
#


экспорт файловой системы NFS
Когда вы разрешаете доступ к файловой системе или каталогу, вызывается файл /etc/exports, который содержит список контроля доступа. Чтобы предоставить сети "subnet.example.com" доступ к /pub, с правами read only, в /etc/exports следует включить строку
/pub *.subnet.example.com(ro,sync)

Очень важно НЕ предоставлять NFS-клиентам права на запись, если только это не является абсолютно необходимым шагом. Данные в /etc/exports по умолчанию экспортируются с опцией «read-only» ("ro").
Строки, разрешающие серверам rac1pub, rac2pub и rac3pub доступ с правами «чтение-запись» к каталогу /data/OracleArch добавляются в /etc/exports и выглядят так:
/data/OracleArch rac1pub.example.com(rw,sync) rac2pub.example.com(rw,sync) rac3pub.example.com(rw,sync)

Обратите внимание, что эти опции НЕ ДОЛЖНЫ отделяться пробелами от имен хостов или сетей, и еще раз отмечу, что для предотвращения спуфинга следует применять полные доменные имена.

Все записи в /etc/exports по умолчанию экспортируются с опцией root_squash (root squashing). Это значит, прошу прощения за тавтологию, что рут на клиентской машине не получит рутовых привилегий (доступа с правами рута) к принадлежащим руту файлам в экспортированных с помощью NFS файловых системах и каталогах. Отключать этот механизм опцией no_root_squash категорически не рекомендуется!
После внесения правок в in /etc/exports, вы можете экспортировать все файловые системы и каталоги командой
# exportfs -a

Обратная операция выполняется командой
# exportfs -ua

Увидеть перечень всех открытых ресурсов можно с помощью команды
# showmount -e localhost
Export list for localhost:
/pub *.subnet.example.com
/data/OracleArch rac3pub.example.com,rac2pub.example.com,rac1pub.example.com


использование NFS поверх TCP
Если вы приняли решение использовать NFS, рекомендуется применять именно NFS поверх TCP, поскольку работа с NFS поверх UDP весьма небезопасна. Все ядра веток 2.4 и 2.6 поддерживают NFS поверх TCP на стороне клиента. Серверная поддержка NFS поверх TCP появилась в последних версиях ядер семейства 2.4 и во всех ядрах ветки 2.6.
Проверить наличие поддержки NFS поверх TCP на вашем сервере поможет команда wire-test (/usr/sbin/wire-test является частью пакета am-utils). Если NFS поверх TCP поддерживается, то вы получите следующий ответ:
# wire-test localhost
Network 1: wire="172.16.1.0" (netnumber=172.16.1).
Network 2: wire="172.16.1.1" (netnumber=172.16.1).
My IP address is 0xac100101.
NFS Version and protocol tests to host "localhost"...
testing vers=2, proto="udp" ->found version 2.
testing vers=3, proto="udp" ->found version 3.
testing vers=2, proto="tcp" ->found version 2.
testing vers=3, proto="tcp" ->found version 3.
#

Если ваш сервер не поддерживает работу в таком режиме, то результат будет следующим:
# wire-test localhost
Network 1: wire="172.16.1.0" (netnumber=172.16.1).
Network 2: wire="172.16.1.1" (netnumber=172.16.1).
My IP address is 0xac100101.
NFS Version and protocol tests to host "localhost"...
testing vers=2, proto="udp" ->found version 2.
testing vers=3, proto="udp" ->found version 3.
testing vers=2, proto="tcp" ->failed!
testing vers=3, proto="tcp" ->failed!
#

При использовании NFS поверх TCP общий каталог монтируется с помощью опции "proto=tcp":
# mount -o proto=tcp:/pub /usr/local/pub

Удостоверьтесь, что у клиента существует каталог назначения (в данном примере - /usr/local/pub).
Проверить работу NFS поверх TCP можно командой mount:
# mount
...
nfsserver:/pub on /usr/local/pub type nfs (rw,proto=tcp,addr=172.16.10.8)
...

Для автоматического монтирования общего каталога при старте системы клиента используется файл /etc/fstab. Для приведенного выше примера этот файл должен выглядеть так:
nfsserver:/pub /usr/local/pub nfs rsize=8192,wsize=8192,timeo=14,intr,tcp 0 0


защита SSH

Данные, передаваемые с помощью многих сетевых сервисов, подобных telnet, rlogin и rsh уязвимы, поскольку могут быть перехвачены злоумышленником. Это одна из причин, побуждающих использовать вместо них SSH. Исходная конфигурация SSH в Red Hat в большинстве случаев соответствует требованиям к безопасности. В любом случае, я бы порекомендовал изменить один из параметров в файле /etc/ssh/sshd_config:

PermitRootLogin no

В разделе «Запрет доступа посредством su к системе и общим аккаунтам» я показал способ отключения прямых соединений ко всем системным и общим аккаунтам, в том числе аккаунту root. Весьма благоразумно будет распространить эту практику и на уровень SSH.

защита Sendmail

Настоящее руководство посвящено в первую очередь тем вопросам безопасности, которые актуальны для всех Linux-систем. Таким образом, подробное рассмотрение защиты почтового или relay-сервера выходит за рамки тематики данного материала, поскольку далеко не все Linux-системы выполняют эти роли. В то же время, в новых Linux-системах Sendmail сконфигурирован для постоянной работы в фоновом режиме. Если ваша система не работает в качестве почтового или relay-сервера, важно убедиться, что она не принимает входящих сетевых соединений от любых хостов за исключением локального сервера.
В Red Hat настроенный по умолчанию файл sendmail.cf запрещает Sendmail принимать входящие внешние соединения. Приведем пример файла /etc/mail/sendmail.cf, который должен дать Sendmail такую команду.
O DaemonPortOptions=Port=smtp,Addr=127.0.0.1, Name=MTA

Этот параметр устанавливается с помощью DAEMON_OPTIONS в файле /etc/mail/sendmail.mc. Раскомментируйте в /etc/mail/sendmail.строку
DAEMON_OPTIONS mc:

DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl

Затем выполните:
# mv /etc/mail/sendmail.cf /etc/mail/sendmail.cf.old
# m4 /etc/mail/sendmail.mc >/etc/mail/sendmail.cf
# /etc/init.d/sendmail restart

Чтобы проверить, продолжает ли Sendmail слушать входящие сетевые запросы, вы можете выполнить одну из следующих команд:
# nmap -sT -p 25
# telnet25

Не запускайте данные команды с локального хоста, поскольку предполагается, что Sendmail принимает соединения с локального узла.

копирование файлов с использованием ssh без ввода логина

Здесь будут рассмотрены некоторые приемы, которые в определенных случаях могут пригодиться. Мы будем копировать файлы по сети с использованием ssh, минуя предложение ввести пароль.
При использовании опции “command” вы сможете отключить scp и тем самым игнорировать все проходящие ssh-команды.
На сервере, с которого вы желаете получить файл, потребуется добавить в файле ~/.ssh/authorized_keys2 в качестве ключа SSH строку
command="/bin/cat ~/" ssh-dss AAABB33Nza...OpenSSH key

Теперь для копирования файла с удаленного сервера запустите команду
ssh@>

Поскольку /bin/cat выполняется на стороне сервера, результат работы должен быть перенаправлен в локальный файл.
Другой способ – это замена /bin/cat собственным скриптом, который, читая переменную окружения $SSH_ORIGINAL_COMMAND, должен будет проверять проходящие команды SSH. Например:
#!/bin/ksh
if [[ $SSH_ORIGINAL_COMMAND = "File1" ||
$SSH_ORIGINAL_COMMAND = "File2" ]]
then
/bin/cat $SSH_ORIGINAL_COMMAND
else
echo "Invalid file name!"
exit 1
fi

Затем в ~/.ssh/authorized_keys2 замените /bin/cat именем скрипта и выполняйте копирование “File1” командой
ssh@File1 >

Копируем “File2”:
ssh@File2 >

Все остальные параметры выдадут ошибку.

настраиваемые параметры ядра

Здесь будет приведен перечень некоторых настраиваемых параметров ядра, которые вы можете задействовать для повышения уровня безопасности вашего Linux-сервера. Для каждого параметра будет приведены примеры тех записей, которые вам потребуется добавить в конфигурационный файл
/etc/sysctl.conf, дабы произведенные изменения сохранились после перезагрузки. Для немедленной активации измененных параметров ядра используйте
# sysctl –p


активация TCP SYN Cookie Protection

”SYN Attack" – это атака типа «отказ в обслуживании», которая направлена на захват всех ресурсов сервера. Потенциальной жертвой может стать любой подключенный к сети сервер. Для включения TCP SYN Cookie Protection отредактируйте файл /etc/sysctl.conf, куда надо будет добавить строку
net.ipv4.tcp_syncookies = 1

отключение IP Source Routing


Маршрутизация сообщений используется для определения сетевого пути от исходной точки к месту назначения. Она применяется для диагностики некоторых сетевых проблем. В то же время, атакующий может попытаться отправить в сеть такой пакт, а затем перехватить ответы, при этом ваш сервер даже не заметит, что работает совсем не с той машиной, которой следует доверять. Поэтому следует включить проверку исходного маршрута. Для этого добавьте в файл /etc/sysctl.conf строку

net.ipv4.conf.all.accept_source_route = 0

отключение ICMP Redirect

Перенаправление ICMP используется роутерами для передачи серверу информации о том, что существует путь, лучше избранного сервером. Атакующий может использовать перенаправление ICMP-пакетов для подмены таблицы маршрутизации, тем самым направляя трафик по совершенно не предусмотренному вами пути. Отключается ICMP Redirect редактированием все того же файла /etc/sysctl.conf, куда добавляется строка

net.ipv4.conf.all.accept_redirects = 0

активация IP Spoofing Protection

IP-спуфинг – это атака, при которой злоумышленник, манипулируя исходящими адресами, посылает пакеты от имени другого хоста. IP-спуфинг часто используется для проведения DoS-атак. Более подробные сведения о технике IP-спуфинга содержатся в статье «IP Spoofing: Understanding the basics» (http://www.linuxexposed.com/internal.php?op=modload&name=News&file=article&sid=550).
Защититься от IP-спуфинга можно с помощью механизма Source Address Verification. Для этого в файл /etc/sysctl.conf добавляется строка
net.ipv4.conf.all.rp_filter = 1


игнорирование ICMP-запросов

Если вы хотите, чтобы ОС Linux игнорировала пинги, внесите в файл /etc/sysctl.conf строку
net.ipv4.icmp_echo_ignore_all = 1 = 1

Это можно сделать далеко не в каждой среде.

игнорирование Broadcast Request

Заставить Linux игнорировать широковещательные запросы можно добавив в /etc/sysctl.conf строку
net.ipv4.icmp_echo_ignore_broadcasts = 1


сообщения о Bad Error Message

У вас есть возможность получать предупреждения о появлении в вашей сети таких сообщений. Для этого добавьте в файл /etc/sysctl.conf строку
net.ipv4.icmp_ignore_bogus_error_responses = 1

регистрация перехваченных и перенаправленных пакетов

Включается данная опция добавлением в файл /etc/sysctl.conf строки
net.ipv4.conf.all.log_martians = 1

дополнительные источники:

Network Security with /proc/sys/net/ipv4 -http://www.linuxsecurity.com/content/view/111337/65/

IP Spoofing: Understanding the basics -http://www.linuxexposed.com/internal.php?op=modload&name=News&file=article&sid=550


показ баннеров при логине

Кроме всех прочих действий, неплохо будет показать пользователю при регистрации в системе сообщение, предупреждающее об ответственности за противоправные действия. Обсудите с юристами соответствующий текст.
Мы будем показывать баннер после того, как пользователь залогинится в системе с использованием ssh, локальной консоли или каким-нибудь другим путем. Для этих целей можно использовать файл /etc/motd. Если он не существует, то потребуется его создать. Затем внесите в него свой предупреждающий текст.
# cat /etc/motd
Система защищена...
Продолжение работы в данной системе означает согласие на отслеживаниие ваших действий.

#

Для работы с SSH вам потребуется отредактировать в файле /etc/ssh/sshd_config параметр Banner. В результате баннер будет показываться перед предложением ввести логин.
Для показа баннера в локальной консоли отредактируйте /etc/issue. Баннер будет показан перед приглашением залогиниться.
В случае GDM вы можете потребовать от пользователя подтвердить принятие ваших условий выбором из опций “Yes” и “No”. Для этого добавьте в начало скрипта /etc/X11/gdm/PreSession/Default строки
if ! gdialog --yesno '\nThis system is classified...\n' 10 10; then
sleep 10
exit 1;
fi

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

разное

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

полезные команды

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

who - gоказывает список пользователей, работающих в системе данный момент;
w - показывает пользователей, работающих в системе и информацию о том, чем они там занимаются;
last - последние пользователи, начавшие работу в системе и дополнительная информация о подключениях: время входа в систему и выхода из нее.
lastb - то же, что и last. Отличается тем, что по умолчанию выводит лог файла /var/log/btmp, который содержит записи о всех неудачных попытках входа в систему.
lastlog - эта команда выдает данные, хранящиеся в /var/log/lastlog, то есть сведения времени последнего входа пользователя в систему.
ac - выдает время соединения в часах по каждому пользователю или другим признакам. Эта команда читает /var/log/wtmp.
dump-utmp - конвертирует данные, взятые из /var/run/utmp или /var/log/wtmp в ASCII-формат.

Кроме этого, периодически проверяйте файл /var/log/messages.

другое

Эти позиции не относятся напрямую к обеспечению безопасности системы, однако на проходящих аудит системах они должны быть надлежащим образом настроены. Речь идет о Resolver (/etc/hosts, /etc/resolv.conf, /etc/nsswitch.conf) и NTP (/etc/ntp.conf)



Werner Puschitz, перевод Алексея Кутовенко



Сетевые решения. Статья была опубликована в номере 03 за 2005 год в рубрике save ass…

©1999-2024 Сетевые решения