Перейти к содержимому
HoginHogin
Назад

Wazuh Active Response: автоматически банить, изолировать и реагировать на инциденты (часть 4/6)

8 мин чтения

В третьей части мы научили Wazuh видеть агрессивный брутфорс SSH: правило 100100 срабатывает на четвёртую неудачу за минуту с одного IP и поднимает алерт уровня 12. Проблема в том, что дальше в цепочке стоит человек: в три часа ночи между «детект сработал» и «кто-то закрыл IP на файрволе» проходит от двадцати минут до следующего утра, а брутфорсу хватит и пяти. Четвёртая часть — про то, как человека из этой цепочки убрать: Active Response, встроенный в Wazuh механизм, который сам банит IP, изолирует хост и запускает произвольные скрипты по сработавшим правилам — без внешнего SOAR.

Содержание

Открыть содержание

Что такое Active Response и где он живёт

Механизм достался Wazuh в наследство от OSSEC и с тех пор почти не менялся — тот же декларативный XML, что и правила, и такая же долгоживущая инвестиция. Идея простая: у каждого алерта есть level, rule id и группа, а у вас — список «если сработало вот это, выполнить вот то». Отдельного сервиса нет: решение принимает analysisd, исполнение доверено wazuh-execd.

От алерта к действию без человека

Ключевой нюанс схемы: скрипт должен лежать на том хосте, где он исполняется. Реакция local исполняется на агенте, приславшем событие, — значит, и скрипт, и nftables должны быть на каждом агенте. Это цена за возможность реагировать там, где идёт атака, а не там, где стоит сервер.

Встроенные команды: firewall-drop и когда его достаточно

В поставке уже есть готовые скрипты, и чаще всего хватает именно их:

firewall-drop — рабочая лошадка: для брутфорса SSH, сканеров и web-атак его достаточно в большинстве случаев. Включается блоком в ossec.conf на manager, скрипт уже входит и в серверный пакет, и в пакет агента.

Когда встроенного мало: нужен nftables-сет со своими таймаутами, вызов внешнего API — создать тикет, изолировать хост в EDR, погасить учётку в IdP — или реакция, зависящая от контекста алерта. Тогда пишете свой скрипт, и это ровно тот же контракт stdin/JSON, что и у встроенных.

Анатомия настройки: command и active-response

Настройка живёт в ossec.conf на manager и состоит из двух блоков — «что запускать» и «когда запускать»:

<command>
  <name>nft-ban</name>
  <executable>nft-ban.sh</executable>
  <timeout_allowed>yes</timeout_allowed>
</command>

<active-response>
  <command>nft-ban</command>
  <location>local</location>
  <rules_id>100100</rules_id>
  <timeout>600</timeout>
</active-response>

Практика: свой nftables-бан с safety-исключением

Собираем пример из заготовки: повторные неудачные аутентификации → IP уходит в nftables-сет, блокировка снимается сама, admin-подсеть не банится никогда. Реестра забаненных и cron-чистилок не будет — таймаут держит само ядро nftables.

База nftables на агенте, /etc/nftables.conf:

table inet wazuh_ar {
  set banned {
    type ipv4_addr
    flags timeout
  }
  chain input {
    type filter hook input priority -10; policy accept;
    ip saddr @banned drop
  }
}

Скрипт кладём в /var/ossec/active-response/bin/nft-ban.sh:

#!/usr/bin/env bash
# Active Response: бан srcip в nftables на 10 минут, admin-подсеть не трогаем.
LOG="/var/ossec/logs/active-responses.log"

INPUT=$(cat)
cmd=$(echo "$INPUT"   | jq -r '.command')
srcip=$(echo "$INPUT" | jq -r '.parameters.alert.data.srcip' | grep -E '^[0-9.]+$')

log() { echo "$(date '+%F %T') nft-ban [$cmd] $*" >> "$LOG"; }

[ -n "$srcip" ] || { log "no valid srcip — skip"; exit 0; }

# Safety: админ-подсети не баним никогда, даже если правило сработало
case "$srcip" in
  192.0.2.*|10.10.*) log "safety: $srcip is admin range — skip"; exit 0;;
