Статья LLM для поиска уязвимостей в коде: практический workflow от SAST до PoC

Сергей Попов

Администратор
30.12.2015
5 715
6 744
Специализация
  1. OSINT
  2. Веб-безопасность
Статус верификации
  1. ✓ Verified
Лупа на тёмном антистатическом коврике над распечатанным фрагментом кода на Си. Сквозь линзу код искажается, проявляя призрачную подсветку несуществующей уязвимости.


За $28.50 в API-кредитах LLM-агент Excalibur скомпрометировал четыре из пяти хостов в Active Directory-лаборатории - бенчмарк команды Hadrian, февраль 2026. RapidPen получает shell за 200–400 секунд при стоимости $0.30–$0.60 за цель. Звучит как будущее, которое уже наступило. Но когда тот же класс моделей получает задачу разобрать функцию парсинга на C из реального open-source проекта - начинается цирк: уверенные вердикты о use-after-free в коде, который вообще не работает с динамической памятью. Между рекламными бенчмарками и AI vulnerability research в поле лежит слой из галлюцинаций, потери контекста и ложных срабатываний. Эта статья - о том, как выстроить workflow с LLM для поиска уязвимостей в коде так, чтобы модель реально ускоряла аудит, а не генерировала шум.

Место в цепочке аудита: где LLM работает и что должно быть до​

LLM для поиска уязвимостей в коде не заменяет ни SAST-сканер, ни ручной разбор. Это прослойка между ними - на этапе, где статический анализ уже отработал, а ручной разбор call chain'ов ещё не начинался. Подробнее - в нашем статье о безопасность llm атаки.

В терминах MITRE ATT&CK использование LLM для анализа open-source кода маппится на несколько техник этапа Resource Development и Reconnaissance:
  • T1593.003 Code Repositories (Reconnaissance) - сбор и анализ публичных репозиториев на предмет уязвимого кода
  • T1588.006 Vulnerabilities (Resource Development) - получение данных об уязвимостях для дальнейшей эксплуатации
  • T1682 Query Public AI Services (Reconnaissance) - использование публичных AI-сервисов как инструмента исследования
  • T1587.004 Exploits (Resource Development) - разработка эксплойтов на основе найденного
На практике последовательность такая: клонируете репозиторий, прогоняете Semgrep или CodeQL для первичной фильтрации, затем скармливаете LLM конкретные файлы с подозрительными паттернами и просите модель проследить dataflow от source к sink. На выходе - список гипотез, каждую из которых нужно подтвердить руками.

Применимость поиска уязвимостей с помощью ИИ по сценариям

СценарийЭффективность LLMКомментарий
Внешний пентест, аудит веб-приложенияСредняяПомогает разобрать бизнес-логику API, но не видит runtime-контекст
Внутренний пентест, кастомные сервисыВысокаяДоступ к исходникам + LLM = быстрый разбор нетривиальных call chain'ов
Bug bounty, open-source targetsВысокаяПубличный код + история коммитов = максимум контекста для модели
Аудит бинарей без исходниковНизкаяМодели плохо работают с декомпилированным кодом, теряют семантику
Embedded/firmware (C, bare metal)СредняяПростые баги находит, но аппаратный контекст ей недоступен

Ключевое ограничение: LLM оперирует текстом в пределах контекстного окна. Даже 128K токенов - это порядка 300–400 страниц кода. Средний open-source проект - сильно больше, и модель физически не способна «увидеть» весь codebase за один вызов.

Требования к окружению​

Перед первым шагом - стек, без которого workflow не работает:

КомпонентМинимумРекомендуется
ОСUbuntu 22.04+ / macOS. Windows - через WSL2Linux-хост или VM
RAM8 ГБ (работа через API)32+ ГБ (локальные модели через Ollama)
VRAMНе требуется для API8 ГБ (quantized 7B) / 24 ГБ (70B)
API-ключиOpenAI API или Anthropic APIОба - для кросс-валидации
ИнструментыSemgrep CLI v1.60+, Git, Python 3.10++ CodeQL CLI, tree-sitter
Бюджет на API$5 на мини-проект (5–10 файлов)$10–50 на проект (20–50 файлов)
СетьOnline для API-моделейOffline возможен с Ollama/llama.cpp

