Хабрахабр

[Перевод] Защищаем веб-сервер на Linux

Привет, Хабр!

Книга "Linux in Action" Дэвида Клинтона вышла в издательстве Manning и рассказывает не только о внутреннем устройстве Linux, но и о наиболее распространенных проблемах, и о способах их устранения. У нас давно не выходило новых книг по Linux для начинающих — и вот мы беремся за перевод новинки именно такого плана.

Автор опубликовал на сайте Hackernoon отрывок из 9-й главы, который мы и предлагаем вам оценить.
Собрать LAMP-сервер, как следует его сконфигурировать, обеспечить надежную обработку данных, настроить предметную область и озаботиться TLS-сертификатом – лишь половина пути к победе. Также необходимо убедиться, что ваша инфраструктура защищена от многочисленных устрашающих угроз Интернета.

Разумеется, этот рассказ не полный (в книге Linux в действии рассмотрены и другие темы, например, установка TLS-сертификатов и работа с SELinux), но для начала и этого будет вполне достаточно. В этой статье мы исследуем безопасность веб-сайта, научившись правильно работать с системными группами, обеспечивать изоляцию процессов и регулярный аудит системных ресурсов.

Системные группы и принцип минимальных привилегий

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

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

Запишите в него простой текст, например, «Hello World», чтобы сразу было видно, когда к файлу удалось успешно обратиться. Разработчики, входящие в состав группы Developers, могут получить доступ к конкретному каталогу, а для пользователей, не относящихся к данной группе, каталог будет закрыт
Попробуйте сами: создайте в текстовом редакторе новый файл. Затем отредактируйте права доступа при помощи chmod 770, так, чтобы владелец файла и члены группы, к которой он относится, имели полные права на работу с файлом, а другие не могли его читать.

$ nano datafile.txt
$ chmod 770 datafile.txt

Если в вашей системе пока нет других пользовательских аккаунтов кроме вашего собственного – создайте такой аккаунт либо при помощи adduser — так делается в Debian/Ubuntu — либо при помощи useradd, как принято в CentOS. Команда useradd сработает и в Ubuntu.

Команда useradd в отличие от adduser из Debian требует, чтобы пользовательский пароль генерировался отдельно:

# useradd otheruser
# passwd otheruser
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

При помощи команды su переключаемся на нового пользователя. После того, как мы введем его пароль, все следующие команды будут выполняться от имени этого пользователя. Вы будете работать от лица именно этого пользователя; ни больше, ни меньше. Если вы попытаетесь считать файл данных datafile.txt (при помощи cat), то ничего у вас больше не выйдет; как вы помните, права на чтение есть только у членов группы. Когда закончите, введите exit, чтобы выйти из оболочки нового пользователя, и вернитесь в свою исходную оболочку.

$ su otheruser
Password:
$ cat /home/ubuntu/datafile.txt
cat: /home/ubuntu/datafile.txt: Permission denied
$ exit

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

Аргумент ubuntu:app-data-group оставляет права на владение файлом пользователю Ubuntu, но группа его меняется на новую: app-data-group. Создадим новую группу, при помощи которой сможем управлять данными нашего приложения, а затем отредактируем свойства нашего файла с данными при помощи команды chown.

# groupadd app-data-group
# chown ubuntu:app-data-group datafile.txt

Запустите ls, чтобы получить «развернутый» вывод этого файла и просмотреть его новые права доступа и статус. Обратите внимание: как и следовало ожидать, файлом владеет пользователь ubuntu, относящийся к группе app-data-group.

$ ls -l | grep datafile.txt
-rwxrwx — — 1 ubuntu app-data-group 6 Aug 9 22:43 datafile.txt

Можно применить usermod, чтобы добавить вашего пользователя к app-data-group, а затем – команду su, чтобы переключиться на оболочку, в которой развернут аккаунт другого пользователя. Теперь, даже несмотря на то, что права доступа к файлу закрывают его от всех «других» — а вы на данный момент определенно «другой» пользователь — вы должны свободно читать этот файл, поскольку относитесь к нужной группе.

# usermod -aG app-data-group otheruser
$ su otheruser
$ cat datafile.txt
Hello World

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

Можете по диагонали просмотреть файл /etc/group – обратите внимание, как много системных процессов относятся к собственным группам… На самом деле, она применяется не только для предоставления нужных прав доступа отдельным пользователям – многие системные процессы также не могли бы выполнять своих задач, если бы для них не была прописана принадлежность к нужным группам.

Сокращенный листинг содержимого /etc/group file:

$ cat /etc/group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:syslog
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
[…]

Изоляция процессов в контейнерах

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

