Методичка: Поиск уязвимостей в коде с использованием преимуществ LLM (Code-First Analysis)
Дисклеймер
Материал предназначен для специалистов по информационной безопасности, системных администраторов и разработчиков. Рассматриваются исключительно технологии и методики — принципы работы, архитектура, способы обнаружения и нейтрализации угроз. Статья носит образовательный характер, не содержит инструкций по созданию или распространению вредоносного ПО и не призывает к нарушению законодательства РФ. Ответственность за применение описанных методов лежит на читателе в рамках действующего законодательства.
📑 Быстрый индекс для поиска
- Фаза 1: Глобальный семантический маппинг архитектуры
- Фаза 2: N-мерный Taint-анализ
- Фаза 3: Анализ бизнес-логики и инвариантов
- Фаза 4: Генерация гипотез и моделирование атак
- Фаза 5: Поиск редких и комплексных векторов
- Фаза 6: Анализ API-специфичных уязвимостей
- Фаза 7: Анализ криптографии и генерации токенов
- Фаза 8: Анализ конфигурации и зависимостей
- Фаза 9: Логическое подтверждение без инструментов
- Фаза 10: Формирование отчета и ремедиации
- 📋 Чек-лист по OWASP Top 10
- 📝 Шаблон отчета об уязвимости
Принцип работы LLM при анализе кода
LLM не должна имитировать человека, читающего код построчно. Преимущество LLM заключается в одновременном удержании в контексте десятков файлов, семантическом понимании намерений разработчика и параллельном переборе логических состояний. Эта методичка предписывает алгоритм действий, максимизирующий эти способности.
Ключевые принципы:
- Параллельный анализ множества файлов и модулей
- Семантическое понимание бизнес-логики, а не только синтаксиса
- Генерация гипотез атак на основе контекста
- Построение графов потока данных через всю кодовую базу
- Логическое подтверждение уязвимостей без запуска эксплойтов
Фаза 1: Глобальный семантический маппинг архитектуры
Цель: Построить ментальную модель приложения до поиска конкретных багов.
1.1 Идентификация границ доверия
Определи все точки входа:
- API endpoints (REST, GraphQL, gRPC)
- CLI аргументы
- Webhook handlers
- Message queue consumers
- WebSocket connections
Определи, где данные пересекают границу:
- Из внешнего мира во внутреннюю сеть
- От пользователя к базе данных
- От frontend к backend
- Между микросервисами
1.2 Картирование состояний и ролей
Выяви все возможные статусы пользователя:
- guest, user, admin, banned, pending, suspended
- Механизмы перехода между статусами
- Условия активации/deactivation
1.3 Анализ жизненного цикла ключевых объектов
Для каждого ключевого объекта (User, Order, Payment, Session) определи:
- Как создается, модифицируется и уничтожается
- Где происходят глубокие копии, сериализация/десериализация, кэширование
- Какие данные живут дольше, чем должны (токены в памяти, временные файлы)
1.4 Анализ middleware и guards
Определи порядок применения middleware:
- Аутентификация
- Авторизация
- Rate limiting
- CORS
- CSRF protection
- Input validation
Порядок часто критичен. Если валидация применяется после авторизации, но до проверки прав доступа, это может привести к bypass.
1.5 Анализ конфигурации безопасности
Проверь реализацию:
- CSRF токены (генерация, валидация, срок жизни)
- CORS политики (allowed origins, credentials)
- Rate limiting (по IP, по пользователю, по endpoint)
- IP allow-list (где применяется, можно ли обойти через заголовки)
- HTTP security headers (CSP, HSTS, X-Frame-Options)
1.6 Анализ зависимостей и окружения
Определи фреймворки, ORM, шаблоны рендеринга и версии из:
- package.json, requirements.txt, pom.xml, Gemfile
- Dockerfile, docker-compose.yml
- Configuration files
Сформируй сводку: «Приложение использует Django ORM, но в модуле X используется сырой SQL, а аутентификация опирается на JWT без проверки exp«.
Фаза 2: N-мерный Taint-анализ (Источник → Синк)
Цель: Отследить поток данных, используя семантическое понимание, а не регэкспы.
Taint-анализ — это метод отслеживания потока данных от источника (source) до места исполнения (sink) с проверкой промежуточных трансформаций.
2.1 Идентификация Источников (Sources)
Найди все места, где данные контролируются пользователем:
- request.GET, request.POST, request.body, request.json()
- HTTP заголовки: User-Agent, Referer, X-Forwarded-*, Authorization, Cookie
- URL параметры, path segments
- Данные из БД, которые ранее были записаны пользователем
- Данные из предыдущих ответов API
- Environment variables (если могут быть контролированы)
2.2 Отслеживание трансформаций
Проследи путь переменной. Если встречается функция очистки (например, escape(), cast(int), sanitize()), оцени её семантическую достаточность.
Пример LLM-мышления: “Переменная приводится к int, что защищает от SQLi, но далее используется как индекс массива. Это не защищает от Out-of-Bounds, если проверка диапазона отсутствует”.
Проверь:
- Достаточно ли валидации для конкретного sink?
- Можно ли обойти валидацию через encoding (URL encoding, Unicode, null bytes)?
- Применяется ли валидация ко всем путям данных?
2.3 Идентификация Синков (Sinks)
Найди места исполнения:
- SQL: db.query(), cursor.execute(), ORM raw queries
- OS commands: eval(), exec(), os.system(), subprocess.call()
- File operations: open(), read(), write(), os.path.join()
- Rendering: render_template(), innerHTML, document.write()
- Deserialization: pickle.loads(), yaml.load(), JSON.parse()
- Network: requests.get(), urllib.urlopen(), socket.connect()
2.4 Прямой и обратный Taint
Прямой taint: Source → Transformation → Sink
Построй текстовый граф потока данных: Source (Line 12, file A) -> Transformation (Line 45, file B, недостаточная) -> Sink (Line 89, file C).
Обратный taint: Данные из доверенной зоны попадают в место, где формируется ответ пользователю.
- Stored XSS: данные из БД отображаются без экранирования
- Information Disclosure: чувствительные данные попадают в логи или ответы API
- Second-order attacks: данные сохраняются и позже используются в опасном контексте
2.5 Taint через хранилища
Отслеживай taint через разные типы хранилищ:
- Redis → DB → кэш → шаблон
- Очередь сообщений → обработчик
- Сессия → cookie → следующий запрос
- Файловая система → загрузка → обработка
Фаза 3: Анализ бизнес-логики и инвариантов
Цель: Выявить уязвимости, связанные с нарушением бизнес-правил.
3.1 Выявление неявных инвариантов
Определи бизнес-правила, которые должны выполняться:
- “Сумма по счетам должна равняться нулю”
- “Баланс не может стать отрицательным”
- “Один пользователь — один активный сеанс”
- “Промокод можно использовать только один раз”
- “Цена не может быть отрицательной”
LLM ищет места, где эти правила проверяются неполно или только на фронтенде/в одном из шагов.
3.2 Многошаговые процессы и атомарность
Проанализируй процессы:
- Регистрация, восстановление доступа, смена email/телефона
- Подтверждение операций (payment, delete, transfer)
- Workflow с несколькими шагами
Вопрос для проверки: можно ли прервать процесс посередине и продолжить с изменёнными параметрами? Можно ли вызвать шаг 3, не выполнив шаг 2?
3.3 Экономические и ресурсные атаки
Проверь:
- Ценообразование: возможность отрицательных цен, изменение количества на отрицательное
- Промокоды: множественное применение, обход лимитов
- Бонусы: начисление без списания, race condition при списании
- Rate limiting: обход через разные заголовки, распределенная атака
3.4 Race Condition и TOCTOU
Race Condition — ситуация, когда результат выполнения зависит от порядка или времени выполнения потоков.
TOCTOU (Time-of-Check to Time-of-Use) — уязвимость, возникающая, когда между проверкой условия и использованием результата проверки состояние может измениться.
Ищи операции “проверка, затем использование”:
- Проверка баланса → списание
- Проверка существования файла → запись
- Проверка наличия промокода → применение
- Проверка лимита → инкремент счетчика
Вопрос: что произойдет, если этот endpoint будет вызван 100 раз параллельно до завершения первой транзакции?
Фаза 4: Генерация гипотез и моделирование атак
Цель: Использовать способность LLM к абстрактному мышлению для поиска логических уязвимостей.
Для каждой критической функции LLM должна сгенерировать блок [ГИПОТЕЗА]:
4.1 Гипотеза обхода бизнес-логики
Триггер: Многошаговые процессы, сложные условия, зависимости между параметрами.
LLM-вопросы:
- Можно ли вызвать шаг 3, не выполнив шаг 2, манипулируя параметрами или порядком запросов?
- Что если изменить порядок параметров в JSON?
- Что если передать дополнительные поля?
- Что если один из обязательных параметров будет пустым?
4.2 Гипотеза непрямого воздействия (Second-Order)
Триггер: Данные сохраняются в БД и позже читаются в другом контексте.
LLM-вопрос: Если я внедрю полезную нагрузку здесь (например, в имя пользователя), где еще это имя будет отображено или использовано (в SQL-запросе для генерации отчета, в email-уведомлении, в админ-панели)?
4.3 Гипотеза альтернативных путей
LLM-вопросы:
- Что если данные придут не через основной путь, а через административный интерфейс / импорт / интеграцию?
- Что если пользователь имеет несколько ролей/аккаунтов одновременно?
- Что если запрос придёт с задержкой (async-обработка)?
- Что если один из сервисов (микросервис) откажет или ответит медленно?
4.4 Гипотеза нестандартных данных
LLM-вопросы:
- Что если данные содержат unicode, эмодзи, right-to-left символы, нулевые байты?
- Что если длина данных превышает ожидаемую (buffer overflow в интерпретаторах)?
- Что если данные содержат специальные символы для конкретного sink (SQL, HTML, shell)?
- Что если тип данных отличается от ожидаемого (массив вместо строки, объект вместо числа)?
4.5 Гипотеза обхода аутентификации/авторизации
LLM-вопросы:
- Можно ли обойти проверку, передав специальный заголовок (X-Forwarded-For, X-Original-URL)?
- Можно ли получить доступ к admin endpoint, изменив роль в JWT или сессии?
- Можно ли обойти CSRF проверку, используя другой Content-Type?
- Можно ли обойти rate limiting, ротируя IP через заголовки?
Фаза 5: Поиск редких и комплексных векторов
Цель: Искать то, что часто пропускают автоматические сканеры и уставшие разработчики.
5.1 Prototype Pollution (JavaScript/Node.js)
Ищи рекурсивное слияние объектов (merge, cloneDeep, extend), где ключи не валидируются. Проверь возможность установки __proto__, constructor, prototype.
Пример уязвимого кода:
function merge(target, source) { for (let key in source) { if (source.hasOwnProperty(key)) { target[key] = source[key]; } } } merge(userInput, config); // userInput может содержать __proto__
5.2 Cache Poisoning (Отравление кэша)
Ищи использование заголовков X-Forwarded-Host, X-Original-URL, X-Host для генерации абсолютных URL или редиректов, которые могут быть закэшированы CDN или обратным прокси.
Проверь:
- Генерация ссылок в email с использованием заголовков
- Redirect на основе заголовков
- CORS headers на основе Origin
5.3 Mass Assignment / Auto-Binding
Ищи endpoints, которые принимают JSON-объект и напрямую передают его в ORM для обновления:
user.update(request.json) # Можно обновить is_admin, balance, role
Проверь, есть ли whitelist полей для обновления.
5.4 SSRF через нестандартные векторы
Ищи не только http://, но и:
- file://, gopher://, dict://, ftp://
- XXE через XML парсеры
- ImageTragick через обработку изображений
- DNS rebinding через внутренние домены
- Cloud metadata endpoints (169.254.169.254)
5.5 Уязвимости десериализации
Ищи не только явный RCE, но и возможность манипуляции объектами для обхода проверок:
- Изменение типа переменной с boolean на object для обхода строгой проверки ===
- Внедрение дополнительных полей в сериализованный объект
- Изменение порядка полей для обхода валидации
5.6 IDOR через косвенные ссылки
Даже если используется UUID, проверь:
- Раскрывается ли UUID в ответах API для других пользователей
- Можно ли предсказать UUID (sequential, timestamp-based)
- Есть ли проверка принадлежности объекта текущему пользователю
IDOR (Insecure Direct Object Reference) — уязвимость, возникающая, когда приложение не проверяет, имеет ли пользователь право доступа к запрашиваемому объекту.
5.7 Open Redirect
Ищи параметры, принимающие URL для редиректа:
- redirect, next, url, return_to, continue
- Проверь, можно ли использовать //evil.com, @evil.com, evil.com%00@good.com
- Проверь, применяется ли редирект после валидации
Фаза 6: Анализ API-специфичных уязвимостей
Цель: Выявить уязвимости, специфичные для различных типов API.
6.1 REST API
Проверь:
- Mass assignment через PATCH/PUT запросы
- IDOR через изменение ID в URL
- Broken access control через изменение HTTP метода (GET вместо POST)
- Information disclosure через verbose error messages
- Rate limiting bypass через разные endpoints
6.2 GraphQL
Проверь:
- Introspection query (можно ли получить схему API)
- Query depth limit (можно ли выполнить вложенный запрос на 100 уровней)
- Query complexity limit (можно ли выполнить запрос с 1000 полей)
- Batch query abuse (можно ли выполнить 100 запросов в одном)
- IDOR через изменение ID в query/mutation
- Information disclosure через error messages
Пример опасного запроса:
query { user(id: 1) { name email posts { comments { author { posts { # Бесконечная вложенность } } } } } }
6.3 gRPC
Проверь:
- Reflection enabled (можно ли получить список сервисов)
- Authentication/authorization на уровне сервисов
- Input validation для protobuf messages
- Rate limiting на уровне сервисов
6.4 WebSocket
Проверь:
- Authentication при установлении соединения
- Authorization для разных каналов/комнат
- Input validation для сообщений
- Rate limiting для сообщений
- Cross-site WebSocket hijacking
Фаза 7: Анализ криптографии и генерации токенов
Цель: Выявить слабости в криптографических реализациях.
7.1 Генерация токенов
Проверь генерацию:
- Reset-password токены
- Invite ссылки
- Session ID
- CSRF токены
- API ключи
Ищи проблемы:
- Использование random вместо secrets (Python) или Math.random() вместо crypto.randomBytes() (JavaScript)
- Использование uuid1 (на основе времени и MAC) вместо uuid4 (случайный)
- Слабый salt или отсутствие salt
- Переиспользование nonce
- Предсказуемые ID (sequential, timestamp-based)
7.2 Хранение паролей
Проверь:
- Алгоритм хеширования (bcrypt, scrypt, Argon2 — хорошо; MD5, SHA1 — плохо)
- Наличие salt
- Количество итераций (work factor)
- Использование pepper (секретный ключ на уровне приложения)
7.3 Шифрование данных
Проверь:
- Режим шифрования (GCM, CCM — хорошо; ECB, CBC без authentication — плохо)
- Наличие AEAD (Authenticated Encryption with Associated Data)
- Управление ключами (ротация, хранение)
- IV/nonce генерация (должна быть уникальной для каждого шифрования)
7.4 JWT токены
Проверь:
- Алгоритм подписи (RS256, ES256 — хорошо; none, HS256 с слабым секретом — плохо)
- Проверка exp (expiration time)
- Проверка iss (issuer) и aud (audience)
- Хранение секрета (не в коде, не в git)
- Возможность algorithm confusion атаки (подмена RS256 на HS256)
Фаза 8: Анализ конфигурации и зависимостей
Цель: Выявить проблемы в конфигурации и используемых компонентах.
8.1 Конфигурация безопасности
Проверь:
- Debug mode enabled в production
- Default credentials (admin/admin, root/root)
- Verbose error messages (stack traces, SQL errors)
- Directory listing enabled
- Unnecessary HTTP methods enabled (TRACE, PUT, DELETE)
- Missing security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options)
8.2 Зависимости и Supply Chain
Supply Chain — цепочка поставок компонентов, включая все зависимости и их зависимости.
Проверь:
- Известные уязвимости (CVE) в используемых версиях
- Использование устаревших версий
- Использование компонентов без поддержки (unmaintained)
- Использование компонентов из ненадежных источников
- Отсутствие lock файлов (package-lock.json, Pipfile.lock)
8.3 Конфигурация БД
Проверь:
- Использование default credentials
- Избыточные привилегии у application user
- Отсутствие encryption at rest
- Отсутствие аудита действий
- SQL mode (strict mode для MySQL)
8.4 Конфигурация облачных сервисов
Проверь:
- S3 buckets с публичным доступом
- IAM policies с избыточными привилегиями
- Отсутствие MFA для критичных операций
- Отсутствие logging и monitoring
- Использование default VPC/security groups
Фаза 9: Логическое подтверждение без использования инструментов
Цель: Доказать уязвимость, опираясь исключительно на логику кода, без запуска эксплойтов.
Если LLM находит потенциальную уязвимость, она должна сформировать блок [ЛОГИЧЕСКОЕ ПОДТВЕРЖДЕНИЕ], отвечающий на вопросы:
9.1 Достижимость
Могу ли я, как злоумышленник, контролировать входные данные на этом пути?
Пример: “Да, потому что параметр X берется из req.body без middleware аутентификации”.
9.2 Отсутствие защиты
Почему существующие проверки не работают?
Пример: “Да, есть проверка if (user.role == 'admin'), но она выполняется после выполнения опасной операции, или проверяется только наличие ключа в объекте, но не его значение”.
9.3 Конструируемость полезной нагрузки
Могу ли я составить строку/объект, который удовлетворит условиям sink?
Пример: “Для эксплуатации Path Traversal через параметр debug, мне достаточно передать ../../../etc/passwd. Код использует os.path.join(base_dir, user_input). Поскольку base_dir не заканчивается на /, а user_input начинается с /, os.path.join проигнорирует base_dir и вернет абсолютный путь из user_input. Это гарантированно сработает в Python”.
9.4 Влияние
Что именно произойдет?
- Чтение файла
- Выполнение кода
- Обход аутентификации
- Раскрытие чувствительных данных
- Изменение данных
- Отказ в обслуживании
9.5 Условия успешной эксплуатации
Определи:
- Какие предусловия должны быть выполнены (состояние аккаунта, время суток, количество предыдущих действий)
- Насколько атака воспроизводима (одноразовая, требует race condition, требует специфического тайминга)
- Степень влияния (полный компромисс, частичный, только для конкретных пользователей)
Фаза 10: Формирование отчета и ремедиации
Цель: Выдать результат в формате, готовом для разработчика или AppSec-инженера.
10.1 Структура вывода для каждой найденной уязвимости
🏷️ Тип уязвимости: (Например: Second-Order SQL Injection, TOCTOU Race Condition)
📍 Локация: Файл:строка (Источник) → Файл:строка (Синк)
🧠 Логика уязвимости: Краткое объяснение, почему это работает, с акцентом на ошибку в логике разработчика.
💡 Теоретический PoC (Payload): Пример запроса или состояния, которое эксплуатирует уязвимость.
🛡️ Рекомендация по исправлению: Конкретный фрагмент кода, как это исправить.
10.2 Трёхуровневая система рекомендаций
Быстрое исправление (минимально достаточное):
Пример: добавить startswith(base_dir) после join.
Правильное исправление (defense-in-depth):
Пример: использовать pathlib.Path с relative_to и строгой проверкой.
Стратегическое (архитектурное изменение, если баг системный):
Пример: полностью убрать пользовательский ввод из пути к файлам, использовать объектное хранилище.
📋 Чек-лист по OWASP Top 10
A1 Инъекции
- SQL injection (parameterized queries, ORM)
- NoSQL injection (validation, sanitization)
- OS command injection (avoid shell execution)
- LDAP injection (escaping special characters)
- XPath injection (parameterized queries)
A2 Недостатки аутентификации
- Password policy (complexity, length)
- Password storage (bcrypt, scrypt, Argon2)
- Session management (secure cookies, rotation)
- Multi-factor authentication
- Account lockout (brute force protection)
- Password reset flow (secure tokens, expiration)
A3 Разглашение конфиденциальных данных
- Encryption in transit (TLS 1.2+)
- Encryption at rest (database, files)
- Sensitive data in logs (masking)
- Sensitive data in responses (filtering)
- Sensitive data in URLs (avoid GET parameters)
A4 Внедрение внешних сущностей XML
- Disable DTD processing
- Disable external entities
- Use less complex data formats (JSON)
- Validate XML input
A5 Недостатки контроля доступа
- Access control checks on every request
- Deny by default
- IDOR prevention (ownership checks)
- Directory traversal prevention
- CORS configuration
A6 Некорректная настройка параметров безопасности
- Remove default credentials
- Disable debug mode
- Configure security headers
- Disable directory listing
- Remove unnecessary features
- Error handling (no stack traces)
A7 Межсайтовое выполнение сценариев
- Output encoding (context-aware)
- Content Security Policy
- Input validation
- HttpOnly and Secure flags for cookies
- Avoid dangerous functions (innerHTML, eval)
A8 Небезопасная десериализация
- Avoid deserialization of untrusted data
- Use safe serialization formats (JSON)
- Integrity checks (signatures)
- Type checking before deserialization
A9 Использование компонентов с известными уязвимостями
- Regular dependency updates
- Vulnerability scanning (SAST, SCA)
- Remove unused dependencies
- Use trusted sources
A10 Недостатки журналирования и мониторинга
- Log authentication events
- Log access control failures
- Log input validation failures
- Alert on suspicious activity
- Log retention policy
- Protect logs from tampering
📝 Шаблон отчета об уязвимости
Отчет об уязвимости: [Название уязвимости]
🏷️ Тип уязвимости
[Например: Second-Order SQL Injection, TOCTOU Race Condition]
📍 Локация
- Источник: Файл:строка
- Трансформация: Файл:строка
- Синк: Файл:строка
🧠 Логика уязвимости
[Краткое объяснение, почему это работает, с акцентом на ошибку в логике разработчика]
💡 Теоретический PoC
[Пример запроса или состояния, которое эксплуатирует уязвимость]
HTTP Request
POST /api/endpoint HTTP/1.1 Host: example.com Content-Type: application/json {"parameter": "payload"}
🛡️ Рекомендации по исправлению
Быстрое исправление
[Минимально достаточное исправление]
# Код до [code] # Код после [code]
Правильное исправление
[Defense-in-depth подход]
# Код до [code] # Код после [code]
Стратегическое исправление
[Архитектурное изменение, если баг системный]
[Описание]
📊 Оценка риска
- CVSS Score: [score]
- Exploitability: [low/medium/high]
- Impact: [low/medium/high/critical]
- Reproducibility: [easy/moderate/difficult]
📚 Ссылки
🧠 Internal Prompt Template для LLM
При получении фрагмента кода, LLM должна неявно или явно проговаривать следующий алгоритм:
- Анализ: Что эта функция пытается сделать? Каковы её входные и выходные данные?
- Поиск источников: Откуда приходят arg1, arg2? Контролируются ли они пользователем?
- Поиск синков: Куда эти данные в итоге попадают? (БД, файловая система, другой вызов API, рендеринг)
- Проверка барьеров: Есть ли между источником и синком валидация? Является ли она семантически надежной (а не просто формальной)?
- Генерация гипотез: Что если тип данных изменится? Что если массив будет пустым? Что если вызвать это дважды?
- Вердикт: Если цепочка Source → (неадекватная защита) → Sink существует, классифицировать как уязвимость и сформулировать логическое доказательство.
Примечание: Данная методичка разработана для максимизации аналитических способностей языковой модели, исключая зависимость от внешних сканеров и фокусируясь на глубоком семантическом понимании архитектуры и логики приложения.
#appsec #codeanalysis #llm #vulnerabilities #security #owasp #taintanalysis #bugbounty