Для NDA-проектов - только локальные модели. Код, отправленный в облачный API OpenAI или Anthropic, покидает ваш контур. Точка. Ollama + CodeLlama или DeepSeek Coder - минимальный локальный стек.

AI vulnerability research: пошаговый workflow​

Шаг 1 - Сужение scope и подготовка контекста​

Скармливать модели весь репозиторий - бессмысленно. Она подавится и выдаст generic-ответ из учебника. Workflow начинается с фильтрации.
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

По данным фреймворка SecLLMHolmes (обзор Макрушина), все протестированные модели показывают недетерминированные ответы - при повторном запуске на идентичном коде результаты различаются. Один прогон ничего не доказывает. Три запуска с вариациями формулировки - минимум. Уязвимость, которую модель находит в 3/3 запусках, становится кандидатом на ручную проверку. Результат 1/3 - с высокой вероятностью шум.

Шаг 3 - Верификация и отсев false positives​

Здесь начинается реальная работа, и именно здесь LLM перестаёт быть «автономным сканером» и становится ассистентом.

Чеклист верификации каждой находки:
  1. Проверить dataflow вручную. Модель заявила, что пользовательский ввод доходит до memcpy без проверки длины? Проследите call chain. В половине случаев между source и sink стоит валидация, которую модель «не заметила» из-за ограниченного контекста.
  2. Сверить CWE-классификацию. Модели систематически путают CWE-идентификаторы. Buffer overflow (CWE-120) и out-of-bounds read (CWE-125) - разные вещи с разными последствиями и разной эксплуатабельностью. Всегда сверяйте с MITRE CWE.
  3. Написать PoC или unit-test. Если уязвимость выглядит реальной - подтвердите воспроизводимым тестом. LLM может помочь сгенерировать тестовый ввод, триггерящий найденный путь, но сам PoC - проверяйте руками.
  4. Проверить историю коммитов. git log -p -- [файл] покажет, менялась ли функция недавно и не был ли баг уже исправлен.
  5. Кросс-проверка второй моделью. Находку GPT-4 прогоните через Claude (или наоборот). Если обе модели независимо указывают на один и тот же dataflow - вероятность реального бага растёт.
Исследователи Google Project Zero (по данным из обзора Макрушина) улучшили результаты LLM в задачах поиска уязвимостей в 20 раз. Ключевые принципы: пространство для рассуждений (модель должна «думать вслух»), интерактивная среда, доступ к инструментам (отладчик, интерпретатор), автоматическая проверка результата и стратегия отбора из нескольких гипотез. Все пять принципов работают и в ручном workflow - chain-of-thought промпт вместо «дай ответ одним словом», итеративные уточнения вместо одного прогона, обязательная проверка каждой гипотезы.

Интеграция LLM со статическим анализом кода: Semgrep + AI​

Semgrep находит паттерны по правилам. LLM понимает семантику. Вместе они закрывают слепые зоны друг друга - и это ядро того, что можно назвать AI SAST-инструментами практического уровня.

Workflow комбинации: Semgrep находит все вызовы strcpy, sprintf, memcpy без проверки bounds - синтаксический паттерн. LLM получает каждый найденный вызов с контекстом и оценивает: source действительно контролируется атакующим? Из 50 находок Semgrep после такой фильтрации остаётся 5–10 кандидатов на ручную проверку. Экономия времени - на порядок.

Кастомное правило Semgrep для поиска потенциальных buffer overflow, результаты которого передаются на проверку LLM:
YAML:
rules:
  - id: unsafe-memcpy-candidate
    patterns:
      - pattern: memcpy($DST, $SRC, $LEN)
      - pattern-not-inside: |
          if ($LEN <= sizeof($DST)) { ... }
    message: "memcpy без bounds check - кандидат на LLM-анализ"
    languages: [c]
    severity: WARNING
