Ce mail provient de l'extérieur, restons vigilants ===================================================================== CERT-Renater Note d'Information No. 2025/VULN836 _____________________________________________________________________ DATE : 04/12/2025 HARDWARE PLATFORM(S): / OPERATING SYSTEM(S): Systems running libpng versions prior to 1.6.52. ===================================================================== https://github.com/pnggroup/libpng/security/advisories/GHSA-9mpm-9pxh-mg4f _____________________________________________________________________ Out-of-bounds read in `png_image_read_composite` High ctruta published GHSA-9mpm-9pxh-mg4f Dec 3, 2025 Package libpng Affected versions >= 1.6.0, < 1.6.52 Patched versions 1.6.52 Description Summary An out-of-bounds read vulnerability in libpng's simplified API allows reading up to 1012 bytes beyond the png_sRGB_base[512] array when processing palette PNG images with partial transparency and gamma correction. Important: The PNG files that trigger this vulnerability are valid per the PNG specification. No malicious crafting is required. The bug is in libpng's internal state management, not in the image data. Any legitimate PNG meeting the trigger conditions will cause the out-of-bounds read. Trigger Conditions All of the following conditions must be met: Palette image (IHDR color type 3) Partial transparency via tRNS chunk with alpha values between 1 and 254 (not just 0 or 255) Gamma correction via gAMA chunk with non-1.0 gamma value Simplified API used (png_image_begin_read_from_* and png_image_finish_read) Output format without alpha (e.g., PNG_FORMAT_RGB) No explicit background color (background = NULL in png_image_finish_read) These are all common, legitimate properties of real-world PNG files. Root Cause The function png_image_read_composite assumes pixel data has been premultiplied by png_do_compose, producing linear values where component <= alpha always holds. This invariant is violated for palette images with gamma correction due to a flag synchronization bug. The Invariant Violation Location: pngrtran.c:1845 in png_init_read_transformations For palette images with gamma correction, libpng performs composition directly on the palette entries (lines 1773-1836), then clears the PNG_COMPOSE flag to prevent re-composition: /* Prevent the transformations being done again. */ png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); The bug: This clears PNG_COMPOSE but does not clear PNG_FLAG_OPTIMIZE_ALPHA. The Resulting State After png_init_read_transformations for a palette+tRNS+gAMA image: PNG_COMPOSE = NO (cleared at line 1845) PNG_FLAG_OPTIMIZE_ALPHA = YES (still set from png_set_alpha_mode_fixed) How This Causes the Overflow When the simplified API calls png_image_read_composite: It checks PNG_FLAG_OPTIMIZE_ALPHA and sees YES. It assumes pixel data is linear premultiplied (where component <= alpha). But png_do_compose never ran (PNG_COMPOSE was cleared). The palette was premultiplied but converted back to sRGB via gamma_from_1. Expanded pixels are sRGB, not linear; component values can exceed alpha. The formula computes an out-of-range index: component *= 257*255; /* =65535 */ component += (255-alpha)*png_sRGB_table[outrow[c]]; component = PNG_sRGB_FROM_LINEAR(component); /* OOB read here */ Mathematical Analysis The formula in png_image_read_composite assumes linear premultiplied data where component <= alpha. Under this assumption: Maximum: alpha * 65535 + (255-alpha) * 65535 = 255 * 65535 = 16711425 Index: 16711425 >> 15 = 509 Verdict: Valid index (array size is 512) However, PNG alpha is explicitly non-premultiplied per the PNG specification. When the data arrives as sRGB (due to the flag synchronization bug), component values can legitimately exceed alpha. For example, with component=249, alpha=242: Value: 249 * 65535 + (255-242) * 65535 = 262 * 65535 = 17170170 Index: 17170170 >> 15 = 524 Verdict: Invalid index, 12 entries (24 bytes) past buffer Worst case (component=255, alpha=1): Value: 255 * 65535 + 254 * 65535 = 509 * 65535 = 33357315 Index: 33357315 >> 15 = 1017 Verdict: Invalid index, 506 entries (1012 bytes) past buffer Impact Information disclosure: Reading adjacent global data (png_sRGB_delta[] and potentially other globals). Denial of service: Read extending up to 1012 bytes past array may access unmapped memory and crash. No attacker control required: Legitimate, non-malicious PNG files trigger this bug. Fix The fix consists of two commits: Commit 1 (788a624): Defensive Bounds Check Adds a clamp before PNG_sRGB_FROM_LINEAR to prevent OOB read: if (component > 255*65535) component = 255*65535; component = PNG_sRGB_FROM_LINEAR(component); Commit 2 (a05a48b): Flag Synchronization Fix Addresses the root cause by clearing PNG_FLAG_OPTIMIZE_ALPHA when PNG_COMPOSE is cleared for palette images: /* In png_init_read_transformations (pngrtran.c) */ png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; /* Added */ And using the appropriate composition formula based on the flag state. Mitigation Upgrade to libpng 1.6.52 or later. If immediate upgrade is not possible: Provide an explicit background color to png_image_finish_read (uses different code path). Use the low-level API instead of simplified API. Request alpha-preserving output (e.g., PNG_FORMAT_RGBA) to avoid composition path. Related Vulnerabilities This is distinct from CVE-2025-64720 (fixed in libpng 1.6.51), which also involved PNG_sRGB_FROM_LINEAR but occurred in png_init_read_transformations during palette premultiplication. Both vulnerabilities stem from the complexity of the alpha optimization code paths and the PNG_FLAG_OPTIMIZE_ALPHA flag. Severity High 7.1/ 10 CVSS v3 base metrics Attack vector Network Attack complexity Low Privileges required None User interaction Required Scope Unchanged Confidentiality Low Integrity None Availability High CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:H CVE ID CVE-2025-66293 Weaknesses Weakness CWE-125 Credits @flyfish101 flyfish101 Reporter ========================================================= + CERT-RENATER | tel : 01-53-94-20-44 + + 23/25 Rue Daviel | fax : 01-53-94-20-41 + + 75013 Paris | email:cert@support.renater.fr + =========================================================