Системы принудительного контроля доступа и сетевой защиты
Злоумышленник нашел уязвимость в веб-приложении и смог выполнить произвольный код от имени пользователя www-data. Стандартная модель прав доступа в Linux говорит: процесс www-data имеет право читать, писать и исполнять любые файлы, владельцем которых является www-data, а также читать файлы с правами o+r. Это означает, что взломанный веб-сервер может запустить компилятор в /tmp, скачать скрипт для майнинга, прочитать конфигурационные файлы других сайтов в /var/www, если они не изолированы строго, и даже попытаться открыть локальное сетевое соединение к базе данных. Классические права доступа (DAC) бессильны, потому что процесс действует в рамках легитимных полномочий своего пользователя. Чтобы остановить атаку на этом этапе, система должна контролировать не только права пользователя, но и конкретные действия процесса, а также жестко фильтровать сетевой трафик.
За пределами DAC: архитектура LSM
Классическая модель прав доступа (rwx, ACL, SUID) относится к категории Discretionary Access Control (DAC), или дискреционного контроля доступа. Фундаментальный принцип DAC: владелец объекта сам определяет права доступа к нему. Если пользователь alice создала файл, она может разрешить кому угодно его читать. Если процесс запущен от имени root, он игнорирует большинство проверок DAC.
Mandatory Access Control (MAC), или принудительный контроль доступа, работает иначе. В MAC политики безопасности определяются централизованно системным администратором и жестко контролируются ядром. Ни один пользователь, даже владелец файла, не может изменить политику MAC для своего объекта. В правильно настроенной MAC-системе даже процесс с эффективным UID 0 (root) будет заблокирован, если его действие не разрешено явным образом в политике.
В Linux реализация MAC опирается на фреймворк Linux Security Modules (LSM). Он предоставляет набор перехватчиков (хуков) внутри ядра. Каждый раз, когда процесс запрашивает доступ к системному ресурсу (открытие файла, создание сокета, отправка сигнала), ядро сначала проверяет стандартные права DAC. Если DAC запрещает доступ, возвращается ошибка Permission denied. Если DAC разрешает доступ, запрос передается в модуль LSM. И только если LSM дает добро, действие выполняется.
!Процесс проходит последовательную проверку доступа через DAC, а затем через MAC.
В экосистеме Linux исторически закрепились две основные реализации LSM: AppArmor и SELinux. В дистрибутивах семейства Debian стандартом является AppArmor.
AppArmor: Путевой контроль доступа
AppArmor (Application Armor) использует концепцию путевого контроля (path-based MAC). Политики безопасности привязываются не к пользователям, а к абсолютным путям исполняемых файлов. Мы ограничиваем не абстрактного пользователя www-data, а конкретный бинарный файл /usr/sbin/nginx.
Режимы работы профилей
Каждая программа, защищаемая AppArmor, имеет свой профиль (файлы конфигурации хранятся в /etc/apparmor.d/). Профиль может находиться в одном из трех состояний:
| Режим | Поведение системы | Применение |
| :--- | :--- | :--- |
| Enforce (Принуждение) | Блокирует любое действие, не разрешенное явно. Записывает попытку нарушения в лог. | Боевая эксплуатация защищенного сервиса. |
| Complain (Жалоба) | Разрешает действие, но записывает предупреждение в аудит-лог. | Отладка и создание новых профилей без остановки сервиса. |
| Unconfined (Неограниченный) | Процесс игнорирует AppArmor, опираясь только на DAC. | Поведение по умолчанию для программ без профиля. |
Синтаксис и анатомия профиля
Рассмотрим фрагмент профиля AppArmor для вымышленного демона резервного копирования /usr/local/bin/backup-daemon:
Права на файлы обозначаются буквами:
r (read) и w (write) — чтение и запись.
k (lock) — право накладывать блокировку на файл.
* — рекурсивное совпадение (все файлы и поддиректории), в отличие от , которое совпадает только с файлами строго в текущей директории.Особого внимания заслуживают права на исполнение дочерних программ. Если наш демон вызывает /usr/bin/tar, AppArmor должен знать, как контролировать новый процесс:
ix (inherit execute): дочерний процесс унаследует текущий профиль. /usr/bin/tar будет жестко ограничен теми же правилами, что и backup-daemon.
px (profile execute): при запуске /usr/bin/gzip AppArmor потребует переключения на отдельный профиль, написанный специально для gzip. Если профиля нет, запуск блокируется.
ux (unconfined execute): запуск без ограничений (крайне небезопасно, нарушает изоляцию).Правило deny обладает абсолютным приоритетом. Даже если подключенная абстракция #include <abstractions/base> разрешает чтение содержимого /etc/, строка deny /etc/shadow r гарантированно заблокирует доступ к файлу паролей.
Интерактивное создание профиля
Написание профиля с нуля вручную — сложная задача, так как современные программы неявно открывают сотни файлов (динамические библиотеки, локали, сокеты). В Debian для автоматизации этого процесса используется пакет apparmor-utils.
!Пошаговая интерактивная анимация создания профиля AppArmor: от запуска aa-genprof до финального профиля в режиме Enforce с подсветкой активных элементов на каждом шаге.
Процесс создания итеративен:
Выполняется команда aa-genprof /usr/local/bin/backup-daemon. Утилита создает пустой профиль-скелет, переводит его в режим Complain и ожидает действий.
Администратор в другом терминале запускает программу и выполняет все типичные сценарии ее работы. Ядро фиксирует доступы в системный лог.
Возврат в утилиту aa-genprof и запуск сканирования ("Scan"). Утилита читает логи и по каждому зафиксированному системному вызову задает вопрос: разрешить чтение этого файла? разрешить этот сетевой вызов?
После ответов профиль сохраняется и переводится в режим Enforce.Если в процессе эксплуатации программа обновляется и начинает требовать новые доступы, используется команда aa-logprof. Она анализирует свежие отказы (сообщения DENIED в /var/log/syslog) и предлагает добавить разрешающие правила в существующий профиль.
> Уязвимость путевого подхода (AppArmor) заключается в жестких ссылках (hardlinks). Если профиль ограничивает /usr/bin/secret-app, а злоумышленник создаст жесткую ссылку /tmp/my-app на тот же индексный дескриптор (inode), контроль может быть нарушен из-за изменения пути вызова.
Альтернативный подход: Inode-based MAC
Для полноты картины системному администратору необходимо понимать и альтернативный подход, применяемый в корпоративных системах на базе Red Hat (где стандартом является SELinux). Вместо путей там используется Inode-based MAC.
Каждому объекту в системе (файлу, процессу, порту) присваивается криптографическая метка — контекст безопасности, который хранится в расширенных атрибутах файловой системы (xattr).
!Структура контекста безопасности SELinux, состоящая из пользователя, роли, типа и уровня доступа.
Контекст состоит из четырех полей: user:role:type:level. Главным элементом является тип (Type Enforcement). Процесс с определенным типом может взаимодействовать только с файлами разрешенных типов, независимо от того, где эти файлы находятся в файловой системе. Это исключает атаки через жесткие ссылки, но требует от администратора постоянного контроля за правильной маркировкой файлов при их перемещении.
Сетевая изоляция: управление брандмауэром через ufw
AppArmor защищает систему изнутри, ограничивая скомпрометированные процессы. Однако первый рубеж обороны — это сеть. Сервер не должен принимать соединения на порты, которые не предназначены для публичного доступа.
В ядре Linux за фильтрацию сетевых пакетов отвечает подсистема Netfilter, управление которой традиционно осуществляется утилитами iptables или nftables. Их синтаксис сложен, избыточен и требует глубокого понимания цепочек маршрутизации пакетов (PREROUTING, INPUT, FORWARD, OUTPUT).
Для упрощения администрирования в Debian и Ubuntu применяется ufw (Uncomplicated Firewall) — фронтенд, который транслирует простые человекочитаемые команды в сложные правила iptables/nftables.
Базовая настройка и логика по умолчанию
Золотое правило сетевой безопасности: запрещено всё, что не разрешено явно.
Свежеустановленный ufw отключен. Перед его активацией необходимо задать базовые политики и обязательно разрешить SSH-подключения, иначе при включении брандмауэра администратор потеряет доступ к удаленному серверу.
Политика deny incoming означает, что любой входящий пакет, не соответствующий явно заданным разрешающим правилам, будет отброшен (drop) без отправки ответа отправителю. Это делает закрытые порты невидимыми для сканеров сети. Политика allow outgoing разрешает серверу беспрепятственно скачивать обновления и обращаться к внешним API.
Синтаксис правил: от простого к сложному
ufw поддерживает несколько уровней детализации при написании правил.
1. Простые правила (по порту или имени сервиса)
Разрешить HTTP-трафик можно указав номер порта или имя сервиса (имена берутся из файла /etc/services):
ufw allow 80
ufw allow http
Если сервис использует протокол UDP (например, DNS-сервер), протокол указывается явно:
ufw allow 53/udp
2. Расширенные правила (IP-адреса и подсети)
Часто требуется ограничить доступ к сервису, разрешив его только для определенного IP-адреса или корпоративной подсети. Например, доступ к базе данных MySQL (порт 3306) должен быть открыт только для серверов из внутренней подсети 10.0.0.0/24.
Синтаксис расширенного правила строится по схеме: ufw [allow/deny] from <источник> to <назначение> port <порт> proto <протокол>.
> Важно: ufw читает правила сверху вниз. Как только пакет совпадает с правилом, поиск прекращается. Если вы сначала добавите правило allow from any to any port 80, а затем deny from 192.168.1.100 to any port 80, злоумышленник всё равно получит доступ, так как сработает первое разрешающее правило.
Для управления порядком используется нумерованный вывод:
ufw status numbered
Чтобы вставить запрещающее правило на первую позицию:
ufw insert 1 deny from 192.168.1.100
Удаление правила происходит по его номеру:
ufw delete 1
Ограничение частоты подключений (Rate Limiting)
Открытие порта SSH (ufw allow ssh) делает сервер уязвимым для атак полного перебора паролей (brute-force). ufw имеет встроенный механизм ограничения частоты подключений — limit.
Под капотом эта команда использует модуль recent из iptables. Логика работы следующая: если с одного IP-адреса поступает более 6 попыток инициации нового соединения в течение 30 секунд, все последующие пакеты с этого адреса будут отбрасываться. Это кардинально замедляет brute-force атаки, не мешая легитимным пользователям, которые редко подключаются чаще одного раза в несколько минут.
Интеграция с приложениями (App Profiles)
Многие пакеты при установке в Debian (например, Nginx, Apache, OpenSSH) автоматически создают профили для ufw. Эти профили хранятся в директории /etc/ufw/applications.d/ и содержат информацию о портах, которые использует приложение.
Просмотреть список доступных профилей:
ufw app list
Вывод может выглядеть так:
Вместо того чтобы вручную открывать порты 80 и 443, администратор может применить профиль:
ufw allow 'Nginx Full'
ufw app info 'Nginx Full' (покажет, какие именно порты открывает этот профиль).
Логирование и диагностика
Когда легитимный трафик блокируется, необходимо проанализировать логи брандмауэра. По умолчанию логирование в ufw отключено или работает на минимальном уровне.
Включение логирования:
ufw logging on (или ufw logging low)
Записи о заблокированных пакетах будут отправляться в системный журнал ядра и сохраняться в /var/log/ufw.log или /var/log/syslog. Строка лога выглядит примерно так:
[UFW BLOCK] IN=eth0 OUT= MAC=... SRC=192.168.1.50 DST=10.0.0.5 LEN=60 TOS=0x00 ... PROTO=TCP SPT=45321 DPT=8080 ...
Здесь администратор видит интерфейс (IN=eth0), IP-адрес источника (SRC), IP-адрес назначения (DST), протокол (PROTO=TCP) и целевой порт (DPT=8080). Эта информация позволяет точно определить, какое разрешающее правило необходимо добавить.
Комплексный подход к безопасности требует совместного использования инструментов. ufw блокирует несанкционированный доступ к сервисам извне, отсекая большую часть векторов атак на сетевом уровне. Если же легитимный сервис (например, веб-сервер, доступный через открытый порт 80) скомпрометирован через уязвимость в коде, в дело вступает AppArmor. Он не позволит взломанному процессу выйти за пределы своего профиля, прочитать системные файлы или запустить несанкционированные бинарные файлы. Понимание этих двух слоев защиты — сетевого и системного — является необходимой базой перед переходом к изучению низкоуровневой контейнеризации, где изоляция строится на тех же принципах пространств имен и модулей безопасности ядра.