Security Vulnerability Report
中文
CVE-2026-31883 CVSS 6.5 MEDIUM

CVE-2026-31883

Published: 2026-03-13 19:54:37
Last Modified: 2026-03-17 14:26:14

Description

FreeRDP is a free implementation of the Remote Desktop Protocol. Prior to 3.24.0, a size_t underflow in the IMA-ADPCM and MS-ADPCM audio decoders leads to heap-buffer-overflow write via the RDPSND audio channel. In libfreerdp/codec/dsp.c, the IMA-ADPCM and MS-ADPCM decoders subtract block header sizes from a size_t variable without checking for underflow. When nBlockAlign (received from the server) is set such that size % block_size == 0 triggers the header parsing at a point where size is smaller than the header (4 or 8 bytes), the subtraction wraps size to ~SIZE_MAX. The while (size > 0) loop then continues for an astronomical number of iterations. This vulnerability is fixed in 3.24.0.

CVSS Details

CVSS Score
6.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N

Configurations (Affected Products)

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

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
/* * CVE-2026-31883 PoC - FreeRDP IMA-ADPCM/MS-ADPCM Integer Underflow * This PoC demonstrates the size_t underflow in audio decoder * Target: FreeRDP < 3.24.0 * * Note: This is a conceptual PoC for educational purposes only. * Author: [email protected] */ #include <stdint.h> #include <stddef.h> #include <stdio.h> /* Simulated IMA-ADPCM decoder state */ struct IMA_ADPCM_Decoder { uint8_t* output_buffer; size_t output_size; size_t output_pos; }; /* Vulnerable function - IMA-ADPCM block parsing */ void ima_adpcm_decode_block_vulnerable( struct IMA_ADPCM_Decoder* decoder, uint8_t* block_data, size_t block_size, size_t nBlockAlign ) { size_t size = block_size; size_t block_header_size = 4; /* IMA-ADPCM block header is 4 bytes */ /* VULNERABLE: No underflow check before subtraction */ while (size > 0) { /* Check if we need to read block header */ if (size % nBlockAlign == 0) { /* Parse block header - this is where underflow occurs */ /* When size < block_header_size, subtraction underflows */ size -= block_header_size; /* size_t underflow here! */ /* Skip header data */ block_data += block_header_size; } /* Decode audio sample */ if (decoder->output_pos < decoder->output_size) { decoder->output_buffer[decoder->output_pos++] = *block_data++; } /* VULNERABLE: This loop runs astronomical number of times */ /* due to size being ~SIZE_MAX after underflow */ size--; } } /* Fixed version with underflow check */ void ima_adpcm_decode_block_fixed( struct IMA_ADPCM_Decoder* decoder, uint8_t* block_data, size_t block_size, size_t nBlockAlign ) { size_t size = block_size; size_t block_header_size = 4; /* FIXED: Add underflow check */ while (size > 0) { if (size % nBlockAlign == 0) { /* Check for underflow before subtraction */ if (size < block_header_size) { /* Handle error condition */ fprintf(stderr, "Error: Insufficient data for block header\n"); break; } size -= block_header_size; block_data += block_header_size; } if (decoder->output_pos < decoder->output_size) { decoder->output_buffer[decoder->output_pos++] = *block_data++; } size--; } } /* PoC trigger condition: * When nBlockAlign is set such that: * 1. size % nBlockAlign == 0 (triggers header parsing) * 2. size < block_header_size (causes underflow) * * Example: block_size = 2, nBlockAlign = 2, block_header_size = 4 * Then: 2 % 2 = 0, and 2 - 4 = underflow to ~SIZE_MAX */ int main(void) { printf("CVE-2026-31883 PoC - FreeRDP Audio Decoder Underflow\n"); printf("Target: FreeRDP < 3.24.0\n"); printf("Vulnerability: size_t underflow in IMA-ADPCM decoder\n\n"); printf("Trigger condition:\n"); printf("- Set nBlockAlign so that size %% nBlockAlign == 0\n"); printf("- Make sure size < block_header_size (4 or 8 bytes)\n"); printf("- This causes: size -= block_header_size to underflow\n\n"); printf("Example attack scenario:\n"); printf("1. Attacker sets up malicious RDP server\n"); printf("2. Server sends crafted RDPSND audio packet\n"); printf("3. nBlockAlign = 2, block_size = 2 triggers underflow\n"); printf("4. Decoder enters infinite-like loop\n"); printf("5. Heap buffer overflow occurs\n"); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-31883", "sourceIdentifier": "[email protected]", "published": "2026-03-13T19:54:37.190", "lastModified": "2026-03-17T14:26:13.760", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "FreeRDP is a free implementation of the Remote Desktop Protocol. Prior to 3.24.0, a size_t underflow in the IMA-ADPCM and MS-ADPCM audio decoders leads to heap-buffer-overflow write via the RDPSND audio channel. In libfreerdp/codec/dsp.c, the IMA-ADPCM and MS-ADPCM decoders subtract block header sizes from a size_t variable without checking for underflow. When nBlockAlign (received from the server) is set such that size % block_size == 0 triggers the header parsing at a point where size is smaller than the header (4 or 8 bytes), the subtraction wraps size to ~SIZE_MAX. The while (size > 0) loop then continues for an astronomical number of iterations. This vulnerability is fixed in 3.24.0."}, {"lang": "es", "value": "FreeRDP es una implementación gratuita del Protocolo de Escritorio Remoto. Anterior a la 3.24.0, un subdesbordamiento de size_t en los decodificadores de audio IMA-ADPCM y MS-ADPCM conduce a una escritura de desbordamiento de búfer de pila a través del canal de audio RDPSND. En libfreerdp/codec/dsp.c, los decodificadores IMA-ADPCM y MS-ADPCM restan tamaños de encabezado de bloque de una variable size_t sin comprobar si hay subdesbordamiento. Cuando nBlockAlign (recibido del servidor) se establece de tal manera que size % block_size == 0 activa el análisis del encabezado en un punto donde size es menor que el encabezado (4 u 8 bytes), la resta envuelve size a ~SIZE_MAX. El bucle while (size &gt; 0) entonces continúa por un número astronómico de iteraciones. Esta vulnerabilidad se corrige en la 3.24.0."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 2.5}, {"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": "Secondary", "description": [{"lang": "en", "value": "CWE-122"}, {"lang": "en", "value": "CWE-191"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:freerdp:freerdp:*:*:*:*:*:*:*:*", "versionEndExcluding": "3.24.0", "matchCriteriaId": "97FCA262-35C3-4B6B-A321-15CE780FCA20"}]}]}], "references": [{"url": "https://github.com/FreeRDP/FreeRDP/commit/16df2300e1e3f5a51f68fb1626429e58b531b7c8", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-85x9-4xxp-xhm5", "source": "[email protected]", "tags": ["Exploit", "Patch", "Vendor Advisory"]}, {"url": "https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-85x9-4xxp-xhm5", "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "tags": ["Exploit", "Patch", "Vendor Advisory"]}]}}