или как мы угостили Nuclei его же фаст-фудом и приручили KESL

В тот летний вечер я всего-то хотел дождаться выхода очередного релиза своего какафон-рок проекта — он традиционно выкатывается в 00:01 по мск, а потом надо раскидать релиз по чатам-каналам и лечь спать.

Но вместо спокойного вечера с сериальчиком мне прилетела задачка от одного крупного госзаказчика: «Касперский кладёт в карантин IP-адрес фронта, когда ваша СКИПА PentOps его мониторит — что делать?»

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

1. Синдром заблокированного фронта или «Что вообще происходит?»

Архитектура у заказчика классическая:
Интернет → Terminat0r-LB → backend, где на каждом узле бекенда крутится Kaspersky Endpoint Security for Linux (KESL), а паранойя включена ровно на максимум: Network Threat Protection (NTP) ловит всё, что напоминает атаку, и… банит IP-адрес, откуда прилетели пакеты.

Фронт стоит за балансером, X-Forwarded-For он не смотрит, поэтому в карантин улетает именно адрес балансера, а не злобного бота-хакера из пула СКИПА СайберОК. Через час блок снимается, но за это время EASM не ищет баги, SLA горит, DevOpsы плачут, клиенты пишут нехорошее в поддержку.

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

2. Попытка воспроизвести (спойлер: не вышло)

Логика подсказывала:
«Повторяем скан ➔ видим блокировку ➔ дальше разберёмся».

Поднял минимальный стенд Nginx, прокинул через балансёр, запустил без пайплайна "все-все-все" шаблоны нуклея, авось что-то стрельнет.

nuclei -u http://target.example -t ~/nuclei-templates

— и… тишина.
KESL NTP молчит, IP-адрес жив. Казалось бы, «задача решена» — но нет, в бою фронтенд всё равно улетает в карантин. Значит, наш макет слишком «чистый», сигнатурам не за что зацепиться. Пришлось копать глубже.

3. Эхо-сервер: первая, но наивная идея

Как только антивирусу не нравится то, что мы отдаём, давайте отдавать то, что он хочет.

Сварганил самый простой «эхо» (псведокод, исходники в гите в конце статьи):

from flask import Flask, request
app = Flask(__name__)

@app.route("/", defaults={"path": ""})
@app.route("/<path:path>", methods=["GET", "POST"])
def echo(path):
    return f"{request.method} {request.full_path}", 200

Прогнал — снова ноль срабатываний.

Открытие: KESL смотрит не только URI-паттерны, а ещё ответ сервера. Мы отдаём безобидный «OK», и антивирус безмятежен.

4. «Накорми сканер его же шаблоном» — рождение Nuk-Nuke

Каждый шаблон Nuclei (YAML-файл) хранит:

  • путь запроса (path или raw)

  • и самое главное — matchers: набор признаков «успешной атаки»(статус-код, строки, регекспы, заголовки).

matchers:
  - type: status
    status:
      - 200
  - type: word
    words:
      - "<title>It works!</title>"

И тут щёлкнуло:

Если мы вернём сканеру именно такой статус и текст, шаблон сработает, Nuclei закричит «CRITICAL» — а NTP, увидев точно тот маркер, вешает бан.

Так родился Nuk-Nuke — мини-сервер, который парсит все шаблоны и автоматически подделывает «успешный взлом».

5. Как устроен «Нюк-Нюк»

5.1 Генерируем кэш

  • В каталоге ~/nuclei-templates — 10 000+ YAML-ов.

  • Проходим их ProcessPoolExecutor-ом, вытаскиваем (path, status, headers, body).

  • Кладём в один MsgPack. Разок считаем — и стартуем за 0,3 с.

python decoy_server.py --rebuild-cache

5.2 Отдаём правильные ответы

@app.before_request
def dispatch():
    entry = DECOYS.get(normalise(request.path))
    if entry:
        status, hdrs, body = entry
        return make_response(body, status, hdrs)

Пара штрихов:

  • Заменяем заголовки, чтобы ответ походил на Apache, а не на Flask dev-server.

  • Поддерживаем --prod (Waitress), чтобы не палить баннеры Werkzeug.

Полный код в репозитории.

6. Демон-тест

  1. Запускаем сервер:

    export DECOY_SERVER_HEADER="Apache/2.4.57"
    python decoy_server.py --prod --port 8080
  2. Стреляем Nuclei:

    nuclei -u http://127.0.0.1:880 -t ~/nuclei-templates 
  3. Через пару секунд в kesl-control --get-blocked-hosts — наш IP.
    Проблема воспроизведена на локалке, можно охотиться на «токсичные» шаблоны.

7. Фильтруем термо-яд — минус четыре* шаблона

Оказалось, банят ровно четыре древних CVE (Tomcat, Atlassian, Log4Shell).
Достаточно запустить бой-скан без них:

nuclei -t ~/nuclei-templates \
       -et http/cves/2017/плохой.yaml,http/cves/2021/плохой.yaml \
       -l prod-endpoints.txt

— и KESL больше не реагирует.

*На самом деле все немного сложнее, за эти 4 алерта отвечает пачка шаблонов (особенно за Log4j), но с помощью Nuk-Nuke они очень быстро собираются.

8. Это ок, но нужно лучше

Ок, мы собрали плохие шаблоны, но что если вылезут другие сигнатуры в будущем? В идеале надо все-таки добавить IP-фронта в исключения. На какой-то момент я сдался и обратился в поддержку.
Их ответ был профессиональным и исчерпывающим.

Эта великая мудрость привела меня к силе и, початив c Гуглом и Гопотой минут десять, я нашел рабочий вариант.

# Узнать имя задачи
sudo kesl-control --get-task-list | grep -i network_threat

# Включить исключения и добавить IP
sudo kesl-control --set-settings Network_Threat_Protection \
     UseExcludeIPs=Yes \
     ExcludeIPs.item_0000=10.10.10.10

# Перезапустить задачу
sudo kesl-control --stop-task Network_Threat_Protection
sudo kesl-control --start-task Network_Threat_Protection

9. Что прокачать дальше

Идея

Зачем

Tarpit-mode

Спать врагу: после первой «атаки» кладём соединение на паузу 5с

Рандомизация баннеров

Мешаем IIS/Apache/Nginx, чтобы ловились разные сигнатуры

Плагин для Nginx

Отдавать поддельный ответ прямо из error_page 404

Стрим логов в Loki / Slack

Собирать IP-адреса реальных сканеров в SOC

10. Выводы

  • Nuk-Nuke позволяет на тестовом стенде быстро понять, какие именно nuclei-шаблоны бьют по антивирусу/IDS.

  • После этого достаточно одной короткой строки -et (или исключения в KESL) — и фронтовый IP жив, сканы идут, NTP остаётся включённым.

  • Проверить на баги чтобы не взломали через антивзломщик.

  • Весь проект — полчаса вайбкодинга.

  • Я успел все заделать к выходу какафон-рок релиза, ура!

Иногда, чтобы обмануть защиту, нужно всего-навсего показать ей то, что она ожидает увидеть.

Слайды доклада лежат у нас в телеге, а полный код «Нюк-Нюка» — прямо тут. Забирайте, экспериментируйте и не давайте сканерам скучать!

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


  1. j_larkin
    18.07.2025 14:19

    этот?
    этот?


    1. sgordey Автор
      18.07.2025 14:19

      Они братья в нюке, да. Шарят за 139й порт :)


  1. max9
    18.07.2025 14:19

    кажется что статья написана ради статьи :)

    достаточно сказать
    kesl-control -set-set 17 BlockAttackingHosts=No и спокойно разбираться не привлекая внимание санитаров и девопсин.

    и да, --set-settings работает на лету в 99% случаев, рестартить таску/продукт не надо.

    и, запихав в эксклюды вы пропустите все атаки, в тч "ложно-положительные"


    1. sgordey Автор
      18.07.2025 14:19

      Привет. Спасибо за хинт с BlockAttackingHosts=No, кажется прикольным вариантом если форвардить алерты в SEIM чтобы не пропустить что-то в проде, протестим.

      >  --set-settings работает на лету в 99% случаев, 

      Жаль, что вы не работаете в техподдержке ЛК %)

      Однако:
      1. Задача в т.ч. была выяснить корневую причину срабатывания, т.е. на какой трафил Каспер агрится. Просто отключив блокировку ты получишь только лог с набором 4х унылых cve-х (да простят меня экс-коллеги из АМР и Грейта) которые слабо соотносятся с реальными чеками
      2. В условиях был "большой госзаказчик" где внесение изменений без "санитаров и девопсин" привлечет внимание не только санитаров. Но и лесников. Ну те, которые всех разогнали. Поэтому нужно было воспроизвести на стенде и прочекать стоковые и кастомные чеки. Так родился Нюк-Нюк
      3. У Нюк-Нюка появилось и другое применение - спамить Нуклей-кидди. И еще классный маскот, вот :)

      >и, запихав в эксклюды вы пропустите все атаки, в тч "ложно-положительные"

      все так, прочекаем в связке с siem и фильтрацией алертов от пробника.

      Спасибо!


      1. max9
        18.07.2025 14:19

        кажется прикольным вариантом если форвардить алерты в SEIM чтобы не пропустить что-то в проде, протестим.

        к сожалению штатным сиемом это не шлется, только из КСЦ, как видно из текста у вас его как-то неочень.

        Задача в т.ч. была выяснить корневую причину срабатывания .... да простят меня экс-коллеги из АМР и Грейта

        ну раз вы все знаете, то можно было написать на newvirus@ :) там бы сразу сказали


        1. sgordey Автор
          18.07.2025 14:19

          Много сподобно куда написать, но как работает система гораздо интересней.