Готовые сканеры выдают замечания, но не объясняют устройство конкретного сервера. Разберём ручной аудит безопасности Linux: воспроизводимый набор команд, который проверяет учётные записи, открытые порты, права файлов, целостность пакетов и активность в логах. Чек-лист подходит для Debian, Ubuntu и RHEL-систем.
Фиксация базового состояния
Без зафиксированного нормального состояния находки невозможно интерпретировать. Сохраните вывод проверок в каталог с датой: через месяц сравнение покажет только реальные изменения.
mkdir -p /root/audit/$(date +%F)
cd /root/audit/$(date +%F)
ss -tlnp > listening.txt
dpkg --get-selections > packages.txt
find / -xdev -perm -4000 -type f > suid.txt 2>/dev/null
# сравнение с прошлым прогоном
diff -u /root/audit/2026-10-01/listening.txt listening.txt
Храните архив вне сервера: если машина скомпрометирована, локальные файлы правятся вместе с остальными. Регулярность важнее глубины: еженедельный прогон ценнее разового аудита.
Шаг 1. Учётные записи и права
Сначала смотрим на пользователей: лишние интерактивные аккаунты и второй держатель нулевого UID — самая частая находка на старых серверах, которые годами не пересматривали.
# аккаунты с интерактивной оболочкой
awk -F: '$7 !~ /(nologin|false)$/ {print $1, $3, $7}' /etc/passwd
# держатели нулевого UID кроме root
awk -F: '$3 == 0 {print $1}' /etc/passwd
# состояние всех паролей
sudo passwd -S -a | grep -v " NP "
# история входов и попытки перебора
last -F | head -40
sudo lastb | head -30
Следите за аккаунтами без срока действия в chage -l. Попытки перебора видны в lastb: повторяющиеся имена с одного адреса — повод закрыть доступ.
Шаг 2. Слушающие сокеты и файрвол
Каждый открытый порт — потенциальная точка входа. Сравните список с перечнем сервисов, которые действительно должны работать на этой машине.
# все TCP-слушатели с именем процесса
sudo ss -tlnp
# UDP-слушатели: о них чаще всего забывают
sudo ss -ulnp
# действующие правила файрвола
sudo nft list ruleset | head -60
Службы вроде rpcbind или устаревшего telnet встречаются регулярно: их оставляли от старых установок. Отключайте то, что не используется, — неиспользуемый демон не должен запускаться вовсе.
Шаг 3. Бинарники, возможности и права
SUID-файлы запускаются с правами владельца и потому всегда на прицеле. Проверьте, что список оправдан, не вырос сам собой и не содержит интерпретаторов.
# файлы с битами SUID и SGID
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null
# возможности вместо бита SUID
getcap -r / 2>/dev/null | head -30
# файлы, доступные на запись всем
find /etc /opt /srv /var/spool -xdev -perm -0002 -type f 2>/dev/null
# содержимое каталогов cron
sudo ls -lR /etc/cron.d /var/spool/cron
Найденные python, vim или find с битом SUID почти всегда следствие ручной настройки. Убирайте бит, если в задаче он не нужен, а исключения фиксируйте комментарием.
Шаг 4. Целостность и обновления
Пакетный менеджер находит подмену системных файлов: проверка сверяет хэши из индекса с текущим содержимым.
# Debian и Ubuntu
dpkg -V 2>/dev/null | head -40
# RHEL и производные
sudo rpm -Va 2>/dev/null | head -40
# ожидающие обновления безопасности
apt list --upgradable 2>/dev/null | grep -ci security
# версия ядра и автообновления
uname -r
systemctl is-enabled unattended-upgrades
Изменения в /etc/ssh/sshd_config он не заметит, поэтому настройки сравнивайте с эталонной копией или через утилиту etckeeper, которая хранит /etc в системе контроля версий.
Шаг 5. Логи и активность
Последний блок отвечает на вопрос, не происходило ли чего-то уже. Смотрят на отказы аутентификации, запуски от root и исполнение команд через аудит ядра, если он включён.
# отказы входа и их источники
sudo journalctl -u ssh --since "30 days ago" | grep -c "Failed password"
sudo journalctl -u ssh --since "30 days ago" | grep "Failed password" | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10
# запуски sudo за неделю
journalctl -t sudo --since "7 days ago" | grep COMMAND | tail -30
# исполнение команд, если настроен auditd
sudo ausearch -m execve -ts recent | head -20
Если auditd не запущен, включите его и настройте минимальное правило в /etc/audit/rules.d/: без фильтра журнал переполнит диск за день.
Шаг 6. SSH и критические конфигурации
Открытый SSH остаётся главной точкой входа: сравните действующий конфигурационный файл с эталонной копией, убедитесь, что вход от root и по паролю запрещены, а ключи в authorized_keys принадлежат нужным людям.
# действующая конфигурация с учётом всех подключенных файлов
sudo sshd -T | grep -Ei "^(permitrootlogin|passwordauthentication|pubkeyauthentication|x11forwarding)"
# владельцы и права у всех выданных ключей
sudo find /home /root -path "*/.ssh/authorized_keys" -exec ls -l {} \;
# права на конфигурационный файл демона
sudo stat -c "%a %U %n" /etc/ssh/sshd_config
# проверка синтаксиса перед перезапуском службы
sudo sshd -t && sudo systemctl reload ssh
Отдельно проверьте, что демон не слушает на всех адресах: ограничение по интерфейсу в сочетании с правилом файрвола закрывает перебор паролей.
Шаг 7. Автоматизация прогона
Однотипные проверки превращают в скрипт: сравнение результатов двух дат показывает только реальные изменения.
#!/bin/bash
# /usr/local/sbin/server-audit.sh
OUT=/root/audit/$(date +%F); mkdir -p "$OUT" /root/audit/baseline
/usr/bin/ss -tlnp > "$OUT/listening.txt"
/usr/bin/dpkg -V > "$OUT/modified.txt" 2>/dev/null
/usr/bin/find / -xdev -perm -4000 -type f > "$OUT/suid.txt"
/usr/bin/cp -a /etc/ssh/sshd_config /root/audit/baseline/sshd_config
/usr/bin/diff -u /root/audit/baseline/listening.txt "$OUT/listening.txt"
Строки в modified.txt указывают на изменённые системные файлы, а diff показывает, какие порты появились или пропали. Держите копии каталога audit вне сервера: после компрометации локальные отчёты не достоверны.
Чек-лист одним прогоном
- Зафиксировать baseline: слушатели, пакеты, SUID-файлы, содержимое cron.
- Пройти по интерактивным аккаунтам, нулевым UID и срокам паролей.
- Сверить открытые порты с перечнем нужных сервисов.
- Проверить SUID, capabilities, файлы с правом записи для всех.
- Прогнать dpkg -V или rpm -Va и список ожидающих обновлений.
- Изучить отказы входа, sudo-команды и включённый аудит ядра.
- Сохранить отчёт вне сервера и назначить дату следующей проверки.
Итог
Ручной аудит — это не поиск экзотических уязвимостей, а проверка соответствия сервера ожиданиям: лишних пользователей нет, лишних портов нет, системные файлы не менялись, обновления применяются. Держите чек-лист в репозитории, прогоняйте его по расписанию и сравнивайте результаты с базовой копией. Так вы узнаете о проблеме раньше, чем её обнаружит кто-то другой.