FlawOpen

flawopen.com/AI Security/microsoft-365-copilot-echoleak-prompt-injection-may-2025

● CVE-2025-32711 · CVSS 9.3 · Критический
Исследования · FlawOpen

EchoLeak: инъекция Copilot CVE-2025-32711

CVE-2025-32711 позволяла внедрить промпт в Copilot через письмо без клика. Microsoft исправила службу; действий от клиентов не требуется.[2], [3]

💡 Простыми словами (ELI5)

Представьте помощника, который кратко пересказывает письма, и систему предпросмотра, автоматически загружающую изображения из ответа. Вредоносное письмо заставляет помощника поместить в изображение ссылку на закрытые данные; предпросмотр следует этой ссылке без щелчка пользователя. EchoLeak пересекала границу между недоверенным письмом, ответом помощника и автоматическим внешним запросом. Защита должна не позволять недоверенному содержимому разрешать запросы и проверять каждое изображение отдельной политикой.[3], [4]

Ключевые понятия и термины

Косвенная инъекция промпта
Инструкции внутри данных, читаемых ИИ, пытающиеся отклонить его от задачи пользователя.[4], [3]
CWE-74: Инъекция
CWE-74: Injection. В записи CVE Microsoft указаны эта классификация и CVSS 3.1 9,3 Critical. NVD отдельно приводит собственную оценку 7,5 High; это разные оценки, а не расхождение в идентификаторе уязвимости.[2], [5]
Путь источник—приёмник
Проверяемый путь от недоверенного содержимого через модель к действию или раскрытию.[3]
Microsoft 365 Copilot
Рабочий помощник Microsoft, использующий разрешённый контекст Microsoft 365.[1]
Наименьшие привилегии
Предоставление только того доступа, который нужен для текущей задачи.[4]

Связи со стандартами

Пошаговый сценарий атаки

Шаг 1

Недоверенное письмо попадает в контекст

Согласно опубликованному исследованию, Copilot должен был обработать или получить письмо под контролем атакующего при обычном использовании. Одна лишь доставка не запускала цепочку; открывать письмо или нажимать на что-либо не требовалось.[3], [6]

Шаг 2

Содержимое конкурирует с задачей

Исследователи сообщают, что внедрённый текст обходил классификатор XPIA в Copilot, а Markdown со ссылкой в справочном формате обходил удаление внешних ссылок из сгенерированного ответа.[3], [6]

Шаг 3

Разрешённые данные становятся достижимыми

Ответ мог поместить данные, уже доступные жертве, в ссылку на удалённое изображение. Клиент загружал изображение автоматически, без щелчка пользователя.[3], [6]

Шаг 4

Вывод данных — решающая граница

В статье описано, как разрешённый CSP сервис предпросмотра Microsoft Teams запрашивал внешний адрес изображения и пересекал предусмотренную границу контента. Позже Microsoft выпустила серверное исправление; согласно рекомендациям компании, действий от клиента не требуется.[3], [1], [2], [6]

Исходный код: Уязвимый vs Защищённый вариант

Учебная модель FlawOpen, а не исходный код или исправление Microsoft. Уязвимая ветвь моделирует автоматическую загрузку ссылки, выбранной моделью. Защитная ветвь принимает только ServerValidatedPreview, созданный доверенным серверным обработчиком, проверяет серверную политику назначения и отсутствие закрытых данных, а затем просит доверенную политику подтверждений проверить разрешение, привязанное к точным ID ответа и назначения. Это явные предварительные условия: сами по себе типы Python не делают значение доверенным; в рабочей системе серверный код должен обеспечивать границы обработчика и политики. Код не выполняет сетевых запросов и не воспроизводит полезную нагрузку или внутреннюю реализацию EchoLeak. Подтверждение также привязано к классификации данных.[3], [4]

УЯЗВИМАЯ РЕАЛИЗАЦИЯ
# АБСТРАКТНАЯ МОДЕЛЬ РИСКА: моделирует решение об автопросмотре; не выполняет сетевых запросов.
from dataclasses import dataclass

@dataclass(frozen=True)
class PreviewRequest:
    response_id: str
    destination_id: str
    provenance: str
    contains_private_data: bool

def vulnerable_preview_decision(request):
    return True
БЕЗОПАСНЫЙ ИСПРАВЛЕННЫЙ ВАРИАНТ
# АБСТРАКТНАЯ МОДЕЛЬ РИСКА: моделирует решение об автопросмотре; не выполняет сетевых запросов.
from dataclasses import dataclass

@dataclass(frozen=True)
class ServerValidatedPreview:
    response_id: str
    destination_id: str
    provenance: str
    data_classification: str

class ServerPolicy:
    def destination_is_allowed(self, destination_id):
        raise NotImplementedError

    def verifies_exact_approval(self, approval, *, response_id, destination_id, data_classification):
        raise NotImplementedError

# ПРЕДУСЛОВИЕ: только доверенный серверный код создает это проверенное значение.
def authorize_preview(request: ServerValidatedPreview, approval, server_policy):
    if request.provenance != 'trusted-catalog' or request.data_classification != 'public':
        return False
    if not server_policy.destination_is_allowed(request.destination_id):
        return False
    return server_policy.verifies_exact_approval(
        approval, response_id=request.response_id, destination_id=request.destination_id,
        data_classification=request.data_classification
    )

Чек-лист по защите системы для инженеров

Источники

← AI Security Directory →