{"schema":"threatline.record/2","record":{"id":"GHSA-26cc-wjh8-hjw6","aliases":["GHSA-26cc-wjh8-hjw6"],"summary":"Heap Buffer Overflow in FreeRDP persistent cache v2 parser FreeRDP ","details":"Summary\r\nA heap‑buffer‑overflow vulnerability exists in FreeRDP’s persistent cache v2 parser. When processing a maliciously crafted persistent cache v2 file, integer wraparound within bitmap‑size calculation leads to inconsistent buffer‑size accounting, which can trigger heap memory corruption, denial‑of‑service and potential arbitrary code execution.\r\nDetails\r\nThis vulnerability resides in persistent_cache_read_entry_v2 inside libfreerdp/cache/persistent.c.\r\nThe helper function persist_cache_get_data computes bitmap data size with the expression 4ull * entry->width * entry->height.\r\nWhen parsing a malicious v2 persistent cache file, attacker‑controlled large width and height values trigger 64‑bit unsigned integer wraparound, producing a small falsified expected value.\r\nThe existing check if (expected > UINT32_MAX) cannot reject this wrapped small value.\r\nallocated = MAX(0x4000, expected) guarantees the heap buffer allocated via winpr_aligned_recalloc is at least 0x4000 bytes. However, entry->size is assigned the wrapped‑around small expected value.\r\nIn persistent_cache_read_entry_v2, the code performs:\r\n\r\nif (fread(entry->data, 0x4000, 1, persistent->fp) != 1)\r\n\treturn -1;\r\nIt unconditionally reads fixed 0x4000 (16 KiB) bytes from the cache file into entry->data.\r\nAlthough the heap buffer itself is sized for 0x4000, the variable entry->size holds the wraparound‑truncated small value. This inconsistent size accounting introduces risks for subsequent logic that relies on entry->size.\r\nAdditionally, the helper scan‑loop function persistent_cache_read_v2 uses hard‑coded fseek(fp, 0x4000, SEEK_CUR) to skip bitmap payload. Combined with the wraparound‑corrupted dimension values, file‑pointer mis‑positioning occurs during cache‑file traversal, leading to parsing‑state corruption, out‑of‑bounds memory access when interpreting subsequent cache‑entry headers, and heap corruption.\r\nRelevant real upstream vulnerable snippet:\r\n\r\nstatic int persistent_cache_read_entry_v2(rdpPersistentCache* persistent,\r\n                                          PERSISTENT_CACHE_ENTRY* entry)\r\n{\r\n\tPERSISTENT_CACHE_ENTRY_V2 entry2 = WINPR_C_ARRAY_INIT;\r\n\r\n\tWINPR_ASSERT(persistent);\r\n\tWINPR_ASSERT(entry);\r\n\r\n\tif (fread(&entry2, sizeof(entry2), 1, persistent->fp) != 1)\r\n\t\treturn -1;\r\n\r\n\tentry->key64 = entry2.key64;\r\n\tentry->width = entry2.width;\r\n\tentry->height = entry2.height;\r\n\tentry->flags = entry2.flags;\r\n\r\n\tif (!persist_cache_get_data(persistent, entry))\r\n\t\treturn -1;\r\n\r\n\tif (fread(entry->data, 0x4000, 1, persistent->fp) != 1)\r\n\t\treturn -1;\r\n\r\n\treturn 1;\r\n}\r\n\r\nAn attacker can construct a malicious v2 persistent cache file with oversized width and height fields to trigger this integer wraparound. The mismatch between actual allocated buffer capacity and entry->size, paired with hard‑coded 16‑KiB read / fseek operations, corrupts parsing state and triggers heap‑based out‑of‑bounds access.\r\nReferences:\r\nPoC repository: https://github.com/programmervuln/freerdp-persistent-cache-v2-heapoverflow \r\nSource file: [https://github.com/FreeRDP/FreeRDP/blob/master/libfreerdp/cache/persistent.c\r\nPoC\r\nBuild FreeRDP 3.31.1 from source with ASAN (‑fsanitize=address) enabled to capture crash traces.\r\nCompile gen_poc_v2.c from the PoC repository to generate malicious persistent cache v2 file.\r\nConfigure FreeRDP client to load this malicious cache file.\r\nLaunch FreeRDP client to trigger persistent‑cache parsing logic. ASAN will report heap‑memory corruption crash inside the persistent‑cache parsing code path.\r\nFull ASAN crash backtrace can be provided upon maintainer request.\r\nImpact\r\nVulnerability class: CWE‑122 Heap‑based Buffer Overflow\r\nSuccessful exploitation causes heap memory corruption, application denial‑of‑service, and theoretically potential arbitrary code execution within FreeRDP client process.\r\nAttack prerequisite: Local user interaction; victim must load a malicious persistent cache v2 file.\r\nAffected component: libfreerdp/cache/persistent.c, persistent cache v2 parser.\r\nAffected version: FreeRDP 3.31.1. No patched version available at time of reporting.\r\nCVSS 3.1：CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H (7.8 High)","categories":["Unclassified"],"product":"FreeRDP","vendor":"","ecosystem":null,"affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-26cc-wjh8-hjw6","source_modified_at":"2026-10-01T11:13:39Z","fetched_at":"2026-10-23T21:14:28.314422Z","package":{"ecosystem":"c","name":"FreeRDP"},"range":"<= 3.31.1"}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-26cc-wjh8-hjw6","source_modified_at":"2026-10-01T11:13:39Z","fetched_at":"2026-10-23T21:14:28.314422Z","package":{"ecosystem":"c","name":"FreeRDP"},"version":"3.32.0"}],"cvss":null,"severity":"High","kev":{"listed":false},"epss":{"probability":null,"percentile":null,"score_date":null},"published_at":"2026-10-01T11:13:39Z","modified_at":"2026-10-01T11:13:39Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-26cc-wjh8-hjw6","fetched_at":"2026-10-23T21:14:28.314422Z","source_modified_at":"2026-10-01T11:13:39Z"}],"sources":["GitHub Advisory Database"],"references":[],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":null,"confidence":"unknown","reviewed":false},"change_timestamp":"2026-10-01T11:13:39Z","content_hash":"6f81a12a13a111f5f85ade0ae3571844257b0bc64bbf61a90ac90a848aea6ff6"}}