По данным исследования Augment Code, синтаксическое детектирование не способно отследить dataflow через границы функций - для этого нужен семантический анализ. LLM, в свою очередь, ненадёжен в точном синтаксическом матчинге. Комбинация закрывает оба пробела: Semgrep берёт на себя точность паттернов, LLM - межфайловый контекст и оценку эксплуатабельности.

Аналогичный подход работает с CodeQL: пишете запрос, ищущий taint-flow от source до sink, а LLM помогает интерпретировать результаты и оценить, реально ли source контролируется атакующим в конкретном сценарии развёртывания.

Автоматизированный аудит кода: что LLM находит и что пропускает​

КритерийLLM (GPT-4 / Claude)SemgrepCodeQLРучной аудит
Сильные стороныСемантический анализ, cross-file рассуждения, объяснение на естественном языкеБыстрый, детерминированный, кастомные правилаГлубокий dataflow, taint-анализ уровня проектаБизнес-логика, архитектурные дефекты
ОграниченияГаллюцинации, недетерминизм, ограниченное контекстное окноТолько синтаксис, не видит dataflow через файлыСложная настройка, требует сборки проектаМедленно, дорого, субъективно
Когда использоватьРазбор сложных call chain'ов, оценка эксплуатабельности, генерация PoC-гипотезПервичная фильтрация, CI/CD, known-bad паттерныTaint-анализ на уровне всего проектаАрхитектурный review, logic bugs
Когда не использоватьКак единственный инструмент; для бинарей; для NDA-кода через облачный APIДля семантических багов и бизнес-логикиДля проектов без билд-системыДля сканирования тысяч файлов
Стоимость (20–50 файлов)$5–30 APIБесплатно (OSS)Бесплатно (OSS)$5,000–50,000
False positive rate30–70% без верификации20–40%10–20%5–10%

Цифры по false positive rate - ориентировочные, на основе практики работы с несколькими десятками open-source проектов на C/Go/Python. Конкретные значения зависят от языка, качества промптов и размера контекстного окна.

Где LLM хорош:
  • Memory corruption (C/C++): buffer overflow, use-after-free, double free. Модели уверенно распознают небезопасные паттерны работы с памятью при достаточном контексте.
  • Injection-векторы: SQL injection, command injection, path traversal. Если source и sink в пределах переданного контекста - модель отслеживает dataflow.
  • Криптографические ошибки: устаревшие алгоритмы, слабые ключи, отсутствие IV.
  • Hardcoded secrets. Тривиальная задача, но Semgrep справляется не хуже.
Где LLM code security analysis буксует:
  • Logic bugs и ошибки авторизации. Модель не знает бизнес-требований. «Пользователь A не должен видеть данные пользователя B» - этот контекст за пределами кода.
  • Race conditions и TOCTOU. Требуют понимания runtime-поведения, а модель видит только текст.
  • Архитектурные дефекты. Неправильное разделение привилегий, небезопасная композиция сервисов - уровень выше отдельных функций.
  • Уязвимости в зависимостях. LLM не знает актуальную базу CVE в реальном времени. Для этого есть SCA-инструменты (Snyk, Trivy, Grype).

GPT vulnerability scanner: пять антипаттернов​

  1. «Весь репозиторий в один промпт». Даже 128K токенов - это около 300 страниц кода. Модель теряет фокус, отвечает шаблонно и пропускает реальные проблемы. Решение: декомпозиция по файлам с контекстом зависимостей.
  2. Один прогон как финальный вердикт. SecLLMHolmes показал: результаты недетерминированны. Один прогон - лотерея. Три прогона с вариациями промпта - уже статистика.
  3. Игнорирование forward security. Термин из исследования arxiv: код, который выглядит безопасным для сегодняшней модели, может оказаться уязвимым для модели через год. Более мощная модель с более глубоким анализом найдёт то, что текущая пропустила. LLM-аудит - снимок, а не сертификат.
  4. Облачный API для NDA-проектов. Код уходит на серверы провайдера. Решение: Ollama + CodeLlama/DeepSeek Coder, self-hosted с гарантиями приватности.
  5. Доверие CWE-классификации без проверки. Модели путают близкие CWE-идентификаторы и завышают severity. Каждый CWE сверяйте с MITRE напрямую. Я видел, как GPT-4 присваивал CWE-89 (SQL injection) коду, который работал с файловой системой и к базе данных не обращался вовсе.
