Харденинг ОС и хоста
Каждый запущенный сервис, открытый порт и поставляемое умолчание — это поверхность атаки. Харденинг ужимает хост до его реальной задачи, меняет разрешающие умолчания на безопасные и закрепляет измеримую базовую линию, делая дрейф видимым.
Свежий облачный образ Ubuntu загружается, и ещё до того, как ты в первый раз зайдёшь по SSH, ss -tlnp уже показывает горстку слушателей, которых ты не просил: рекурсивный резолвер, привязанный к публичному интерфейсу, спулер печати из десктопного мета-пакета, демон SNMP с до сих пор выставленным community-строкой public. Каждый — это сервис, которым ты не пользуешься, который не аудировал и не пропатчишь вовремя. И каждый — это дверь. Тебя ещё никто не атаковал. Образ просто приехал с открытыми дверями, и «умолчание» — самое опасное слово в инфраструктуре.
К концу этого урока ты будешь знать, как ужать хост ровно до той задачи, которую он выполняет, заменить разрешающие умолчания на безопасные и закрепить базовую линию так, чтобы дрейф конфигурации стал тем, что ты видишь, а не тем, что обнаруживаешь посреди инцидента.
Поверхность атаки — это сумма того, что достижимо
Прежде чем харденить хост, нужна точная модель того, до чего реально может дотянуться атакующий. Поверхность атаки хоста — это объединение всех интерфейсов, где недоверенный ввод встречается с твоим кодом: слушающие сетевые порты, запущенные сервисы и их RPC-эндпоинты, локальные setuid-бинарники, модули ядра, открытые файловые системы, плановые задачи и учётные данные, под которыми всё это работает. Каждый пункт — потенциальный вход или потенциальная эскалация. Рычаг защитника прост до жестокости и эффективен до жестокости: тебя нельзя проэксплуатировать через сервис, который не запущен. У удалённого кода нет CVE.
Именно поэтому сокращение поверхности атаки — самый высокорычажный шаг в безопасности хоста и самый дешёвый. Патч чинит один известный баг в сервисе; удаление сервиса чинит все баги, которые в нём когда-либо будут, включая ещё не обнаруженные. Когда прилетели классы багов вроде Shellshock (2014) и PrintNightmare (2021), отмахнулись не те хосты, что патчились быстрее всех, — а те, что вообще никогда не ставили уязвимый компонент. Сокращение бьёт реакцию.
Минимизация сервисов: вычитай, прежде чем добавлять
Минимизация сервисов — это дисциплина запускать минимальный набор процессов, нужных хосту для его одной задачи, и ничего больше. Машине, которая обслуживает HTTP, не нужны почтовый агент, десктопный DNS-резолвер, Avahi/mDNS, CUPS или X-сервер. Операционный тест для каждого слушателя — одно предложение: назови конкретную функцию, которую он обслуживает, и команду-владельца. Не можешь — он не должен работать.
На практике ты проходишь по поверхности и срезаешь:
- Аудит слушателей —
ss -tulpn(илиss -tlnpдля TCP) сопоставляет каждый открытый порт с процессом и PID, который его держит. Всё, что не можешь назвать, останавливается. - Сначала отключи, потом удали —
systemctl disable --now <svc>не даёт ему пережить перезагрузку;apt purge/dnf removeстирает бинарник, чтобы его нельзя было снова включить или проэксплуатировать. - Привязывай к самому узкому интерфейсу — сервис, который говорит только с localhost, должен слушать
127.0.0.1, а не0.0.0.0. База, привязанная к0.0.0.0с дефолтным паролем, — так и попадают в записку с требованием выкупа. - Файрвол по умолчанию запрещает — отбрасывай весь входящий, затем разрешай только названные порты. Файрвол — твоя страховка для сервиса, который ты забыл отключить.
Безопасные умолчания: выжившие должны быть безопасны из коробки
У всех сервисов, переживших минимизацию, умолчания настроены на быстрый старт, а не на продакшен-безопасность — а это противоположные цели. Поставляемые умолчания оптимизированы под «работает с первого запуска без конфигурации», а это значит широкие привязки, многословные ошибки, разрешающие права и образцовые учётки. Харденинг переворачивает каждое из этих умолчаний в deny-by-default: конфигурация стартует с самой ограничительной настройки и открывает только то, что названо явно.
| Поверхность | Рискованное умолчание | Укреплённая настройка | Почему важно |
|---|---|---|---|
| SSH | Пароль + вход под root | Только ключи, PermitRootLogin no | Убивает подбор и credential-stuffing |
| Привязка БД | 0.0.0.0, образцовый пароль | 127.0.0.1, ротируемый секрет | База недостижима из интернета |
| Файрвол | Разрешать весь входящий | Drop по умолчанию, разрешить порты | Страховка для забытого сервиса |
| Сервисы | Работа под root | Непривилег. юзер, сброшенные caps | Компрометация остаётся локальной |
| Ошибки | Многословные трейсы, баннеры | Общие ошибки, версия скрыта | Лишает атакующего бесплатной разведки |
Два самых ценных умолчания для исправления — аутентификация и привилегии. SSH с парольной аутентификацией и включённым входом под root — самая брутфорсимая поверхность в публичном интернете; переход на вход только по ключам с PermitRootLogin no убирает весь класс атак на угадывание учёток. А принцип наименьших привилегий применим к каждому процессу: веб-сервер, скомпрометированный во время работы под root, — это скомпрометированный хост; тот же эксплойт против сервиса, работающего под непривилегированным пользователем со сброшенными Linux-capabilities, — это скомпрометированный процесс, разница между инцидентом и катастрофой.
▸Почему это работает
Почему удалить сервис строго лучше, чем пропатчить его? Патч — это обещание про известные баги: он закрывает раскрытые на сегодня CVE, в день, когда ты его применил, при условии что ты применил его вовремя (а медианное время до патча в индустрии измеряется неделями, не часами). У удалённого сервиса нет поверхности атаки вообще: ни zero-day, ни задержки патча, ни агента, который надо держать свежим, ни конфигурации для дрейфа. Патчинг — гонка, которую ты бежишь вечно; удаление гонку завершает. Поэтому «а оно нам вообще нужно?» — первый вопрос харденинга, задаваемый раньше «оно пропатчено?».
Базовые линии: сделать укреплённое состояние измеримым и долговечным
Хост, который ты захарденил руками, укреплён один раз. Через три месяца и сорок деплоев кто-то снова включил сервис, чтобы дебажить аварию, прогон config-management откатил настройку, пересборка образа уронила твои правила файрвола — а ты не в курсе, потому что «укреплён» жил только в памяти одного инженера. Лекарство — базовая линия: записанное, машинно-проверяемое определение известно-хорошего безопасного состояния хоста плюс непрерывное сравнение с ним.
Ровно это и дают CIS Benchmarks — построенные по консенсусу, предписывающие конфигурационные базовые линии для каждой ОС и платформы, где каждый контроль указывает и проверку аудита, и шаг исправления. NIST SP 800-123 формулирует ту же идею на уровне программы: укрепи до документированного стандарта, а затем поддерживай его. Базовая линия превращает харденинг из героического разового усилия в принудительно соблюдаемое свойство:
- Закрепи как код — закодируй базовую линию в Ansible/Chef/Puppet или в золотом образе, чтобы каждый хост рождался укреплённым, а не укреплялся постфактум.
- Аудируй непрерывно — инструменты вроде OpenSCAP,
Lynisили скан CIS-CAT оценивают живой хост против бенчмарка и выдают балл плюс список проваленных контролей. - Алертуй на дрейф — когда живой хост расходится с базовой линией, эта дельта — событие безопасности, а не сноска. Дрейф часто оказывается первым видимым признаком либо небрежного изменения, либо активного вторжения.
Скан находит спулер печати CUPS, слушающий на продакшен-веб-хосте, у которого нет принтеров и который обслуживает только HTTP. Выбери лучший ответ харденинга.
Почему удаление неиспользуемого сервиса в общем случае более сильный контроль, чем держать его пропатченным?
Ты захарденил хост руками, и он проходит скан CIS с высоким баллом. Через шесть недель — какая наиболее вероятная причина, что он больше не соответствует?
Упорядочь рабочий процесс харденинга хоста от первого шага к последнему:
- 1 Перечисли слушателей и сервисы (ss -tulpn), чтобы отобразить реальную поверхность
- 2 Минимизируй: отключи и удали каждый сервис, который не можешь назвать
- 3 Примени безопасные умолчания к выжившим (deny-by-default, наименьшие привилегии)
- 4 Закрепи укреплённое состояние как базовую линию по CIS (как код)
- 5 Непрерывно сканируй на дрейф и алертуй на расхождения
- 01Что такое поверхность атаки хоста и почему её сокращение даёт больший рычаг, чем патчинг?
- 02Что такое базовая линия и почему харденинг без неё распадается во времени?
Харденинг хоста — это дисциплина ужать машину ровно до той задачи, которую она выполняет, и удержать её там. Начни с отображения поверхности атаки — каждый слушающий порт, сервис, setuid-бинарник и привилегии, под которыми всё работает, — потому что тебя нельзя проэксплуатировать через сервис, который не запущен. Сначала минимизируй: перечисли слушателей через ss -tulpn, затем отключи и удали всё, чью функцию и владельца не можешь назвать, ведь у удалённого кода нет CVE, а удаление бьёт вечную гонку патчей. Затем сделай выживших безопасными из коробки, перевернув разрешающие умолчания в deny-by-default и наименьшие привилегии: SSH только по ключам без входа под root, базы, привязанные к localhost, файрволы с drop по умолчанию, сервисы под непривилегированным пользователем со сброшенными capabilities. Наконец, сделай это долговечным: закрепи укреплённое состояние как базовую линию по CIS, выраженную кодом, аудируй живые хосты непрерывно через OpenSCAP или CIS-CAT и считай любой дрейф от базовой линии событием безопасности — потому что хост, укреплённый руками, укреплён ровно один раз и распадается со следующим деплоем. И теперь, когда ты загружаешь свежий образ и ss -tlnp показывает слушателей, которых ты не просил, твой первый вопрос не «оно пропатчено?» — а «могу ли я назвать, что это делает, и если нет, почему оно работает?».
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.
Примени это
Примени этот урок в реальном проекте.