Отчеты об уязвимостях

CVE-2025-68670: как мы нашли RCE-уязвимость в xrdp

В дополнение к решениям на базе KasperskyOS «Лаборатория Касперского» предлагает различное вспомогательное ПО, облегчающее работу бизнесу. Например, пользователи Kaspersky Thin Client — операционной системы для тонких клиентов — могут также приобрести Kaspersky USB Redirector — модуль расширения возможностей сервера удаленных рабочих столов xrdp для Linux. Он помогает обеспечить доступ к локальным USB-устройствам (флеш-накопителям, токенам, смарт-картам и принтерам) в сеансе удаленного рабочего стола. Естественно, сохраняя при этом безопасность подключения.

Мы ответственно подходим к безопасности наших продуктов и регулярно проводим анализ их защищенности. Kaspersky USB Redirector — не исключение. В прошлом году в рамках мероприятий по анализу защищенности этого решения мы обнаружили уязвимость удаленного выполнения кода в сервере xrdp, которая получила идентификатор CVE-2025-68670. Мы сообщили о находке мейнтейнерам проекта, и они оперативно отреагировали: исправили уязвимость в версии 0.10.5, портировали патч в версии 0.9.27 и 0.10.4.1 и выпустили бюллетень безопасности. В этой статье мы расскажем, в чем состоит CVE-2025-68670, и дадим рекомендации по защите.

Передача клиентских данных по протоколу RDP

Установка соединения по протоколу RDP — сложный многоэтапный процесс, в ходе которого клиент и сервер обмениваются различными настройками. В контексте найденной уязвимости нас интересует обмен защищенными настройками (Secure Settings Exchange), который происходит непосредственно перед аутентификацией клиента. На этом этапе клиент передает серверу защищенные учетные данные в сообщении Client Info PDU (блок данных протокола с информацией о клиенте): имя пользователя, пароль, cookie-файл для автоматического возобновления подключения и т. д. Эти данные объединены в структуру TS_INFO_PACKET и могут быть представлены в виде Unicode-строк длиной до 512 байт, последний из которых обязательно равен нулю. В коде xrdp этой структуре соответствует структура xrdp_client_info, которая выглядит следующим образом.

Значение константы INFO_CLIENT_MAX_CB_LEN соответствует максимальной длине строки и задается следующим образом.

Клиент при передаче Unicode-данных использует формат UTF-16. При этом на сервере эта информация перед сохранением конвертируется в UTF-8.

Размер буфера для распаковки имени домена в кодировке UTF-8 [2] передается функции ts_info_utf16_in [1], в которой реализована защита от его переполнения [3].

Далее функция in_utf16_le_fixed_as_utf8_proc, где происходит собственно конвертация данных из UTF-16 и UTF-8, проверяет количество записанных байт [4], а также то, что строка заканчивается нулевым байтом [5].

Соответственно, до 512 байт входных данных в кодировке UTF-16 конвертируются в данные в UTF-8, размер которых также может составлять до 512 байт.

CVE-2025-68670 — RCE-уязвимость в xrdp

Уязвимость содержится в функции xrdp_wm_parse_domain_information, которая обрабатывает сохраненное на сервере в кодировке UTF-8 имя домена. Эта функция, как и описанные выше, вызывается до аутентификации клиента, то есть для эксплуатации аутентификация не нужна. Ниже представлен стек вызовов, где это видно.

Фрагмент кода, в котором вызывается уязвимая функция, выглядит следующим образом.

Как можно видеть, первый аргумент функции в строке [6] — это имя домена длиной до 512 байт. Последний аргумент — буфер resultIP размером 256 байт (это можно видеть в строке [7]). Теперь посмотрим, что делает с этими аргументами непосредственно уязвимая функция.

