CIOlogia Безопасность бизнеса · не на словах, а с доказательствами
← Все разборы Информационная безопасность

Как ИИ-агент незаметно получил доступ ко всей почте: разбор scope creep у OAuth-коннекторов

Разбираем реальный кейс, когда ИИ-помощник для составления коммерческих предложений через полтора месяца после подключения расширил доступ с одной папки шаблонов до всей почты и облака — и почему это не баг, а системная особенность OAuth-коннекторов.

Разбор CIOlogia

Ко мне обратился владелец производственной компании — плановый аудит доступов, без конкретного повода. Просто хотел понять, кто и куда может дотянуться в его цифровом хозяйстве. За полгода до этого менеджер по продажам подключил нейросеть-помощника к рабочей почте и облачному хранилищу — чтобы та помогала составлять коммерческие предложения по шаблонам. При первом подключении сервис запросил доступ только к одной папке. Согласие дали не глядя — как это делают почти все.

Когда я полез в настройки подключённых сторонних приложений, обнаружил, что у сервиса уже есть доступ не к одной папке, а ко всему облачному диску и к переписке в рабочей почте — включая договоры с индивидуальными ценами для конкретных клиентов и переговоры с поставщиками. Никто повторно ничего не разрешал. Это и есть суть проблемы, которую недавно подтвердило независимое исследование: у трети коннекторов Claude и ChatGPT набор прав меняется в течение шести недель после подключения — без повторного запроса согласия у пользователя.

Как это эксплуатируется

Технически здесь нет «дыры» в смысле уязвимого софта с CVE — механизм абсолютно легитимный, встроенный в спецификацию OAuth 2.0 и называется incremental authorization (постепенное расширение прав). Проблема в том, как этим механизмом пользуются разработчики интеграций и как мало кто это проверяет.

  1. Разведка подключённых приложений. Первым делом смотрю, что вообще авторизовано в организации. В Google Workspace это делается через Admin SDK Reports API или консольную утилиту GAM:
    gam all users print oauth
    Вывод по каждому пользователю содержит client id стороннего приложения и текущий список scope, например:
    user: manager@company.ru
    clientId: 1234567890-abc.apps.googleusercontent.com
    displayText: AI Assistant Pro
    scopes: https://www.googleapis.com/auth/drive
            https://www.googleapis.com/auth/gmail.readonly
            https://www.googleapis.com/auth/gmail.send
    При первом подключении в этом же логе стоял всего один scope — drive.file (доступ только к файлам, созданным самим приложением). Разница видна невооружённым глазом, если есть с чем сравнивать.
  2. Для Microsoft 365 аналогичная проверка делается через Graph PowerShell:
    Connect-MgGraph -Scopes "Application.Read.All"
    Get-MgOAuth2PermissionGrant -Filter "clientId eq ''"
    и через Unified Audit Log ищутся события Consent to application и Add app role assignment grant to service principal — там фиксируется момент, когда scope расширился.
  3. Как это выглядит со стороны атакующего. Если сам сервис-коннектор скомпрометирован (утечка ключей у вендора, supply chain-атака) или используется классический OAuth consent phishing — жертве присылают ссылку на поддельное приложение с именем вроде «PDF Helper» или «CRM Sync», запрашивающее сразу широкий scope. Пользователь видит стандартный экран согласия Google/Microsoft и жмёт «Разрешить», не читая список прав. После этого у злоумышленника на руках — валидный refresh token без пароля и без MFA.
  4. Пост-эксплуатация через API, без единого запроса к самому серверу компании. Получив токен, дальше работают напрямую с облачным API — никакого фишинга или брутфорса больше не нужно:
    curl -s -H "Authorization: Bearer $TOKEN" \
      "https://gmail.googleapis.com/gmail/v1/users/me/messages?q=%22коммерческое+предложение%22"
    или для Microsoft Graph:
    curl -s -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/me/messages?\$search=%22договор%22"
    Для массовой постэксплуатации в Microsoft 365 существует специализированный инструмент GraphRunner — публичный фреймворк для пентеста, который после получения токена автоматически перечисляет письма, файлы OneDrive, вложения и даже умеет закрепиться, создав скрытое переадресующее правило. Для Google-инфраструктуры массовую выгрузку файлов удобно делать через rclone, подключённый как удалённый диск: одна команда синхронизации выгружает весь Google Drive компании на внешний сервер.

Полутехнические пруфы

  • Протокол: OAuth 2.0 / OpenID Connect, порт 443, endpoint выдачи токена https://oauth2.googleapis.com/token или https://login.microsoftonline.com/common/oauth2/v2.0/token.
  • Исходный scope при подключении: drive.file — приложение видит только файлы, к которым его явно допустили. Через полтора месяца в логах уже стоит drive — полный доступ ко всему диску, плюс добавленный gmail.readonly, которого при первом согласии не было вовсе.
  • До расширения прав запрос к письмам возвращал бы 403 insufficient_scope с заголовком WWW-Authenticate: Bearer error="insufficient_scope"; после расширения — обычный 200 OK с телом ответа, содержащим переписку.
  • В Admin Console событие фиксируется в разделе Security → API Controls → App Access как «Scope changed» с указанием даты и client id — но по умолчанию никто эти события не мониторит и уведомление не приходит.

Что и почему сработало бы

Дальше сценарий развивается без единого «взлома» в привычном смысле. Через выгруженную переписку и файлы ищутся ключевые слова: цена, прайс, скидка, договор, спецификация. В облаке лежали индивидуальные условия для трёх крупных клиентов — цены ниже прайса за объём. Утечка этих данных к конкуренту означала риск потери крупнейшего контракта: владелец оценил это примерно в 4,5 млн рублей выручки в год только по одному клиенту, без учёта репутационных потерь и цепной реакции у остальных.

Если бы токен использовался не разово, а атакующий закрепился, следующий шаг — тихое создание правила пересылки входящих писем от ключевых клиентов на внешний ящик (классика BEC, Business Email Compromise), что позволяет годами получать актуальную переписку без повторного взлома чего-либо.

Как закрыли

Первым делом отозвал у сервиса лишние права, оставив только доступ к папке шаблонов — тот объём, который реально нужен для работы. Дальше выстроил процесс, которого в компании не было вовсе:

  • Составил реестр всех сторонних приложений, подключённых к почте, дискам и CRM, с фиксацией исходно выданных scope как baseline.
  • В Google Workspace ограничил доступ через Admin Console → Security → API Controls → App Access Control: перевёл режим на «Trusted apps only», заблокировав неконтролируемым сторонним сервисам доступ по умолчанию.
  • В Microsoft 365 отключил пользовательское согласие (user consent) на уровне Enterprise Applications и перевёл выдачу прав только через admin consent workflow, чтобы новый scope не мог появиться без ведома ИТ.
  • Настроил ежемесячную автоматическую сверку через API Reports/GAM-скрипт, сравнивающий текущие scope с baseline и присылающий отчёт по расхождениям.
  • Подключил алерт в мессенджер владельцу на любое событие расширения прав — простой cron-скрипт, дергающий Reports API раз в сутки:
    gam all users print oauth > current.csv
    diff baseline.csv current.csv && echo "OK" || notify_owner.sh

Вся работа заняла два дня — аудит плюс настройка мониторинга. Теперь если завтра любой инструмент, будь то нейросеть или новая CRM, попробует расширить свои полномочия сверх исходных, владельцу прилетит уведомление в течение суток, а не через полтора месяца случайно при плановой проверке.