По данным исследования arxiv (Tier-1 research), фундаментальная проблема подхода «fighting fire with fire» - использования вероятностных AI-чекеров для проверки вероятностно генерируемого кода - в том, что он не покрывает «длинный хвост» редких, но критичных багов. Отсутствие найденной уязвимости не доказывает её отсутствия. «Not found» означает «not reached» - модель не добралась до нужного участка в пространстве состояний. Атакующий с более мощной моделью, большим вычислительным ресурсом или инсайтом о кодовой базе будет иметь преимущество.

Машинное обучение и поиск уязвимостей: ограничения, о которых не пишут в README​

Каталог Hadrian фиксирует более 70 open-source инструментов для AI offensive security к марту 2026 года. До выхода GPT-4 в 2023 их было менее пяти. Рост - взрывной, но большинство инструментов заточены под автоматизированный пентест (сканирование + эксплуатация известных CVE), а не под аудит исходного кода.

Для автоматизации bug bounty и code audit набор инструментов значительно уже. И ограничения - заметнее:
  • Контекстное окно - жёсткий потолок. Ни одна модель не видит весь проект целиком. Уязвимости, требующие понимания взаимодействия между десятками файлов, остаются невидимыми без правильной декомпозиции.
  • Недетерминизм - системная проблема. Не баг конкретной модели, а свойство архитектуры. Любой LLM-based scanner будет давать разные результаты на одном и том же коде. Запустите трижды - получите три разных списка.
  • Отсутствие runtime-контекста. Модель работает со статическим текстом. Она не знает, какой ввод реально приходит на production-сервер, какие переменные окружения установлены, какие branches активны.
  • Устаревание данных обучения. Модель не знает о CVE, опубликованных после cutoff-даты обучения. Новые паттерны атак, свежие advisory - всё это за пределами её знаний без RAG или tool-calling.
По данным CVE-Bench (Hadrian), AI-агенты эксплуатируют лишь 13% критических CVE в production-средах - при том что в контролируемых условиях с полным описанием уязвимости тот же GPT-4 показывает 87%. Разрыв в семь раз между лабораторией и реальностью. Его не закрыть увеличением контекстного окна.

Последние полтора года я встраиваю LLM в цикл аудита кода - результат неоднозначный, но конкретный. Разбор длинных call chain'ов, который раньше занимал три часа, с Claude сжимается до тридцати минут. Генерация гипотез о source-sink парах - то, что требовало методичного grep через cscope - формулируется в одном промпте. Но модель - не vulnerability scanner. Это ассистент, который «читает» код быстрее вас и предлагает гипотезы. Верификация - на вас.

Проблема индустрии в том, что маркетинг обгоняет инженерную честность. Бенчмарки показывают 87% - но в лабораторных условиях с полным описанием уязвимости. В поле - 13%. Разрыв в семь раз, и его закрывают слайдами, а не методологией.

Мой прогноз: LLM не станет автономным аудитором в ближайший год. Зато станет стандартным слоем пайплайна - между Semgrep и ручным review. Те, кто сейчас выстроит workflow с правильной промпт-инженерией, верификацией и интеграцией с SAST, получат преимущество в скорости без потери качества. Остальные будут тонуть в false positives и через полгода спишут LLM как «хайп, который не работает». На HackerLab есть задачи в категориях web и pwn, где можно отработать полный цикл - от анализа исходников до рабочего эксплойта - в контролируемой среде без последствий.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab