В ChatGPT нашли уязвимость: аккаунт можно захватить ссылкой на чат

В ChatGPT нашли уязвимость: аккаунт можно захватить ссылкой на чат

Команда исследователей, публикующаяся на parameter.ai, рассказала, что в октябре 2026 года нашла цепочку ошибок в ChatGPT. Обычную публичную ссылку на чат (/share/) можно было превратить в JavaScript-код атакующего, который выполняется от имени chatgpt.com внутри авторизованной сессии того, кто открыл ссылку. Атакующему достаточно создать вредоносный разговор, опубликовать его штатной функцией «поделиться» и отправить ссылку жертве. Устанавливать приложение, вступать в проект, вставлять код или открывать инструменты разработчика не нужно: единственное действие жертвы, открыть ссылку. Авторы подтвердили, что код мог получить список недавних диалогов жертвы, достать содержимое приватного разговора, которым она ни с кем не делилась, и отправить часть данных на внешний сервер. OpenAI исправила проблему 26 октября и классифицировала отчёт как P1.

Цепочка началась с двух безобидных по отдельности функций: интерактивного графика и предпросмотра HTML (кнопка Preview). Preview запускает произвольный HTML в ограниченном фрейме на другом веб-адресе, и он не может прочитать основную страницу ChatGPT (parent.document). Но график подгружает математическую библиотеку MathLive, которая ставит на основной странице обработчик сообщений для экранной клавиатуры. Обмен сообщениями между фреймами (postMessage) разрешён даже изолированному фрейму, и это безопасно, только если получатель проверяет отправителя. MathLive этого не делал: политика проверки источника у его верхнеуровневого контроллера была «none», то есть он принимал сообщения с любого адреса, и не требовал, чтобы сообщение об изменении настройки пришло от заранее одобренного окна.

Preview отправлял два сообщения: первое подменяло раскладку виртуальной клавиатуры HTML-кодом атакующего, второе заставляло показать клавиатуру. MathLive склеивал раскладку в HTML-строку и записывал её через innerHTML на настоящую страницу ChatGPT; вспомогательная функция createHTML ничего не очищала, а лишь помечала строку как доверенную. Скрипты, вставленные через innerHTML, сами не запускаются, поэтому авторы использовали iframe с атрибутом srcdoc. MathLive добавлял такой фрейм в основной документ без атрибута sandbox, и браузер выдавал ему идентичность https://chatgpt.com, так что код внутри получал доступ к родительской странице.

Оставалась политика безопасности контента (CSP): она блокировала встроенный JavaScript, но разрешала скрипты с YouTube. Конечная точка YouTube oEmbed поддерживала параметр callback в стиле JSONP (ответ, это JavaScript, а не обычный JSON). Она пыталась отклонить некорректный callback, но подставляла его в ответ до возврата ошибки проверки. Завершив свой callback конструкцией ;void, авторы сделали дописанный YouTube объект безвредным, и браузер выполнил ответ как скрипт. Итог, произвольный JavaScript от имени chatgpt.com.

Первая рабочая версия была не слишком реалистичной: отправителем служило подконтрольное исследователям приложение ChatGPT, которое жертве пришлось бы сначала подключить. Попытка доставить HTML как вложение упёрлась в то, что при экспорте в публичную ссылку вложение сохранялось, а график с MathLive, нет, и слушать сообщения было некому. Прорыв случился, когда график и HTML-предпросмотр, написанный ассистентом, положили в один обычный публичный разговор: график инициализировал MathLive, а предпросмотр отправлял два сообщения. Ссылку можно разослать по почте, в чате, через обращение в поддержку или в соцсети. В самом стабильном варианте жертва открывала ссылку и один раз нажимала штатную кнопку Preview. Затем авторы пометили HTML-блок как доступный для предпросмотра, и ChatGPT стал открывать его автоматически: единственным кликом оставалось открытие ссылки. Автоматический путь воспроизвели трижды в отдельном аккаунте, в том числе после жёсткого обновления страницы; предупреждение появлялось примерно через 4,5 секунды. Из-за гонки между загрузкой графика и предпросмотра итоговый вариант повторял те же два сообщения в течение ограниченного времени, а защита на странице следила, чтобы доказательство с приватным диалогом и исходящий запрос выполнялись один раз.

В доказательстве кода использовались прямые запросы к авторизованному API: сначала список разговоров (GET /backend-api/conversations с limit=20, order=updated, offset=0), затем данные выбранного приватного диалога (GET /backend-api/conversations/ с num_turns=2). Данные уходили обычным запросом картинки на подконтрольный авторам сервер. Авторы намеренно отправили наружу лишь небольшой фрагмент ответа, хотя внедрённый код мог прочитать его целиком. Поскольку код работал с авторизованным доступом веб-приложения, он, по их словам, мог выполнять любые действия от имени аккаунта жертвы.

