Intel Node
CVE-2025-68670: discovering an RCE vulnerability in xrdp
During a security assessment of Kaspersky USB Redirector, we discovered CVE-2025-68670: a pre-auth RCE in the xrdp server component. Project maintainers promptly patched the vulnerability.
In addition to KasperskyOS-powered solutions, Kaspersky offers various utility software to streamline business operations. For instance, users of Kaspersky Thin Client , an operating system for thin clients, can also purchase Kaspersky USB Redirector, a module that expands the capabilities of the xrdp remote desktop server for Linux. This module enables access to local USB devices, such as flash drives, tokens, smart cards, and printers, within a remote desktop session – all while maintaining connection security. We take the security of our products seriously and regularly conduct security assessments.
Kaspersky USB Redirector is no exception. Last year, during a security audit of this tool, we discovered a remote code execution vulnerability in the xrdp server, which was assigned the identifier CVE-2025-68670 . We reported our findings to the project maintainers, who responded quickly: they fixed the vulnerability in version 0. 10. 5, backported the patch to versions 0. 9. 27 and 0. 10. 4. 1, and issued a security bulletin . This post breaks down the details of CVE-2025-68670 and provides recommendations for staying protected.
Client data transmission via RDP Establishing an RDP connection is a complex, multi-stage process where the client and server exchange various settings. In the context of the vulnerability we discovered, we are specifically interested in the Secure Settings Exchange, which occurs immediately before client authentication. At this stage, the client sends protected credentials to the server within a Client Info PDU (protocol data unit with client info): username, password, auto-reconnect cookies, and so on.
These data points are bundled into a TS_INFO_PACKET structure and can be represented as Unicode strings up to 512 bytes long, the last of which must be a null terminator. In the xrdp code, this corresponds to the xrdp_client_info structure, which looks as follows : { [.. SNIP.. ] char username[INFO_CLIENT_MAX_CB_LEN]; char password[INFO_CLIENT_MAX_CB_LEN]; char domain[INFO_CLIENT_MAX_CB_LEN]; char program[INFO_CLIENT_MAX_CB_LEN]; char directory[INFO_CLIENT_MAX_CB_LEN]; [.. SNIP..
] } The value of the INFO_CLIENT_MAX_CB_LEN constant corresponds to the maximum string length and is defined as follows: #define INFO_CLIENT_MAX_CB_LEN 512 When transmitting Unicode data, the client uses the UTF-16 encoding. However, the server converts the data to UTF-8 before saving it. if (ts_info_utf16_in( // [1] s, len_domain, self->rdp_layer->client_info. domain, sizeof(self->rdp_layer->client_info. domain)) ! = 0) // [2] { [.. SNIP.. ] } The size of the buffer for unpacking the domain name in UTF-8 [2] is passed to the ts_info_utf16_in function [1], which implements buffer overflow protection [3].
static int ts_info_utf16_in(struct stream *s, int src_bytes, char *dst, int dst_len) { int rv = 0; LOG_DEVEL(LOG_LEVEL_TRACE, "ts_info_utf16_in: uni_len %d, dst_len %d", src_bytes, dst_len); if (!