Неполадки в отладке: как уязвимость в WinDbg позволяет атаковать разработчиков

в 7:00, , рубрики: windbg, уязвимости

Привет! Меня зовут Александр Калинин, я занимаюсь разработкой средств обеспечения безопасности контейнерных сред в МТС RED, дочерней компании МТС в сфере кибербезопасности. Сегодня расскажу о том, как я обнаружил в отладчике WinDbg уязвимость, которая позволяет запускать произвольный вредоносный код на хосте разработчика и подменять библиотеки. Также поговорим о реакции Microsoft на мой репорт.

Неполадки в отладке: как уязвимость в WinDbg позволяет атаковать разработчиков - 1

Перспективность этой поверхности атаки я заметил еще примерно в 2016 году, когда занимался в основном разработкой под Windows. Как всем известно, неотъемлемой частью жизненного цикла продуктовой разработки является поддержка, в том числе – сбор крэшдампов в случае, если ваш продукт неожиданно выйдет из строя на стороне конечного пользователя. Это может быть реализовано как средствами Windows – службой Windows Error Reporting, так и кастомными инструментами, но, так или иначе, в первом приближении процесс обычно включает в себя следующие этапы:

  1. Создание аварийного дампа на стороне пользователя

  2. Отправка аварийного дампа на сервер сбора дампов

  3. Автоматический триажинг проблем

  4. Оповещение разработчиков о новой ошибке

  5. Ручной анализ проблемы разработчиками

Это комплексный процесс и угрозы могут встречаться практически на каждом из его этапов, но сегодня мы сосредоточимся на этапе №5.

TL/DR

Уязвимость позволяет атакующему выполнять произвольный код в контексте отладчика Microsoft WinDbg с включенным клиентом Source Server. Для удаленного варианта эксплуатации этой уязвимости необходим доступ от целевого хоста к SMB-ресурсу, предоставленному злоумышленником - как внутри локальной сети компании, так и в интернете, если позволяет корпоративный фаерволл (что, к сожалению, до сих пор встречается довольно часто).

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

В нашем примере мы переопределяем путь к расширениям WinDbg, что провоцирует DLL Hijacking во время повторной инициализации DbgEngine, и успешно приводит к выполнению произвольных DLL, включая DLL, доступные по путям UNC, например с SMB-сервера.

Подробнее о механике уязвимости

В WinDbg есть функция «Индексация исходного кода», которая позволяет разработчикам встраивать в файлы отладочной информации PDB инструкции о том, как загрузить исходный код для конкретной сборки PE-файла. PDB-файлы генерируются при сборке кода компилятором MSVC и по умолчанию содержат отладочные символы – структуры, сигнатуры функций и многое другое. К этому билду можно добавить информацию об источнике исходных кодов. Эти инструкции необходимо расположить в стриме PDB-файла под названием Srcsrv, и выглядят они как классический ini-файл.

Данный файл, кроме всего прочего, содержит интересные нам ключи:

  • SRCSRVCMD описывает шаблон команды, которая должна скачать файл с исходным кодом из репозитория. Например, для TFS она выглядит как tf.exe get ...

  • SRCSRVENV позволяет задать переменные среды для запускаемой команды из SRCSRVCMD в формате KEY=VALUE.

Пример содержимого стрима SrcSrv

Пример содержимого стрима SrcSrv

Идея запускать неподписанные команды на машине разработчика звучит совсем мрачно, поэтому Microsoft внедрил базовое средство безопасности: чтобы предотвратить автоматическое выполнение вредоносных командных строк, клиент SrcSrv по умолчанию предварительно требует на это согласия пользователя, чтобы разработчик мог сам решить, безопасна команда или нет. У пользователя также есть возможность (и на практике так делают многие) навсегда отключить эти запросы:

Окно запроса разрешения на выполнение команды

Окно запроса разрешения на выполнение команды

В контексте рассматриваемой уязвимости, к сожалению, эта мера бессильна: Srcsrv.dll использует значение SRCSRVENV для установки переменных среды в текущем процессе WinDbg до отображения диалогового окна согласия.

Последовательность триггера уязвимости и отображения окна предупраждения

Последовательность триггера уязвимости и отображения окна предупраждения

Сценарий удаленной эксплуатации

Теперь, зная все вводные, давайте представим себе примерный сценарий удаленной атаки.

Допустим, компания X использует серверы сбора аварийных дампов от клиентов для postmortem-отладки разрабатываемого ими программного обеспечения. Злоумышленники создают pdb-файл, который эксплуатирует эту уязвимость: они встраивают в него поток SRCSRV со специально сформированной конфигурацией сервера исходных кодов, где вышеупомянутый параметр SRCSRVENV установлен в значение _NT_DEBUGGER_EXTENSION_PATH=192.168.1.2box1337

Переопределение переменной среды с путем к расширениям WinDbg

Переопределение переменной среды с путем к расширениям WinDbg

