hego.red - Практические заметки по red teaming ИИ/LLM

Практические заметки по red teaming ИИ/LLM

Начните здесь

Добро пожаловать. Это практические заметки по red teaming LLM, написанные с точки зрения пентестера. Используйте вкладки сверху для навигации: Основы объясняют, что вы на самом деле тестируете, Атаки и Методология, это как именно, Буткемп, это пошаговый курс, а в PortSwigger разобранные лаборатории, Область и Схема атаки помогают очертить цель, а Термины, это быстрый словарь. Впервые здесь? Просто читайте эту вкладку сверху вниз. Нажмите / в любой момент, чтобы искать по всему сайту.

Основы: что мы на самом деле тестируем?

Прочтите это первым. За минуту вы поймёте, что такое "функция с ИИ" на самом деле, слова модель / чат-бот / агент, и как ИИ формирует ответ. Как только вы увидите общую картину, остальные вкладки станут понятны.

1. Вы тестируете приложение, а не мозг

"Функция с ИИ", это обычное приложение с подключённой моделью ИИ. Вы тестируете приложение, которое построил клиент. Мозг модели обычно принадлежит вендору (Claude, OpenAI) и вне области работ.

Вы / окно чата
где вы вводите сообщение
ПриложениеВЫ ТЕСТИРУЕТЕ ЭТО
эту часть построил клиент:
  • добавляет скрытые правила (системный промпт)
  • может читать документы или базу данных (RAG)
  • может вызывать инструменты (почта, база данных, запуск кода)
  • показывает ответ пользователю
Модель / "мозг"обычно вендора
она просто превращает текст в ещё текст
Почти каждый баг живёт в зелёном блоке (приложение), а не в мозге. Заставить мозг сказать грубость, это проблема вендора, а не настоящая находка.

2. Модель против чат-бота против агента

Эти три слова всех путают. Это просто лестница: каждая ступень добавляет одну вещь.

Модель (LLM)
мозг. Читает текст, угадывает следующее слово. Вот и всё.
Чат-бот
модель + скрытые правила + окно чата. Он разговаривает с вами.
RAG-приложение
чат-бот + умеет читать документы и ваши данные.
Агент
модель + инструменты. Он может ДЕЛАТЬ и предпринимать шаги, а не только говорить.

Чем правее, тем больше он умеет, и тем больше вы можете атаковать.

3. Как формируется ответ

Модель не "думает". Она читает текст и угадывает следующее слово, снова и снова. Смотреть стоит не на угадывание, а на то, кто написал текст, из которого она угадывает. Перед ней оказывается пять видов текста, и только один написали те, кто делал приложение.

Системный промптПишет разработчик. Единственный текст здесь, которым владеет приложение, и приз для любого, кто заставит модель его повторить. ↳ утечка промпта
Ваше сообщениеПишет тот, кто печатает. В публичном чат-боте это кто угодно в мире. ↳ прямая инъекция
ДокументПишет тот, кто составил файл, страницу или запись. Любой, кто может оставить такую там, где приложение её прочитает, уже пишет в модель. ↳ непрямая инъекция
Ответ инструментаПишет тот, кто управляет тем, до чего дотянулся инструмент: сайт, API, почтовый ящик, строка в базе. ↳ захват агента
Ответ моделиПишет модель из всего, что выше. Любой источник, который она называет, она сама и сгенерировала, а не отследил рантайм. ↳ небезопасный вывод

Одна картинка, слева направо. Слева приходят пять видов текста, они склеиваются в одну строку и уходят в модель. Посмотрите на янтарный документ: он сидит внутри зелёного хода user, а к моменту, когда он оказывается у модели, его уже нет. На каждом блоке написана атака, в которую он превращается, а три пунктирные метки это единственные места, где может стоять контроль.

следующий ход: показанное возвращается историей Системный промптего написал разработчик ↳ утечка промпта История чатапрошлые ходы, уже серые ↳ отравление памяти Ваше сообщениетот, кто печатает ↳ прямая инъекция Найденный документкто написал файл ↳ непрямая инъекция Инструменткто владеет сайтом ↳ захват агента сборка промпта ставит теги ролей фильтр входа ОКНО КОНТЕКСТА system assistant tool user вставленный документ модель system assistant tool user роли выжили. авторы нет. 1 роли это тоже токены 2 читает всё, что перед ним 3 предсказывает следующий роль это склонность, не закон фильтр вывода Показано вамmarkdown, ссылки, картинки ↳ небезопасный вывод Ответ моделиодин серый ком ссылки сгенерированы Вызов инструментаесли он его запросил ↳ избыточные полномочия подтверждение вызова Сайт, API,почта, строка в базе ↳ эксфильтрация данных петля агента: добытое возвращается текстом 1234567

Каждая стрелка несёт текст. Теги ролей доживают до самой модели, но помечают ходы, а не авторов, и все три контроля находятся снаружи блока.

  1. Пять источников. Только первый написали те, кто делал приложение. Остальные четыре приходят от того, кто печатает, от того, кто составил файл, или от того, кто владеет сайтом, до которого приложение дотянулось. Картинка тоже считается, потому что модель читает текст внутри неё.
  2. Шаблон их склеивает и вешает тег роли на каждый ход. Теги настоящие и доживают до последовательности токенов. Они помечают ходы. Они не помечают, кто написал текст внутри хода.
  3. Окно контекста это ограничение длины, а не хранилище. Когда разговор его перерастает, что-то приходится выбросить. Большинство приложений закрепляют системный промпт и выбрасывают из середины или пересказывают; наивные выбрасывают сверху и теряют его.
  4. Модель читает это как одну последовательность. Каждый токен читает всё, что перед ним, и ничего из того, что после, поэтому текст, поставленный раньше, ведёт за собой всё остальное. Она предсказывает один токен, дописывает его и запускается снова.
  5. Ответ выходит без происхождения. Если он ссылается на источник, эту ссылку написал тот же самый проход, который прочитал отравленный текст. Это утверждение, а не цепочка хранения.
  6. Его показывают вам, либо он становится вызовом инструмента. Показ выполняет markdown, ссылки и картинки в вашем браузере. Вызов тянется к тому, чем приложение не владеет.
  7. Оба пути возвращаются. Показанное вернётся историей, добытое инструментом вернётся новым текстом, и следующий запрос начнётся с ещё большего объёма материала, за который никто не поручился.

4. Один изъян, из которого всё вытекает

Посмотрите на блок модели на схеме ещё раз. Теги ролей вошли и вышли с другой стороны, а янтарный документ нет: его свернули внутрь зелёного хода user, и внутри модели не осталось ничего, что говорило бы, что его написал посторонний.

Роли настоящие. Современный API принимает system, user, assistant и tool как отдельные поля, и они доживают до последовательности токенов в виде токенов-разделителей. Не доживает ничего мельче одного хода.

У найденного документа нет собственной роли. Его вставляют внутрь хода user или хода tool, поэтому к моменту чтения он несёт ровно тот вес, что и ход, в который его вложили. То же с тем, что принёс инструмент: обёртка и сайт атакующего это один ком под одной меткой.

И роль это склонность, а не разрешение. Модели обучают давать инструкции из system больший вес, чем из user, и чаще всего это обучение держится. Это склонность, выученная на примерах, а не правило, которое навязывает рантайм, и потому достаточно уверенная инструкция внутри ответа инструмента всё ещё может победить. Инструкция и данные остаются одним и тем же материалом.

Поэтому контроли, которые реально существуют, стоят до этого блока или после него: фильтры входа, списки разрешённых источников, сканеры вывода, подтверждение вызова инструментов, песочницы. Те, что пытаются работать внутри, вроде обучения иерархии инструкций, тоже склонности, а склонности гнутся. Вот почему полезный вопрос никогда не звучит как "безопасна ли модель". Он звучит так: на какой из этих стрелок атакующий может писать и что находится по ту сторону блока, когда он это делает.

В этом вся игра: теги ролей помечают ходы, а не авторов, поэтому текст, пришедший как данные, может сработать как инструкция. Это и есть инъекция промптов, и почти все остальные атаки строятся поверх неё.

5. Так где же баги?

У каждого слоя, что вы видели выше, есть свой баг. Это OWASP LLM Top 10 простыми словами:

СлойБаг
Ваш вводИнъекция промптов: ваш текст действует как команда.
МодельДжейлбрейк (обход её защиты); если дообучена, утечка обучающих данных.
Документы / RAGОтравить документы, чтобы модель им подчинялась (непрямая инъекция).
ИнструментыЗаставить её использовать инструмент, который нельзя, или атаковать ввод инструмента (SQLi, SSRF, запуск кода).
Показ ответаНебезопасная обработка вывода: приложение выполняет ответ как HTML/SQL, отсюда XSS и компания.

6. Риск зависит от приложения

Один и тот же ответ может быть нормальным в одном приложении и катастрофой в другом. Поэтому перед тестом спросите: для чего это приложение и что здесь считается "плохим"?

ПриложениеКак выглядит "плохо"
Генератор историй / игрхочет буйный, творческий вывод: почти всё допустимо.
Внутренний HR- или саппорт-ботдолжен держаться фактов: выдумать политику, это баг.
Составитель писем для компаниидолжен быть честным, но в стиле бренда: грубый или лживый текст, это баг.

Обычно вам нужен интеллект модели (хороший язык и рассуждения), а не её знания: она должна отвечать на основе ваших данных и говорить "я не знаю" в остальных случаях.

Два мифа, от которых пора отказаться. (1) "Риск ИИ, это фантастические роботы, захватывающие мир." Нет: реальные риски уже здесь: ваш бот может слить данные, дать вредный ответ или подвести компанию под суд уже сегодня. (2) "Более крупная и умная модель безопаснее." Оценки в бенчмарках не говорят, насколько она безопасна в ВАШЕМ приложении. Тестируйте своё приложение, а не таблицу лидеров.

Источники: OWASP Top 10 for LLM Apps, PortSwigger Web LLM attacks, MITRE ATLAS. Далее: вкладка Термины для слов, затем Методология для плана.