По оценке авторов, песочница Preview сработала как задумано; проблема в другом компоненте основной страницы, который согласился выполнять её команды. Они выделяют три решения, превратившие ошибку в полноценную атаку: MathLive принимал изменяющее состояние сообщение, не проверяя фрейм-отправитель; формат сообщения допускал сырой HTML как данные раскладки; этот HTML создавал неизолированный документ с идентичностью chatgpt.com. Лазейка в YouTube, лишь последний обходной шаг для CSP, а не первопричина: блокировка одной этой точки оставила бы ненадёжный Preview со способностью вставлять HTML в ChatGPT. OpenAI воспроизвела и выполнение JavaScript, и доказательство с приватным диалогом. Исправление выкатили в двух версиях веб-фронтенда; в ходе развёртывания изменения CSP заблокировали часть исходной цепочки, а одной версии ещё требовалось обновление. 26 октября OpenAI подтвердила, что обе версии отклоняют кросс-фреймовые сообщения MathLive из отчёта, и закрыла проблему.

В выводах авторы советуют: получатель сообщений должен проверять и веб-адрес отправителя, и конкретное окно, которому дано разрешение; настройки между окнами не должны содержать сырой HTML; динамически создаваемые документы должны оставаться в песочнице, если их содержимое может повлиять на ненадёжный фрейм; CSP должна быть резервной мерой, а не единственным барьером.

Ключевые факты

  • По словам авторов (команда parameter.ai), публичная ссылка на чат ChatGPT выполняла их JavaScript от имени chatgpt.com в авторизованной сессии открывшего её; единственным действием жертвы было открытие ссылки.
  • Код получал список диалогов жертвы, читал приватный разговор, которым она ни с кем не делилась, и отправлял часть данных на внешний сервер.
  • Цепочка: изолированный Preview отправлял два сообщения через postMessage в библиотеку MathLive, не проверявшую отправителя; HTML попадал на страницу через innerHTML, затем создавался фрейм srcdoc без sandbox, а CSP обошли через параметр callback у YouTube oEmbed.
  • OpenAI воспроизвела проблему, выкатила исправление в двух версиях веб-фронтенда, 26 октября подтвердила закрытие и классифицировала отчёт как P1.
  • Авторы подчёркивают: CSP должна быть резервной мерой, а лазейка в YouTube была лишь последним обходным шагом, а не первопричиной.

Почему это важно

Описана атака на чат-сервис ChatGPT, где пользователи хранят личные и рабочие переписки. По описанию авторов, достаточно было одной ссылки на общий чат, чтобы чужой код выполнялся в сессии жертвы и читал приватные диалоги, а возможности шли дальше: они пишут, что могли выполнять любые действия от имени аккаунта. Показательна и сама природа ошибки: изоляция Preview сработала, а брешь возникла на стыке нескольких функций (график, предпросмотр, обмен сообщениями, CSP, публичные ссылки), каждая из которых по отдельности выглядела разумно.

Кому это важно

Разработчикам веб-приложений со встроенными изолированными фреймами и сторонними библиотеками, которые слушают сообщения postMessage; командам безопасности, проверяющим CSP и модели доверия к сторонним доменам; специалистам по безопасности ИИ-продуктов, где контент, созданный пользователем или моделью, отображается внутри основного приложения. Обычным пользователям ChatGPT важно знать, что проблема, по данным авторов, устранена 26 октября.

Как это применить

Выводы авторов практичны: проверяйте и адрес отправителя, и конкретное окно, которому разрешено слать сообщения; не допускайте сырой HTML в настройках, передаваемых между окнами; держите динамически создаваемые документы в песочнице, если на их содержимое мог повлиять ненадёжный фрейм; рассматривайте CSP как запасной барьер, а не единственный. Блокировать только конечную точку YouTube было бы недостаточно, так как первопричина, в обработчике сообщений на основной странице. Обычному пользователю действий не требуется: исправление выкатывается на стороне OpenAI.

Можно ли доверять

Все технические детали взяты из публикации самих исследователей на parameter.ai, независимого подтверждения в источнике нет, заявления OpenAI в нём не приведены. Версию о P1-классификации и исправлении 26 октября тоже излагают авторы. Имена конкретных исследователей в видимой части текста не указаны. Подробности достаточно конкретны (запросы, параметры, число воспроизведений), но проверить их со стороны нельзя. Часть текста (хронология и технические примечания) в доступном материале обрезана.

Риски и подводные камни

В источнике нет сведений об эксплуатации в реальных атаках, о числе затронутых пользователей, об идентификаторе CVE или выплате по программе вознаграждений. Не сказано и то, исправлена ли библиотека MathLive у её разработчиков и закрыл ли YouTube поведение параметра callback. Авторы признают, что в самом стабильном варианте жертве нужен один клик по кнопке Preview, а полностью автоматический вариант они воспроизвели в отдельном аккаунте трижды. Сам по себе вывод об «захвате аккаунта», оценка авторов: на практике они продемонстрировали чтение приватного диалога и отправку небольшой части ответа.

«CSP должна быть резервной мерой, а не единственным барьером после того, как HTML под контролем атакующего попал на основной сайт.»

— Авторы исследования, parameter.ai