Эта переменная среды используется движком Windbg DbgEngine в качестве пути поиска расширений WinDbg, таким как ext.dll/ntsdexts.dll/etc. Загружаются они непосредственно при инициализации DbgEngine. То есть если пользователь загрузит любой другой дамп в текущий экземпляр WinDbg, то с помощью атаки DLL Hijacking можно загрузить и выполнить любой вредоносный код в процессе.

Далее злоумышленники создают файл минидампа с PE-файлом в памяти, содержащим поддельную структуру CV_INFO_PDB70, где указан SMB-путь к ранее созданному PDB-файлу, который триггерит данную уязвимость. Эта структура является стандартным способом указать WinDbg расположение файла PDB для PE, по умолчанию она выглядит примерно так:

Формат структуры CV_INFO_PDB70

Формат структуры CV_INFO_PDB70

В нашем случае злоумышленник задает для PdbFileName UNC-путь к подконтрольному ему ресурсу по протоколу SMB, который в дальнейшем и отдаст на машину жертвы файл .pdb с подделанным потоком SRCSRV.

Сотрудник компании X получает файл минидампа для анализа причин падения продукта, и открывает его в WinDbg, который первым делом загружает файл .pdb из ресурса SMB. WinDbg идентифицирует поток SRCSRV из PDB и передает содержимое потока SRCSRV в функцию srcsrv.dll SrcSrvExecTokenA. Эта функция считывает переменную SRCSRVENV и устанавливает переменную среды _NT_DEBUGGER_EXTENSION_PATH на текущий процесс WinDbg. Уязвимость приведена в действие. Позже отображается окно согласия, но, независимо от решения пользователя, данный экземпляр WinDbg уже содержит измененную переменную среды с путем до расширений.

Так как анализ аварийных дампов памяти – зачастую процесс поставленный на поток, после работы над этим дампом сотрудник компании X открывает следующий файл дампа или даже любой исполняемый файл (опять же, в текущем процессе WinDbg), а уже после этого DbgEngine загрузит библиотеки DLL-расширения не из директории с самим отладчиком, а из предоставленного злоумышленником ресурса SMB.

Процесс WinDbg загружает расширения по сетевому пути

Процесс WinDbg загружает расширения по сетевому пути

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

Уязвимость была проверена на стенде с WinDbg 10.0.19041.685 и Microsoft Source Server (srcsrv.dll) 10.0.19041.685 и имеет классификации Security feature bypass, Local privilege elevation, Remote code execution и Code injection.

Корень проблемы

SRCSRVENV предназначен для назначения переменных среды для выполнения команды из SRCSRVCMD, поэтому его необходимо указывать, например, в аргументе lpEnvironment вызова CreateProcess, а не в контексте вызывающего процесса с использованием SetEnvironmentVariable.

Опасность данной уязвимости

Атаки на самих разработчиков в инфраструктуре компании очень опасны, поскольку они обычно имеют права локального администратора, а также доступ к значительной части исходного кода, сертификатам подписи кода и документации, включая права на запись к части кода продукта. Последствия могут варьироваться от утечки информации до фактического заражения кода продуктов компании, что обойдется компании в огромную сумму.

Общение с Microsoft

  • 22 марта 2021 – отчет о проблеме отправлен Microsoft

  • 22 марта 2021 – отчет принят Microsoft

  • 2 апреля 2021 – проблема подтверждена Microsoft

  • 7 апреля 2021 – присуждено баунти за уязвимость

  • 17 июля 2021 – фикс на этапе тестирования

  • 27 июля 2021 – озвучены планы по релизу фикса в версии SDK от октября 2021

  • 9 октября 2021 – назначено временное CVE (CVE-2021-X41358)

  • 13 октября 2021 – Microsoft отказали в регистрации CVE-2021-41358.

    Тут хотелось бы остановиться подробнее. Отказ в регистрации уязвимости мне мотивировали тем, что фикс попал в новую версию продукта - Windows SDK 11, а уязвимый код был обнаружен в отладчике, который является частью Windows SDK 10. Буквально «нет секьюрити апдейта – нет CVE». Кажется, обычно регистрация уязвимостей работает не совсем так, но оставим это на совести вендора.

  • 26 сентября 2023 - опубликована эта статья

Митигация рисков

Фикс заявлен в версии WinDbg 10.0.22621.0 и выше, а также в Windows SDK 11. Рекомендую использовать для отладки именно эти версии.

Также была написана простая утилита, проверяющая файлы дампов на наличие внешних ссылок на pdb-файлы (Github). Она не проверяет эксплуатацию уязвимости в конфигурации srcsrv, но, как минимум, обнаруживает попытки загрузки pdb из внешних ресурсов, что может эффективно митигировать такую атаку в автоматическом режиме.

Ссылки

Индексация исходников для WinDbg: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/source-indexing

Формат PDB: https://github.com/microsoft/microsoft-pdb/blob/master/README.md

Автор: Александр Калинин

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js