Как видно в коде, если первый символ доменного имени совпадает с «_» (строка [8]), то в буфер resultIP записывается часть доменного имени, начиная со второго символа и заканчивая символами «__» (строка [9]). Поскольку размер доменного имени может достигать 512 байт, даже будучи сформировано корректно, оно может не поместиться в буфере (строка [10]). Как следствие, «лишние» данные запишутся в стек потока, потенциально модифицируя адрес возврата. Если злоумышленник составит доменное имя так, что буфер на стеке будет переполнен и адрес возврата будет подменен значением, подконтрольным атакующему, то при возврате из уязвимой функции поток исполнения изменится в соответствии с намерениями злоумышленника, и он сможет исполнить произвольный код в контексте скомпрометированного процесса (в нашем случае — xrdp-сервера).

Чтобы воспользоваться уязвимостью, атакующему достаточно задать такое имя домена, чтобы после конвертации в UTF-8 между символами «_» и «__» в нем содержалось более 256 байт. Учитывая, что конвертация происходит по определенным правилам, которые легко найти в интернете, это несложная задача — достаточно воспользоваться тем, что длина одной и той же строки в UTF-8 и UTF-16 может различаться. Если коротко, то для этого надо избегать ASCII и некоторых других символов, которые в UTF-16 могут занимать больше места, чем в UTF-8, и при этом не злоупотреблять символами, которые, напротив, после конвертации занимают больше места. Если размер доменного имени в UTF-8 превысит положенные 512 байт, будет ошибка конвертации.

PoC

В качестве PoC для обнаруженной уязвимости мы создали следующий файл .rdp, содержащий IP-адрес RDP-сервера и длинное доменное имя, которое должно спровоцировать переполнение буфера. В доменном имени мы использовали такое количество символов К (U+041A), которое позволит записать в адрес возврата строку «AAAAAAAA». Ниже представлено содержимое файла .rdp.

По нажатии на этот файл процесс mstsc.exe соединяется с указанным в нем сервером. Сервер обрабатывает данные в файле, пытается записать в буфер имя домена, что приводит к переполнению буфера и перезаписи адреса возврата. Если взглянуть на дамп памяти xrdp в момент сбоя, можно увидеть, что буфер и адрес возврата были перезаписаны. На этапе проверки стековой канарейки приложение завершает работу. Пример ниже получен с помощью дебаггера gdb.

Защита от эксплуатации уязвимости

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

На уязвимую функцию также ссылается функция xrdp_wm_show_edits, однако и в ее случае, если компилировать код с безопасными настройками (с использованием стековой канарейки), наиболее тривиальный сценарий эксплуатации будет нереализуем.

Тем не менее стековая канарейка — не панацея. Злоумышленник может узнать или угадать ее значение и перезаписать буфер и адрес возврата так, что сама канарейка останется без изменений. Мейнтейнеры xrdp в бюллетене безопасности, посвященном CVE-2025-68670, не рекомендуют полагаться исключительно на стековую канарейку при использовании проекта.

Хронология устранения уязвимости

  • 12.2025 — Мы отправили отчет об уязвимости через https://github.com/neutrinolabs/xrdp/security
  • 12.2025 — Мейнтейнеры проекта сразу подтвердили, что получили отчет и займутся им в ближайшее время
  • 12.2025 — Приступили к изучению и приоритизации уязвимости
  • 12.2025 — Мейнтейнеры подтвердили уязвимость и начали патчить
  • 12.2025 — Уязвимость получила идентификатор CVE-2025-68670
  • 01.2026 — Патч опубликован в основной ветке проекта

Заключение

Ответственный подход к работе с кодом позволяет сделать надежнее не только наши собственные продукты, но и широко используемые проекты с открытым исходным кодом. Мы уже рассказывали о том, как в результате анализа защищенности решений на базе Kaspersky OS — Kaspersky Thin Client и Kaspersky IoT Secure Gateway — выявили целый ряд уязвимостей в Suricata и FreeRDP, которые мейнтейнеры проектов оперативно исправили. CVE-2025-68670 — это еще одна из таких историй.

Однако обнаружить уязвимость — это только полдела. Мы выражаем благодарность мейнтейнерам xrdp, которые быстро отреагировали на наше обращение, исправили уязвимость и выпустили бюллетень безопасности с описанием проблемы и опций по снижению риска.

CVE-2025-68670: как мы нашли RCE-уязвимость в xrdp

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Отчеты