Однако, благодаря виртуализации становится гораздо проще и дешевле выстроить «ячеистую» архитектуру. Ранее эту проблему было принято решать так: на каждую службу выделяли свою физическую машину. Микросервисная архитектура позволяет не только значительно повысить производительность и эффективность, но и значительно снижают риск взлома каждого отдельного компонента. Сегодня такая архитектура часто именуется микросервисной и позволяет запускать сразу множество контейнеров, в одном из которых может работать, к примеру, база данных, в другом — Apache, а в третьем – медиа-файлы, которые могут встраиваться в ваши веб-страницы.

Сегодня гораздо популярнее становятся и другие контейнерные технологии, например, Docker. «Контейнеры», о которых я говорю, не обязательно должны обладать убедительностью LXC.

Проверяем наличие опасных значений пользовательского ID

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

Взгляните на файл passwd в каталоге /etc/. В данном случае хорошо, что выявить таких самозванцев не составляет труда: их пользовательский и/или групповой ID, как и у админа, будет «0». В первом поле содержится имя аккаунта (в данном случае — root и ubuntu), а во втором вместо пароля может стоять x (если пароль существует – он будет в зашифрованном виде находиться в файле/etc/shadow). В этом файле содержится по записи для каждого обычного и системного пользовательского аккаунта, уже существующего в системе. В случае с ubuntu в данном примере оба ID равны 1000. Но в следующих двух полях содержатся пользовательский и групповой ID. А у администратора, как видите, здесь стоят нули.

$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
[…]
ubuntu:x:1000:1000::/home/ubuntu:/bin/bash

Если когда-нибудь встретите обычного пользователя с пользовательским или групповым ID = 0, то можете не сомневаться, что дело тут нечисто, и ситуацию нужно исправить. Быстрый и легкий способ выявить такую проблему – проверить файл passwd командой awk, которая выведет все строки, в третьем поле которых нет ничего кроме 0. В моем случае (можно выдохнуть) нашлась всего одна такая строка – рут. Можете запустить ее повторно, заменив $4 на $3 – так вы проверите поле группового ID.

$ awk -F: ‘($3 == “0”) ’ /etc/passwd
root:x:0:0:root:/root:/bin/bash

Аудит ресурсов системы

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

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

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

Сканирование портов

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

Но гораздо важнее обращать внимание и на другие, неожиданные результаты. Вы уже знаете, что на обычном веб-сервере, вероятно, должны быть открыты порты HTTP (80) и SSH (22), поэтому они вас не удивят. Команда netstat выводит все открытые порты, а также массу информации о том, как именно они используются.

-l включает лишь слушающие сокеты, а -p добавляет ID процесса слушающей программы. В данном примере мы проверяем совершенно типичный многоцелевой сервер, и команда -n приказывает netstat включить все числовые порты и адреса. Естественно, если что-то видите — действуйте.

# netstat -npl
Active Internet connections (only servers)
Proto Local Address Foreign Address State PID/Program name
tcp 127.0.0.1:3306 0.0.0.0:* LISTEN 403/mysqld
tcp 0.0.0.0:139 0.0.0.0:* LISTEN 270/smbd
tcp 0.0.0.0:22 0.0.0.0:* LISTEN 333/sshd tcp 0.0.0.0:445 0.0.0.0:* LISTEN 270/smbd
tcp6 :::80 :::* LISTEN 417/apache2 […]

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

$ ss -o state established ‘( dport = :ssh or sport = :ssh )’
Netid Recv-Q Send-Q Local Address:Port Peer Address:Port tcp 0 0 10.0.3.1:39874 10.0.3.96:ssh timer:(keepalive,18min,0)

Проверяем активные службы

Если сделать быстрый мгновенный снимок служб, управляемых system и в настоящее время активных на вашем компьютере, то машина поможет выявить любую нежелательную активность. Команда systemctl может вывести список всех существующих служб, а потом их список можно сузить до тех, в описании которых содержится enabled. Так будут возвращены лишь активные службы.

# systemctl list-unit-files — type=service — state=enabled
autovt@.service enabled bind9.service enabled cron.service enabled dbus-org.freedesktop.thermald.service enabled docker.service enabled getty@.service enabled haveged.service enabled mysql.service enabled networking.service enabled resolvconf.service enabled rsyslog.service enabled ssh.service enabled sshd.service enabled
syslog.service enabled systemd-timesyncd.service enabled thermald.service enabled unattended-upgrades.service enabled ureadahead.service enabled

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

# systemctl stop haveged
# systemctl disable haveged

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

Ну, чтобы узнать – нужно посмотреть. Мог ли кто-то установить в системе программы без вашего ведома? Команда yum list installed или, в случае Debian/Ubuntu, dpkg — list выдаст вам подробную сводку, а команда remove должна удалить все пакеты, которые нам не нужны.

# yum list installed
# yum remove packageName

Вот как то же самое делается в Ubuntu:

# dpkg --list
# apt-get remove packageName

Также полезно следить за изменениями, которые вносятся в ваши системные конфигурационные файлы – об этом мы поговорим в главе 11.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть