Когда я разговариваю с джуниор-пентестерами, почти у каждого одна и та же проблема: находят CVE-идентификатор в результатах сканирования, вставляют его в поисковик, читают описание на NVD - и зависают. Описание сухое, терминология мутная, а готовый эксплойт на Exploit-DB есть далеко не всегда. В итоге уязвимость либо помечается как «критическая» на основании одного CVSS-скора (менеджер доволен, толку ноль), либо пропускается, потому что нет очевидного пути к эксплуатации.
Эта статья - про конкретный навык: анализ CVE уязвимостей как отправная точка для построения атаки. Не для отчёта по комплаенсу, не для дашборда с метриками - для реального engagement, где из advisory без исходного кода нужно вырастить тестируемую гипотезу. Покажу, какие поля читать первыми, как интерпретировать CVSS-вектор для планирования атаки, зачем смотреть на CWE раньше описания, и как patch diffing заменяет исходники, когда их нет.
Что реально содержит CVE-advisory и почему этого мало
Русскоязычные материалы по теме CVE описывают формат записи («CVE-год-номер»), историю создания MITRE и общие слова про CVSS. Для понимания контекста сгодится, а на engagement - бесполезно. Типичная CVE-запись содержит:- CVE ID - уникальный идентификатор
- Description - текстовое описание (от одного предложения до абзаца)
- CVSS Score и Vector - числовая оценка и строка метрик
- CWE - классификация корневой причины
- Affected Products (CPE) - список затронутых продуктов и версий
- References - ссылки на vendor advisory, патчи, Exploit-DB, GitHub
Рассчитывать на полноту NVD-записи нельзя. CVE-advisory - стартовая точка, а не финишная. Настоящий анализ описания уязвимости начинается после того, как вы вытянули из записи всё, что можно, и отправились за деталями в vendor bulletin, changelog и бинарные diff-ы патчей.
Как читать CVE описание: пять полей, которые определяют вектор атаки
Когда я открываю свежую CVE на NVD, я не начинаю с описания. Описание - литературный пересказ, часто написанный вендором и намеренно размытый. Мой порядок чтения:- CWE - что за класс уязвимости? Сразу даёт ментальную модель эксплуатации.
- CVSS Vector - не скор, а именно строка вектора. В ней больше информации об атаке, чем в числовой оценке.
- Affected Products / Versions - какие компоненты затронуты, какие версии.
- References - есть ли ссылка на vendor advisory, на GitHub commit (патч), на Exploit-DB.
- Description - и только потом текст. Теперь я читаю его с уже сформированным контекстом.
CVSS-вектор - не оценка опасности, а карта attack surface
CVSS-скор - число для менеджеров. CVSS-вектор - информация для пентестеров. Разница примерно как между «машина быстрая» и «V8, 450 л.с., задний привод, механика». Разберём на реальных примерах.CVE-2021-44228 (Log4Shell): вектор
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H, скор 10.0 CRITICAL.Что здесь читается:
AV:N- атака по сети, локальный доступ не нуженAC:L- низкая сложность, специальных условий нетPR:N- привилегии не требуютсяUI:N- жертве не нужно ничего делатьS:C- Scope Changed, атака выходит за границы уязвимого компонента (Log4j триггерит загрузку с внешнего LDAP, выполнение происходит в контексте приложения)
CVE-2022-30190 (Follina): вектор
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H, скор 7.8 HIGH.На первый взгляд,
AV:L (Local) и UI:R (User Required) делают эту CVE «менее интересной». Но PR:N говорит: привилегии не нужны. А реальность такова: Follina эксплуатируется через специально подготовленный документ Word. Пользователь открывает файл - MSDT вызывается через URL-протокол - RCE. CVE в CISA KEV, помечена как используемая в ransomware-кампаниях. Формально - Local vector. Практически - Exploitation for Client Execution (T1203, Execution), один из самых ходовых сценариев целевых атак.Вывод: CVSS 9.8 иногда менее интересен для пентестера, чем CVSS 6.8 с правильным вектором. CVE-2016-0128 (Badlock) - скор 6.8 MEDIUM, вектор
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N (CWE-254, deprecated-категория Security Features; современная классификация - CWE-300 или CWE-757 для downgrade-атак). Сетевой вектор, привилегии не нужны, но высокая сложность и действие пользователя. UI:R здесь означает, что жертва должна инициировать подключение через скомпрометированный канал (аутентификация через MitM-прокси). Обратите внимание на C:H/I:H - высокое влияние на конфиденциальность и целостность, что критично для MitM-сценария с protocol downgrade на SAM/LSAD (связанная CVE-2016-2118 - аналогичная проблема в Samba). Публичных PoC на Exploit-DB для CVE-2016-0128 и связанной CVE-2016-2118 нет, но сам вектор атаки может быть ценнее, чем очередная критическая SQLi в веб-панели, до которой не дотянуться из-за WAF.CWE классификация: от абстрактной слабости к эксплуатационному примитиву
CWE - классификация уязвимостей, которую большинство пентестеров игнорирует. Зря. CWE напрямую указывает на тип эксплуатационного примитива, а значит - на класс техник, которые стоит пробовать.Практическая таблица маппинга CWE на действия:
| CWE | Тип слабости | Эксплуатационный примитив | Что пробовать |
|---|---|---|---|
| CWE-78 | OS Command Injection | Выполнение произвольных команд ОС | Инъекция через метасимволы (;, \, `) |
| CWE-125 | Out-of-bounds Read | Утечка памяти | Чтение за границами буфера, информационная утечка |
| CWE-502 | Deserialization of Untrusted Data | RCE через десериализацию | Подготовка вредоносного сериализованного объекта |
| CWE-917 | Expression Language Injection | Выполнение кода через шаблонизатор | Инъекция в EL/OGNL/JNDI выражения |
| CWE-20 | Improper Input Validation | Зависит от контекста | Фаззинг входных данных |
| CWE-400 | Uncontrolled Resource Consumption | DoS, иногда - race condition | Перегрузка ресурсов для обхода ограничений |
| CWE-200 | Exposure of Sensitive Information to an Unauthorized Actor | Утечка чувствительных данных | Побочные каналы, ошибки в обработке |
| CWE-190 / CWE-191 | Integer Overflow (CWE-190) / Integer Underflow (CWE-191) | Повреждение памяти | Граничные значения, overflow/underflow |
В старых CVE (2014–2015) может встречаться устаревшая категория CWE-189 (Numeric Errors), которая объединяла эти типы.
Когда у CVE несколько CWE - это золото. Каждый описывает отдельный аспект уязвимости и даёт отдельный вектор для исследования.
Root cause analysis уязвимости без доступа к коду
Root cause analysis - тот этап анализа CVE уязвимостей, который определяет, какой именно дефект в коде привёл к уязвимости. Без исходного кода опираемся на три источника: описание CVE, набор CWE и vendor advisory.CVE-2021-44228: четыре CWE - четыре направления удара
🔓 Эксклюзивный контент для зарегистрированных пользователей.
Log4Shell получил четыре CWE: CWE-20 (Improper Input Validation), CWE-400 (Uncontrolled Resource Consumption), CWE-502 (Deserialization of Untrusted Data), CWE-917 (Expression Language Injection).
Описание NVD: "JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints." Affected versions: Apache Log4j2 2.0-beta9 through 2.15.0.
Root cause analysis по CWE:
- CWE-917 - пользовательский ввод интерпретируется как выражение. Expression Language Injection в чистом виде.
- CWE-20 - входные данные (например, HTTP-заголовок User-Agent) попадают в log message без валидации и санитизации.
- CWE-502 - JNDI-lookup загружает Java-класс с удалённого LDAP-сервера и десериализует его. Deserialization of untrusted data - механизм доставки payload.
- CWE-400 - рекурсивные lookup-ы могут привести к неконтролируемому потреблению ресурсов.
CVE-2014-0160: buffer over-read как информационная утечка
Heartbleed - классика, где CWE сразу указывает на эксплуатационный примитив. CWE-125 (Out-of-bounds Read), векторCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N.Обратите внимание на Impact-метрики:
C:H/I:N/A:N - высокое влияние на конфиденциальность, нулевое на целостность и доступность. Это не RCE, это утечка. CWE-125 подтверждает: чтение за границами буфера. Описание NVD уточняет: "allows remote attackers to obtain sensitive information from process memory via crafted packets that trigger a buffer over-read, as demonstrated by reading private keys."Для пентестера: ищем не выполнение кода, а утечку секретов - приватные ключи, сессионные токены, пароли в памяти. На Exploit-DB - 4 эксплойта, все 4 verified. Vendor: OpenSSL, affected versions: 1.0.1 before 1.0.1g.
CVE-2014-6271: парсинг как корневая причина
Shellshock (CVE-2014-6271) получил CWE-78 (OS Command Injection) и CVSS 9.8 CRITICAL с векторомAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H.Описание: "GNU Bash through 4.3 processes trailing strings after function definitions in the values of environment variables." CWE-78 однозначно: инъекция команд ОС. Root cause - парсер Bash продолжает выполнять код после закрывающей фигурной скобки в определении функции, переданной через переменную окружения.
Связка description + CWE: описание объясняет где (environment variables, function definitions), а CWE-78 - что (command injection). На Exploit-DB - 21 эксплойт, 13 verified, платформа CGI. В CISA KEV с 2022-01-28. Полный root cause - без единого взгляда на исходники Bash.
Построение гипотез эксплуатации без исходного кода
Итак, вы прочитали advisory, определили CWE, разобрали CVSS-вектор, поняли root cause. Дальше - превратить это понимание в тестируемую гипотезу. Это и есть эксплуатация уязвимостей без исходного кода на практике.Patch diffing: бинарный анализ вместо исходников
Когда исходники недоступны (проприетарное ПО, firmware, коммерческие продукты), patch diffing - основной метод верификации гипотезы. Суть: сравниваем уязвимый и пропатченный бинарник, чтобы найти изменённые функции.Требования к окружению: Ghidra 11.x или IDA Pro, плагин BinDiff (для IDA) или встроенный Version Tracking (для Ghidra), два образа firmware или два билда приложения (до и после патча), достаточно места на диске для экспорта BinExport.
Процесс:
- Получите два бинарника - уязвимую и патченную версию. Для firmware - скачать с vendor portal. Для Windows-компонентов - извлечь из обновлений через
expand -f:* update.msu. - Загрузите оба в дизассемблер. В Ghidra - два проекта, автоанализ, затем Version Tracking через
Tools → Version Tracking. - Найдите изменённые функции. BinDiff/Version Tracking покажет функции с высоким similarity score (0.9+), но отличающимися инструкциями. Это и есть патч.
- Проанализируйте diff. Добавленные проверки (boundary check, null check, sanitization) указывают на root cause. Если в патче добавлена проверка длины перед
memcpy- вы смотрите на buffer overflow.
AV:L/UI:R - нужно действие пользователя. CISA KEV подтверждает эксплуатацию в дикой природе, включая ransomware. Гипотеза: можно передать вредоносный URL через OLE-объект в документе Word, который вызовет msdt.exe с произвольными аргументами. Official mitigation от Microsoft - отключение (unregister) ms-msdt URI protocol handler (KB5014697, июнь 2022). Patch diff имеет смысл делать на msdt.exe и обработчике URI-протоколов после июньских обновлений.От advisory до тестируемой гипотезы: пошаговый процесс
Собрал это в workflow, который использую на каждом engagement:Шаг 1. Сбор информации. Открываю CVE на NVD, фиксирую CWE, CVSS-вектор, affected versions, references. Проверяю наличие в CISA KEV. Командой
searchsploit --cve <номер> проверяю PoC на Exploit-DB. Если в references есть ссылка на GitHub - смотрю коммит, это может быть патч.Шаг 2. Формирование гипотезы. На основе CWE и описания формулирую конкретно: «Уязвимость типа X в компоненте Y позволяет Z при условии W.» Не «RCE в Apache», а «Десериализация сомнительных данных через JNDI lookup в Log4j при записи пользовательского ввода в лог.»
Шаг 3. Поиск подтверждений. Ищу PoC на Exploit-DB, GitHub (репозитории poc-in-github), vendor advisory. Для Exploit-DB смотрю дату публикации, платформу, статус verified. Если PoC не verified - это непроверенная гипотеза, а не рабочий эксплойт.
Шаг 4. Валидация в лабораторной среде. Разворачиваю уязвимую версию (Docker-образы из vulhub, ручная установка из архива). Проверяю гипотезу. Фиксирую, что работает, что нет, какие условия нужны.
Шаг 5. Адаптация к целевому окружению. На реальном engagement условия отличаются от лаборатории: WAF, сегментация, нестандартные конфигурации. Адаптирую payload, проверяю обходы.
Этот процесс маппится на MITRE ATT&CK: шаги 1-3 - Vulnerability Scanning (T1595.002, Reconnaissance) и сбор Vulnerabilities (T1588.006) / Exploits (T1588.005, Resource Development). Шаги 4-5 - непосредственная эксплуатация: Exploit Public-Facing Application (T1190), Exploitation for Client Execution (T1203), Exploitation for Privilege Escalation (T1068) или Exploitation of Remote Services (T1210) - зависит от конкретной CVE.
NVD база уязвимостей: анализ в эпоху деградации
NVD остаётся центральным ресурсом, но полагаться на него как на единственный источник - ошибка. NIST приоритизирует обогащение CVE из каталога CISA KEV, федерального софта и критического ПО. CVE вне этих категорий попадают в NVD, но могут долго висеть без CVSS-скора, CPE-конфигурации и ссылок.Что это значит для практики анализа CVE уязвимостей:
- Не ждите обогащения. Если CVE свежая и без CVSS - вычитайте вектор из описания сами. CWE-78 в сервисе с
AV:N- это критично вне зависимости от того, поставил ли NIST скор. - Используйте альтернативные источники. CISA Vulnrichment, VulnCheck KEV, vendor advisory, OSV (для open-source). Для пентестера особенно важен CISA KEV - если CVE в каталоге Known Exploited Vulnerabilities, это подтверждение эксплуатации в дикой природе.
- NVD API для автоматизации. Фильтрация по
hasKevпараметру позволяет получить только CVE из CISA KEV - ваш shortlist для проверки на engagement.
Практический разбор: Stagefright как пример кластера связанных CVE
Иногда одна уязвимость - на самом деле кластер. И тут начинается самое интересное.Все они связаны с библиотекой libstagefright, все remote, платформа Android. Но CWE различаются:
| CVE | CWE | Примитив |
|---|---|---|
| CVE-2015-1538 | CWE-189 (Numeric Errors) | Integer overflow в SampleTable |
| CVE-2015-1539 | CWE-189 | Integer underflow в ESDS parser |
| CVE-2015-3824 | CWE-119 (Buffer Errors) | Integer overflow и memory corruption в MPEG4 tx3g |
| CVE-2015-3826 | CWE-119, CWE-189 | DoS: integer underflow + buffer over-read + crash mediaserver (не RCE) |
| CVE-2015-3828 | CWE-119, CWE-189 | RCE: integer underflow + memory corruption в parse3GPPMetaData |
| CVE-2015-3829 | CWE-189 | Off-by-one в MPEG4 covr atoms (SIZE_MAX) |
| CVE-2015-3864 | CWE-189 | Integer underflow - неполный фикс CVE-2015-3824 |
Для исследователя здесь важен паттерн: один и тот же парсер (MPEG4Extractor) напичкан numeric errors. Если вы нашли один integer overflow в парсере мультимедийных форматов - проверяйте соседние места. CVE-2015-3864 прямо говорит: "this vulnerability exists because of an incomplete fix for CVE-2015-3824." Неполные патчи - один из самых продуктивных источников для vulnerability research. Лично у меня правило: нашёл CVE с пометкой «incomplete fix» - копаю рядом, там почти всегда есть ещё.
На Exploit-DB: CVE-2015-1538 - 1 verified эксплойт (remote, Android), CVE-2015-3864 - 3 эксплойта, 2 verified. Для построения гипотез эксплуатации достаточно знать: все эти CVE эксплуатируются через отправку crafted MP4-файла. Парсер обрабатывает атом, происходит integer overflow, далее - memory corruption и RCE.
Чеклист: быстрая оценка CVE на engagement
Для ежедневной работы я использую компактный чеклист. Глубокий анализ он не заменит, но за три минуты позволяет определить, стоит ли тратить время на конкретную CVE:
Код:
1. CWE → определить класс уязвимости
└─ CWE-78/502/917/94 = высокий приоритет (RCE-потенциал)
└─ CWE-125/200 = информационная утечка
└─ CWE-119/189 = memory corruption (нужен бинарный анализ)
2. CVSS Vector → оценить достижимость
└─ AV:N + PR:N + UI:N = эксплуатация без предусловий
└─ AV:N + PR:N + UI:R = нужен фишинг / social engineering
└─ AV:L + PR:H = нужен уже имеющийся доступ
3. CISA KEV → подтверждение эксплуатации in-the-wild
4. Exploit-DB (searchsploit --cve XXXX) → наличие PoC
5. References → есть ли ссылка на патч-коммит
При анализе CVE без исходного кода patch diffing через BinDiff или Ghidra Version Tracking - один из ключевых методов верификации гипотезы. На деле раздобыть оба билда проприетарного продукта (до и после патча) нередко сложнее, чем выполнить реверс. Для Windows-компонентов это решается через
expand -f:* update.msu. А как вы решаете эту задачу для firmware embedded-устройств - например, для Siemens SCALANCE или аналогичных контроллеров, где vendor не публикует diff между прошивками? Какой toolchain используете для извлечения и сравнения файловых систем из firmware images - binwalk + unsquashfs, jefferson, или что-то другое?Вопрос к читателям
Коллеги, кто работал с patch diffing для CVE без публичных исходников - какой тулчейн используете для бинарного сравнения уязвимой и пропатченной версии? Хотел бы узнать: при анализе Log4Shell (CVE-2021-44228, CWE-917 + CWE-502) в jar-артефактах - вы декомпилируете через Fernflower/CFR и диффите Java-псевдокод, или работаете на уровне байткода черезjavap -c с последующим diff? Если брали firmware или проприетарные бинари с CWE-78 (command injection) - какой IDA/Ghidra-скрипт или BinDiff-версию применяли для локализации изменённой функции парсинга? Поделитесь конкретным пайплайном: что на входе, какие флаги, как фильтруете шум от обфускации или релокаций, чтобы выйти на изменённый sink.
Последнее редактирование модератором: