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

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


Автор опубликовал на сайте Hackernoon отрывок из 9-й главы, который мы и предлагаем вам оценить.

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

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

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


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

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

Разработчики, входящие в состав группы Developers, могут получить доступ к конкретному каталогу, а для пользователей, не относящихся к данной группе, каталог будет закрыт
Попробуйте сами: создайте в текстовом редакторе новый файл. Запишите в него простой текст, например, «Hello World», чтобы сразу было видно, когда к файлу удалось успешно обратиться. Затем отредактируйте права доступа при помощи 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

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

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

# 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, а в третьем – медиа-файлы, которые могут встраиваться в ваши веб-страницы. Микросервисная архитектура позволяет не только значительно повысить производительность и эффективность, но и значительно снижают риск взлома каждого отдельного компонента.

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

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


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

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

$ 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”) {print}’ /etc/passwd
root:x:0:0:root:/root:/bin/bash

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


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

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

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

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


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

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

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

# 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.

Комментарии (34)


  1. degs
    07.10.2018 02:42
    +6

    Приветствую инициативу — переводить отрывки из только что вышедших или еще не вышедших книг, молодцы.
    В данном отрывке сразу например упал глаз на:
    $ chmod 770 datafile.txt
    и дальнейший текст в общем соответствует. Может это отрывок из первой, вводной главы для самых маленьких? Тогда автор (книги) выбрал странный способ рекламы.
    В общем переводчики молодцы, а насчет книги у меня сомнения.


    1. odiemius
      07.10.2018 10:10

      Желательно еще чтобы автор статьи проверял сам, что он публикует, вне зависимости от того, проверяли ли оригинальне авторы. Например

      # systemctl list-unit-files — type=service — state=enabled
      копируйте в консоль и выполните — получится «0 unit files listed.» на работающей системе.
      Вместо такого надо исполнять
      systemctl list-unit-files --type=service --state=enabled
      Ну я-то, с опытом, догадался, что надо делать, а начинающие врядли догадаются до замены стоящего в странице html-ного "— " на два минуса подряд.


  1. chupasaurus
    07.10.2018 05:47

    netstat вместе со всем бандлом net-tools уже лет 6 как deprecated. В Debian Buster из широко используемого софта от него зависят только установщик Openstack, Bind и Cloud-init.


    1. Fedcomp
      07.10.2018 19:22

      очень классно говорить deprecated и не говорить в пользу чего )


      1. YourChief
        08.10.2018 03:40

        В пользу ss. Однако я, например, терпеть его не могу.


        1. spellman003
          08.10.2018 09:35

          А почему? В гугле не нашёл.


          1. YourChief
            08.10.2018 11:39

            Он просто неудобный и часто не применяет те фильтры, которые указаны в командной строке по каким-то свои синтаксическим соображениям. В результате получается проще вывести всё, а потом отгрепать.


  1. bugdesigner
    07.10.2018 09:13
    +1

    Все эти советы ну совсем для чайников. Был случай ещё в начале 2000-х, вломили нам сервер, пролезли через дыру в ssh, как потом выяснилось. Сервак был тестовым и за него как-то забыли, но суть не в этом. Обнаружился взлом случайно, тк через него повалил подозрительный трафик. Когда зашли на него, ничего подозрительного не обнаружили, netstat, lsof, ps ничего не показали. Однако nmap c другой малины роказал несколько "левых" открытых портов. Короче, на машину установили руткит, который прятал всю активность. Заменили libps и ещё кучу утилит — сейчас уже подробностей не помню. К чему я это всё рассказываю? Если сервер взломан, и сделал это опытный хакер, то на самой машине вы так просто ничего не обнаружите.


    1. powerman
      07.10.2018 12:51

      Чтобы что-то обнаружить есть http://rkhunter.sf.net/ и http://www.chkrootkit.org/.


  1. really4g
    07.10.2018 09:22
    +1

    Как-то больше ожидалось увидеть информацию не по съему информации об открытых портах, правах на каталоги и список установленных пакетов. Это скорее общерекомендательные для серверов на базе linux. Название статьи не соответствует содержимому, т.к. все то что описали прекрасно подойдёт и для samba, ftp, ssh, etc.


  1. iig
    07.10.2018 12:46

    Было бы поучительно рассмотреть защищённость от атак определенного вида свежеустановленной системы с типичными настройками. И действия в процессе эксплуатации, которые эту защищённость уменьшают. Или наоборот.
    А то защита сферического веб-сервера с помощью chmod это как-то не очень.


  1. unabl4
    07.10.2018 13:32

    Странно, что в статье нет ничего ни про ufw, ни про iptables (т.е сеть)
    Из собственных (ну и нетолько) практик: 0) вход по SSH только по ключу, никаких паролей, 1) перенос порта ssh на какой-нибудь малоизвестный, чтоб не обстукивали так рьяно. 2) fail2ban.
    Если посмотреть, что делает DigitalOcean на своих готовых дроплетах (например, wordpress) — они по умолчанию гасят все порты, кроме 80-ого, 443-ого и ssh.

    Сам бы хотел бы узнать, как правильно организовывать учётные записи на общем линукс сервере (например, какой-то production сервер). Сколько учётных записей должно быть? Один на каждого разработчика? Или общий на всех? root / не root? Стоит ли заморачиваться с запиливанием ACL? Как организовывать группы?


    1. SirEdvin
      07.10.2018 15:43

      А есть какие-то альтернативы по одному на разработчика? Или после каждого ухода будете менять пароль от пользователя?


      1. scruff
        07.10.2018 18:41

        … пароль, как минимум, а если ходят беспарольно, т.е. по ssh-ключам, то еще и новые ключи всем раздавать — то еще гемор.


      1. unabl4
        07.10.2018 19:28

        У нас был один общий юзер. К нему (в authorized_keys) просто дописывали (или удаляли) ssh ключи с машин разработчиков.


    1. scruff
      07.10.2018 18:35

      Думаю по учетке на каждого дев-а наилучшая практика. Если кто-то начнет беспределить в проде — будет легче вычислить и предпринять меры. Вообще если под одной учеткой работают более одного человека — уже нехорошо. Проще будет с раздачей root/не-root. ACL? Вы про setfacl? Штука в принципе годная, если с самого начала сделать всё по уму (где-то читал, что максимально надо выжать всё из chmod/chown/сhgrp, а если не получается — идти уже в ACL) — т.е. в setfacl «вешать» только группы, а не учетки отдельных пользователей. Кстати на всех виндовых файловых серваках делаю именно так, никаких отдельных пользователей в «security» на директории — проще изменять/отслеживать.


      1. unabl4
        07.10.2018 19:41

        Да, наверно про setfacl. Я на самом деле с этой штукой не игрался — она по дефолту в убунте не доступна, да и нужды в такой гранулярности вроде не было.


    1. roller
      08.10.2018 00:31

      Достаточно всего лишь погуглить blog.appliedinformaticsinc.com/how-to-manage-ssh-keys-using-ansible


    1. iig
      08.10.2018 08:31

      Все зависит от решаемых задач, количества учётных записей, количества серверов, числа администраторов… Все способы правильные, но некоторые более удобные.


    1. gre
      08.10.2018 11:12

      Вот объяснит кто-то зачем переносить ssh на другой порт?
      Чтобы обстукивали меньше? Уменьшить энтропию вселенной или что?
      Или это такая защита от zero-day багов, которых за кучу лет проекта уже просто нет?


      1. roller
        08.10.2018 17:01
        +1

        Защита от замусоривания auth.log


    1. o-pod
      08.10.2018 11:47

      unabl4, как сисадмин могу сказать, что идеально, когда НА ПРОДЕ количество учётных записей разработчиков равно НУЛЮ.
      Каждый должен заниматься своим делом: разработчики — разрабатывать, админы — админить.


  1. scruff
    07.10.2018 18:25

    Статью однозначно в закладки. Присоединюсь к предыдущим коментаторам — сделайте аналогичную «выжимку-памятку» по iptables.


  1. unwrecker
    07.10.2018 18:37

    LAMP? а не слишком ли устарела данная книга?


    1. iig
      07.10.2018 19:14

      А что, разве php уже похоронили? ;)


      1. iproger
        07.10.2018 20:16
        +1

        Зная разницу в скорости между apache и nginx сложно уже пользоваться первым.


        1. iig
          07.10.2018 20:56

          В контексте защиты сервера есть принципиальная разница, apache внутре или nginx?


          1. YourChief
            08.10.2018 03:42

            Да, они по-разному работают и по-разному оказывается запущен PHP. В статье советы как будто щас 90ые, только джэйлы заменили контейнерами.


            1. iig
              08.10.2018 08:24

              Так безопасность на 99.9% это администрирование. В этом отношении за 20 лет что-то поменялось, но статья не об этом.


              1. YourChief
                08.10.2018 11:14

                Нет, это не так. Самые дичайшие дыры до которых легче всего добраться — чаще всего в самом вебприложении.


  1. o-pod
    07.10.2018 21:05
    +1

    А по мне так статья не особо полезная. Автор не концентрирует внимание на каком-то одном аспекте безопасности, а прыгает с темы на тему, толком не раскрыв ни одну из них.

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

    В разделе «Сканирование портов» рассказывается только о сканировании изнутри, и ни слова нет про сканирование снаружи.

    В разделе «Проверяем наличие опасных значений пользовательского ID» очень скудно описывается команда sudo. Все обозначенные автором проверки сводятся к нулю, если предварительно не проверить конфиг самого sudo.


  1. JohnCoffey
    08.10.2018 02:07

    Piter, обратите внимание на 2 издание книги по внедрению зависимостей в .net!

    Ваше 1 издание уже невозможно купить: самое время начать перевод второго.

    www.manning.com/books/dependency-injection-in-dot-net-second-edition


    1. ph_piter Автор
      09.10.2018 10:02

      Вы совершенно правы, переводить необходимо и переводить будем: контракт уже получен, ждем финальную версию текста


  1. saipr
    08.10.2018 16:37

    О создание защищенных Web-сайтов/порталов на базе Apache и российской криптографии.