esac

case "$cmd" in
  add)
    nft add element inet wazuh_ar banned { "$srcip" timeout 10m } \
      && log "blocked $srcip for 10m" || log "nft add failed for $srcip" ;;
  delete)
    nft delete element inet wazuh_ar banned { "$srcip" } 2>/dev/null \
      && log "unblocked $srcip" ;;
esac

Что здесь важно:

Установка и права — на каждом агенте, где скрипт будет исполняться:

install -m 750 -o root -g wazuh nft-ban.sh /var/ossec/active-response/bin/
systemctl restart wazuh-agent

Дальше — ossec.conf на manager (блоки из прошлого раздела) и systemctl restart wazuh-manager.

Как не забанить самого себя

Автобан хорош, пока банит чужих. Три рубежа, каждый спасает в своей ситуации:

Три рубежа против самобана

Про таймауты — две единицы, в которых легко запутаться: timeout в ossec.conf считается в секундах, а repeated_offenders — в минутах, и живёт он в ossec.conf агента, не manager:

<active-response>
  <repeated_offenders>30,60,1440</repeated_offenders>
</active-response>

Первое срабатывание банит на базовый timeout (600 секунд), второе — на 30 минут, третье — на час, четвёртое — на сутки. На Windows-агентах механизм не работает — учитывайте это в гетерогенном парке. Стартовые значения: 10–15 минут базового бана достаточно, чтобы убить перебор, и не так страшно, если под раздачу попал легитимный хост.

Жизненный цикл блокировки с эскалацией

И главное правило внедрения: тестируйте с адреса, потерять доступ с которого не жалко. Первая неделя — короткий timeout и tail логов; лестницу repeated_offenders наращиваете, когда поверили, что ложных срабатываний нет.

ВопросДежурный вручнуюfirewall-dropСвой AR-скрипт
Время реакцииминуты–часысекундысекунды
Что умеетвсё, что умеет человекблок srcip системным файрволомлюбой код: nftables, API, изоляция
Откатчеловекомtimeouttimeout или свой механизм
Ложное срабатываниерешает усталостьбан легитимного IP на N минутровно то, что вы написали
Стоимость входауже оплаченаодин блок в ossec.confскрипт + тест на стенде

Как проверить, что всё работает

Wazuh-logtest тут не помощник: он гоняет правила в изолированной сессии и active response не запускает — проверять нужно живым событием.

С запасного хоста, не из admin-подсети, четыре неудачные SSH-попытки на агент:

for i in 1 2 3 4; do sshpass -p wrong ssh nosuchuser@AGENT_IP true; done

На manager — что алерт поднялся и дошёл до реакции:

tail -f /var/ossec/logs/alerts/alerts.json | grep 100100

На агенте — жизнь самого скрипта и результат:

tail -f /var/ossec/logs/active-responses.log
nft list set inet wazuh_ar banned

В сете должен появиться адрес с тикающим вниз timeout, а SSH с тестового хоста — перестать отвечать. Через десять минут элемент исчезает сам: так вы проверяете и бан, и откат. Если active-responses.log пуст — смотрите /var/ossec/logs/ossec.log на ошибки execd и проверьте, что rules_id совпадает, а у скрипта права 750 root:wazuh.

Итог

Обнаружение без реагирования — это просто дорогой лог: красиво, но атака к моменту прочтения уже закончилась. Active Response не заменит полноценный SOAR — здесь нет оркестрации, плейбуков и approval-цепочек, — но первый шаг к автоматическому ответу он закрывает почти бесплатно: один блок в ossec.conf на встроенный firewall-drop, сорок строк bash для nftables с safety-исключением и таймаутом — и ваш SIEM из второй и третьей частей впервые не только видит брутфорс, но и сам закрывает атакующему IP. В пятой части цикла уходим в Kubernetes: собираем аудит-логи кластера и учимся видеть, кто и что в нём делает.


Поделиться:

Следующая статья
Wazuh: пишем свои правила и decoders, чтобы SIEM не захлебнулся шумом (часть 3/6)