← Все гайды AI Release
EN Подписаться на @ai_release1

Пошаговое руководство: как провести оценку внешней поверхности атаки с помощью ИИ в CVEngine

Обновлено: 25.10.2026 · AI Release · @ai_release1
Пошаговое руководство: как провести оценку внешней поверхности атаки с помощью ИИ в CVEngine

TL;DR

> В исходных материалах канала нет спецификации CVEngine (эндпоинты, имена полей, лимиты). Всё, что относится к самому продукту, помечено как «сверьтесь с документацией»; остальные шаги — стандартные и проверяемые.

Требования и подготовка

Иллюстрация к разделу «Требования и подготовка»
Иллюстрация к разделу «Требования и подготовка»

Пример: проверка окружения одной командой.

curl --version | head -n1; jq --version; nmap --version | head -n1; dig -v

Ожидаемый вывод — четыре строки с версиями, например jq-1.6. Если jq не найден, установка выше не выполнилась.

Если CVEngine или сканер вы разворачиваете на своём железе, порядок подготовки машины описан в гайде по подключению ИИ к домашнему серверу.

Чек-лист перед стартом:

Шаг 1. Инвентаризация внешних активов и проверка DNS

Что сделать: создать рабочую папку, файл периметра asm/scope.txt и таблицу asm/out/resolved.csv с парами «хост → IP».

Зачем: поверхность атаки (attack surface) — это все ваши активы, доступные из интернета. ИИ-слой анализирует только то, что вы ему подали, поэтому мусор в списке хостов = мусор в отчёте.

mkdir -p asm/raw asm/out
cat > asm/scope.txt <<'EOF'
www.example.com
api.example.com
vpn.example.com
EOF

Пример: www.example.com — плейсхолдер. Замените на домены из своего RoE, по одному в строке, без https://.

Теперь разрешите имена в IP:

while read -r h; do
  ip=$(dig +short "$h" | tail -n1)
  echo "$h,${ip:-NXDOMAIN}"
done < asm/scope.txt | tee asm/out/resolved.csv

Ожидаемый вывод:

www.example.com,93.184.216.34
api.example.com,93.184.216.35
vpn.example.com,NXDOMAIN

Как проверить: grep -c NXDOMAIN asm/out/resolved.csv. Если счётчик больше нуля — эти хосты не существуют в DNS или опечатка в имени; исправьте до перехода к шагу 2, иначе curl и nmap упадут на них с ошибкой.

Почему это работает: dig +short отдаёт только ответ резолвера, tail -n1 берёт последнюю A-запись, а ${ip:-NXDOMAIN} подставляет заглушку вместо пустой строки, чтобы CSV не «съехал».

Шаг 2. Сбор данных сканирования и передача в ИИ-модуль CVEngine

Иллюстрация к разделу «Шаг 2. Сбор данных сканирования и передача в ИИ-модуль CVEngine»
Иллюстрация к разделу «Шаг 2. Сбор данных сканирования и передача в ИИ-модуль CVEngine»

Что сделать: снять порты и версии сервисов, добавить HTTP-заголовки и данные TLS-сертификата, собрать всё в assets.json и отправить в CVEngine.

Зачем: ИИ-слой сопоставляет версии сервисов с известными уязвимостями, убирает дубли и ранжирует находки по критичности. Вручную сверять 50 баннеров с базами CVE — это часы; машина делает это за секунды. Точный эндпоинт и имена полей запроса — сверьтесь с документацией CVEngine.

Шаг 2.1 — сканирование портов и версий:

nmap -sT -sV --top-ports 100 -T4 \
  -iL <(cut -d, -f1 asm/out/resolved.csv | grep -v NXDOMAIN) \
  -oX asm/raw/scan.xml

-sT — connect-скан без root, -sV — определение версий, --top-ports 100 — 100 самых частых портов, -oX — результат в XML для машинной обработки.

Шаг 2.2 — конвертация XML в JSON штатной библиотекой Python:

import json, xml.etree.ElementTree as ET

root = ET.parse("asm/raw/scan.xml").getroot()
assets = []
for host in root.findall("host"):
    addr = host.find("address").get("addr")
    for port in host.findall("ports/port"):
        state = port.find("state").get("state")
        if state != "open":
            continue
        svc = port.find("service")
        assets.append({
            "host": addr,
            "port": int(port.get("portid")),
            "service": svc.get("name") if svc is not None else "unknown",
            "version": (svc.get("product", "") + " " + svc.get("version", "")).strip(),
        })
json.dump({"assets": assets}, open("asm/out/assets.json", "w"), indent=2)
print(f"собрано активов: {len(assets)}")

Запуск: python3 to_json.py. Ожидаемый вывод — собрано активов: 37 (число зависит от вашего периметра).

Шаг 2.3 — обогащение HTTP-заголовками и сертификатами:

for h in $(grep -v NXDOMAIN asm/out/resolved.csv | cut -d, -f1); do
  echo "== $h"
  curl -sSI --max-time 10 "https://$h" | head -n 5
  echo | openssl s_client -connect "$h:443" -servername "$h" 2>/dev/null \
    | openssl x509 -noout -subject -dates
done | tee asm/out/http_tls.txt

Результат — блоки вида == api.example.com, строка Server: nginx, затем notAfter=Mar 1 12:00:00 2026 GMT. Просроченный notAfter — сам по себе находка.

Шаг 2.4 — отправка в CVEngine:

export CVENGINE_API_BASE="https://<адрес-вашего-инстанса>"
export CVENGINE_TOKEN="<токен-из-личного-кабинета>"

curl -sS -X POST "$CVENGINE_API_BASE/<эндпоинт-загрузки-активов>" \
  -H "Authorization: Bearer $CVENGINE_TOKEN" \
  -H "Content-Type: application/json" \
  --data @asm/out/assets.json \
  -o asm/out/ai_report.json -w "%{http_code}\n"

Как проверить: код ответа 200 и валидный JSON в отчёте — jq 'keys' asm/out/ai_report.json. Должен вернуться массив ключей, например ["findings","summary"]; имена зависят от версии продукта — сверьтесь с документацией. Если вместо JSON пришёл HTML, см. раздел проблем.

Шаг 3. Проверка результата: подтверждение находок и приоритизация

Иллюстрация к разделу «Шаг 3. Проверка результата: подтверждение находок и приоритизация»
Иллюстрация к разделу «Шаг 3. Проверка результата: подтверждение находок и приоритизация»

Что сделать: разобрать ai_report.json, вручную подтвердить 3–5 верхних находок и зафиксировать итоговую таблицу.

Зачем: ИИ выдаёт гипотезы, а не доказательства. Версия nginx 1.18.0 в баннере может быть подменена или устареть — приоритет ставится только после ручного подтверждения.

Выборка топ-находок:

jq -r '.findings | sort_by(-.score) | .[:5][] | "\(.host):\(.port) \(.service) — \(.score)"' \
  asm/out/ai_report.json

Пример: что должно появиться на экране.

93.184.216.34:443 nginx 1.18.0 — 8.7
93.184.216.35:22 openssh 8.2p1 — 6.1
93.184.216.35:8443 unknown — 5.4

Подтверждение одной находки:

nmap -sV -p 443 93.184.216.34
curl -sI https://api.example.com | grep -iE 'server|strict-transport'

Ожидаемый результат: та же версия в выводе nmap, что и в отчёте ИИ, и отсутствие Strict-Transport-Security в заголовках — это подтверждает находку, а не пересказывает её.

Итоговая таблица, которую вы отдаёте владельцу периметра:

ПриоритетАктивПризнакЧем подтвердили
193.184.216.34:443устаревший `nginx 1.18.0``nmap -sV -p 443`
293.184.216.35:22SSH открыт в интернет`nmap -sT -p 22`
3api.example.comнет HSTS, сертификат истекает`curl -sI`, `openssl x509`

Как проверить: чек-лист приёмки.

Регулярное пересканирование (раз в неделю) удобно вешать на мониторинг с уведомлением в Telegram — схема разобрана в гайде по мониторингу VPS через Telegram-бота.

Возможные проблемы и решения

Проблема. Хост в списке есть, а данных по нему нет

Проблема. Ответ CVEngine не разбирается

Проблема. Сканирование падает сразу

Резюме и следующие шаги

Вы собрали инвентарь периметра, обогатили его данными nmap/curl/openssl, прогнали через ИИ-слой CVEngine и подтвердили верхние находки руками. Дальше — поставьте пересканирование по расписанию и сравните два отчёта, чтобы видеть только новые активы и новые находки.

FAQ

Чем оценка поверхности атаки отличается от пентеста?

ASM ищет и инвентаризирует всё, что торчит в интернет, и ранжирует риски без эксплуатации уязвимостей; пентест — это санкционированная попытка реально проэксплуатировать найденное.

Нужен ли root для nmap -sT?

Нет. Connect-скан устанавливает обычное TCP-соединение через системный вызов, поэтому работает от обычного пользователя. Root нужен для -sS и -O.

Можно ли сканировать чужие домены, чтобы «проверить»?

Нельзя. Сканируйте только активы из подписанного RoE; остальное — неправомерный доступ, даже если вы ничего не эксплуатировали.

Что делать с находками, которые ИИ выдал, а nmap не подтвердил?

Помечайте как ложное срабатывание и сохраняйте пару «находка + вывод проверки» — это обучающий материал для настройки правил на следующей итерации; конкретные настройки скоринга сверьте с документацией CVEngine.

🤖 Кратко для ИИ