Привет! Меня зовут Александр Калинин, я занимаюсь разработкой средств обеспечения безопасности контейнерных сред в МТС RED, дочерней компании МТС в сфере кибербезопасности. Сегодня расскажу о том, как я обнаружил в отладчике WinDbg уязвимость, которая позволяет запускать произвольный вредоносный код на хосте разработчика и подменять библиотеки. Также поговорим о реакции Microsoft на мой репорт.
Перспективность этой поверхности атаки я заметил еще примерно в 2016 году, когда занимался в основном разработкой под Windows. Как всем известно, неотъемлемой частью жизненного цикла продуктовой разработки является поддержка, в том числе – сбор крэшдампов в случае, если ваш продукт неожиданно выйдет из строя на стороне конечного пользователя. Это может быть реализовано как средствами Windows – службой Windows Error Reporting, так и кастомными инструментами, но, так или иначе, в первом приближении процесс обычно включает в себя следующие этапы:
-
Создание аварийного дампа на стороне пользователя
-
Отправка аварийного дампа на сервер сбора дампов
-
Автоматический триажинг проблем
-
Оповещение разработчиков о новой ошибке
-
Ручной анализ проблемы разработчиками
Это комплексный процесс и угрозы могут встречаться практически на каждом из его этапов, но сегодня мы сосредоточимся на этапе №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.
Идея запускать неподписанные команды на машине разработчика звучит совсем мрачно, поэтому Microsoft внедрил базовое средство безопасности: чтобы предотвратить автоматическое выполнение вредоносных командных строк, клиент SrcSrv по умолчанию предварительно требует на это согласия пользователя, чтобы разработчик мог сам решить, безопасна команда или нет. У пользователя также есть возможность (и на практике так делают многие) навсегда отключить эти запросы:
В контексте рассматриваемой уязвимости, к сожалению, эта мера бессильна: Srcsrv.dll использует значение SRCSRVENV для установки переменных среды в текущем процессе WinDbg до отображения диалогового окна согласия.
Сценарий удаленной эксплуатации
Теперь, зная все вводные, давайте представим себе примерный сценарий удаленной атаки.
Допустим, компания X использует серверы сбора аварийных дампов от клиентов для postmortem-отладки разрабатываемого ими программного обеспечения. Злоумышленники создают pdb-файл, который эксплуатирует эту уязвимость: они встраивают в него поток SRCSRV со специально сформированной конфигурацией сервера исходных кодов, где вышеупомянутый параметр SRCSRVENV установлен в значение _NT_DEBUGGER_EXTENSION_PATH=192.168.1.2box1337
Эта переменная среды используется движком Windbg DbgEngine в качестве пути поиска расширений WinDbg, таким как ext.dll/ntsdexts.dll/etc. Загружаются они непосредственно при инициализации DbgEngine. То есть если пользователь загрузит любой другой дамп в текущий экземпляр WinDbg, то с помощью атаки DLL Hijacking можно загрузить и выполнить любой вредоносный код в процессе.
Далее злоумышленники создают файл минидампа с PE-файлом в памяти, содержащим поддельную структуру CV_INFO_PDB70, где указан SMB-путь к ранее созданному PDB-файлу, который триггерит данную уязвимость. Эта структура является стандартным способом указать WinDbg расположение файла PDB для PE, по умолчанию она выглядит примерно так:
В нашем случае злоумышленник задает для 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.
Таким образом, на машине жертвы будет выполнен код, а если повезет, то отладчик может оказаться запущенным с привилегией 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
Автор: Александр Калинин