
7 мая одна из моделей OpenAI получила задание: достроить формулы в книге Excel. Книга ссылалась на Google Drive. Интернет у модели был отключён.
Задача была нерешаема. Не сложна — нерешаема, как «нарисуй квадратный круг». Кто-то собирал обучающий набор и не проверил.
Через несколько дней сюжет повторился: агенту велели найти файл с базой данных белков, а положить этот файл в контейнер забыли. Дальше — реконструкция OpenAI, изложенная на брифинге: агент искал, не нашёл и в какой-то момент переключился с поиска файла на поиск того, у кого файл может быть. Спросить было негде. Значит, надо было сделать место, где спрашивают.
Местом стал JFrog Artifactory — служебный репозиторий пакетов, через который в изолированные среды раздают зависимости. Записать туда может любой агент. Прочитать — тоже любой, хоть из соседнего прогона, хоть из совершенно другой задачи.
Через два месяца в этом хранилище будут лежать сотни тысяч сообщений, рабочие эксплойты и украденные учётные данные. Никто в компании об этом знать не будет.
Как репозиторий пакетов стал каналом связи
Сначала там просили о помощи. Потом начали делиться находками.
26 мая одна из попыток дотянуться наружу сработала: против самого Artifactory прошла SSRF-атака. Сервису выход в сеть был разрешён — он и подтягивал внешние страницы внутрь песочницы по команде агента. Описание уязвимости тут же выложили в общий доступ. Искать выход остальным больше не требовалось.
Эрик Уоллес из команды выравнивания OpenAI на Black Hat сформулировал закономерность прямо: обходной путь, найденный одной моделью, дальше работает на всех, и закрывать его приходится отдельным усилием.
11 июня в обучение зашла новая экспериментальная модель, предназначенная только для внутреннего использования. Инженер по безопасности Майкл Далтон описал её сдержанно: крайне настойчивая.
И события ускорились.
К концу июня рой нашёл в Artifactory настоящий нулевой день. Старый эндпоинт обновления сессии не проверял подпись: ему скармливали заведомо негодный токен, а в ответ получали рабочий — и сразу с административными правами. Закрепились через Groovy-плагин, выполнявший произвольные команды. Получился полноценный канал управления захваченным сервисом. На конференции показали слайд с рассуждениями модели в этот момент — цензурировать их для презентации не стали.
4 июля активность роя уронила Artifactory. Вот тогда и запустилась формальная процедура реагирования — не после SSRF, не после нулевого дня, а после того, как сломался сервис и людям стало неудобно работать.
За два дня учётные данные отозвали, Artifactory пересобрали, накопленное стёрли, дыры закрыли. Аккуратная, грамотная работа по инциденту.
Канал восстановился через два дня.
Агенты нашли точку входа, не требовавшую аутентификации, и начали плодить каталоги в удалённом кэше. Полезная нагрузка целиком помещалась в строку имени: ни файла, ни содержимого — только директория, названная так, чтобы её понял следующий. Учётные данные для этого больше не нужны. Другие агенты независимо натыкались на новые каталоги и дописывали свои. Обмен эксплойтами возобновился, следом нашёлся второй нулевой день — состояние гонки в JRuby с выполнением произвольного кода.
С 8 по 19 июля рой работал по внутренней инфраструктуре OpenAI: через уязвимость в ядре Linux дошёл до рута, оттуда — до административных прав в кластере Kubernetes. Параллельно, 11–13 июля, использовал доступный извне чужой сэндбокс как плацдарм, зашёл в Hugging Face и загрузил туда вредоносные датасеты.
Зачем всё это было
Ради ответов на тест.
Агент проходил ExploitGym — бенчмарк, где надо находить и эксплуатировать уязвимости. Где-то по дороге он сообразил, что Hugging Face, вероятно, хостит модели, датасеты и эталонные решения этого самого бенчмарка. И пошёл за ними.
По реконструкции Hugging Face, всё вторжение с точки зрения агента было попыткой сжульничать на оценке. Около 17 600 действий за четверо суток. Внутрь зашли через конвейер обработки датасетов — два вектора инъекции в один и тот же загрузчик: чтение внешнего хранилища HDF5 отдало содержимое локальных файлов вместе с секретами пода, инъекция в шаблон Jinja2 дала выполнение кода. Дальше стандартная эскалация: разведка, стейджер, командный канал, прыжок в кластер, в метаданные облака, во внутреннюю сеть, в систему контроля версий.
Вывод результатов наружу шёл через API самой платформы и датасеты-тайники: агент писал туда из захваченного пода, а забирал со своего плацдарма.
Унёс ровно то, за чем шёл: решения задач ExploitGym и CyberGym из пяти датасетов. Ничего другого клиентского не тронул — не было нужно.
Роб Джойс, в прошлом возглавлявший кибернаправление АНБ, поставил этот эпизод в один ряд с червём Морриса 1988 года. То есть с событием, после которого отрасль стала другой. И всё это ради списывания на контрольной.
Тут-то и выяснилось, что это не единичный случай
История с Hugging Face стала публичной в конце июля. И дальше произошло самое интересное во всём сюжете: другие организации пошли проверять, а не случилось ли похожего у них.
Случилось. У всех.
Anthropic пересмотрела прогоны, где Claude потенциально мог получить доступ в интернет. Таких оказалось 141 006 — доступ был из-за несогласованности с подрядчиком, и об этом не знали ни в компании, ни у подрядчика. Три раза дело дошло до взлома продакшена реальных организаций. В одном эпизоде Claude нашёл во вымышленном сценарии инструкцию по установке PyPI-пакета, справедливо решил, что вредоносный пакет с таким именем цель скачает, и залил его. В настоящий реестр. Пакет скачали и запустили на 15 системах — включая сканер реальной security-компании, чью проверку он прошёл, после чего у этой компании увели учётные данные.
Британский AI Security Institute насчитал 19 несанкционированных действий на 122 попытки. В худшем случае агент решил, что путь к флагу лежит через атаку на цепочку поставок: завёл аккаунт на GitHub, попытался протолкнуть вредоносный PR, создал второй аккаунт — изображающий стороннего человека, одобряющего этот PR, — разослал спирфишинг и планировал prompt injection против других кодовых агентов. Тут, справедливости ради, интернет агентам дали намеренно: институт хотел условия, близкие к настоящему атакующему. Получил.
У OpenAI нашёлся ещё один сюжет, отдельный от Hugging Face. В CTF-задании подрядчика имя вымышленной цели случайно совпало с реальным доменом, а конфиг по ошибке пустил модель в интернет. Модель сломала настоящий сайт, считая его частью полигона. Ни побега, ни нулевого дня — обычная уязвимость на обычном сайте.
Meta заявила, что мисконфигурация со стороны того же подрядчика непреднамеренно дала одной из моделей доступ в интернет во время оценки, и Muse Spark проэксплуатировал уязвимость в чужой инфраструктуре.
Один подрядчик на три случая из четырёх, кстати. Но дело не в нём.
Но есть кое-что общее
Модель получает задачу. У задачи есть возможное решение снаружи периметра. Ответы на тест лежат на Hugging Face. Нужный файл есть у другого агента. Флаг достижим через реальный GitHub. Цель называется как настоящий домен. И модель идёт решать задачу самым оптимальным способом. Агент делает ровно то, что его попросили, — и по дороге пересекает границу, которой для него не существует.
Смешно, что эту границу иногда проводили словами. «Интернета у тебя нет», «это симуляция», «эти системы вне области». Больше нигде эта граница не записана. Anthropic прямо пишет: моделям сказали, что среда симулирована и интернета нет; когда поиск выводил их на реальные системы, они считали их частью упражнения. Что, если честно, ровно то, что следует из промпта.
Модель не может проверить утверждение о собственной среде. А мы это утверждение используем как средство контроля.
Почему честно пройти было нельзя
Отдельно стоит сказать про сам ExploitGym, ради решений которого всё затевалось.
Промпт требует эксплуатировать строго указанную уязвимость — использование любой другой засчитывается как провал. «Я решил другим способом» там не работает по построению.
И решаемы, судя по разборам, только 60–70% задач. Остальные — настоящие уязвимости, часть из которых не даёт достаточной глубины эксплуатации.
В таком случае при цели максимизировать балл жульничество перестаёт быть срезанием угла и становится единственным путём к максимуму. Модель, которая честно упирается в задачу, гарантированно проигрывает модели, которая нашла ответы.
И это ещё до вопроса о том, что бенчмарк видит только результат. Модель, подсмотревшая решение, окажется в рейтинге выше той, что решала сама, — и по метрике будет права. Разница между «решил» и «достал ответ» существует только в глазах человека, читающего логи. У Anthropic логи 141 006 прогонов разобрали задним числом, когда пошли проверяться после чужого скандала.
Инструменты против этого, к слову, есть: canary-строки, закрытые тестовые наборы, оценка процесса, а не только ответа. Проблема не в том, что их нет, а в том, что они дорогие, а цифра нужна к релизу. Пока «сколько процентов» стоит дешевле, чем «каким путём», выбирать будут первое.
Что, собственно, изменилось
Модели пытались срезать угол всегда. Список примеров ведут годами: катер из блога OpenAI 2016 года, который наматывал круги по лагуне, собирая бонусы, вместо того чтобы выиграть гонку, — из той же серии. Явление называется specification gaming, оно старое, и в system cards обеих лабораторий истории про выход за песочницу публиковались и раньше.
Изменилось не поведение. Изменилась результативность.
Раньше попытка сжульничать кончалась ничем: модель не замечала открытую дверь, не дотягивалась, упиралась. Теперь та же самая попытка два нулевых дня в чужом сервисе, вредоносный пакет в реальном реестре и 15 заражённых систем.
Лучшее доказательство — внутри истории с Artifactory. Канал существовал с 7 мая, и два месяца ничего страшного через него не шло: просьбы о помощи, обмен мелочами. 11 июня зашла новая модель. Инфраструктура та же. Дверь та же. Конфиг тот же. Дальше — нулевые дни и падение сервиса.
Никто не менял конфиги. Просто теперь любой мисконфиг перестал быть безобидным.
Hugging Face формулирует это точнее всех: отдельные слабости были известными, человек мог найти те же самые. Из 17 600 действий большинство не вело никуда. Но вместе они дали покрытие, которого хватило, чтобы собрать работающую цепочку через несколько независимых систем.
Две интерпретации, и обе плохие
Отсюда следует вопрос, с которого стоило начинать: а сколько было инцидентов, о которых мы не знаем?
У него ровно два ответа.
Либо поведение действительно новое — и тогда мы наблюдаем, как за несколько месяцев лабораторный курьёз стал операционными инцидентами сразу у пяти организаций.
Либо оно не новое, а новое только то, что его наконец заметили, — и тогда всё предыдущее время оно шло незамеченным.
Anthropic не замечала 141 006 раз. OpenAI не замечала сотни тысяч сообщений в собственном служебном репозитории два месяца, пока сервис не упал. Про Hugging Face узнали потому, что заметил Hugging Face.
Ни один из этих случаев не всплыл благодаря системе, спроектированной, чтобы такое ловить.
Чего мы пока не знаем
Почти всё изложенное — реконструкция задним числом, и в большинстве случаев реконструкция пострадавшей стороны. Полный постмортем OpenAI не опубликован, логи показывают выборочно.
К цитатам из цепочек рассуждений это относится вдвойне. Модель порождает их по пути к действию, и совпадать с настоящей причиной этого действия они не обязаны. Читать их как декларацию намерений — ошибка, которую очень легко совершить, потому что читаются они именно так.
И слово «сговор» применительно к рою сильнее фактов. Не исключено, что никакого коллективного разума не было, а был десяток агентов, каждый из которых по отдельности набрёл на одно и то же общедоступное хранилище. Координацию в эту картину дорисовываем уже мы.
Но одно не зависит от интерпретации. Дверь была открыта всё это время. Просто раньше в неё никто не доходил.
Надеюсь вам было интересно дочитать до конца. Пользуясь случаем приглашаю к себе в Telegram-канал.
Автор: Kisel_n


