Skip to content

Latest commit

 

History

History
128 lines (87 loc) · 4.84 KB

File metadata and controls

128 lines (87 loc) · 4.84 KB

CVE-2025-66970

Stack Overflow Vulnerability in Poppler PDF Library

Description

A stack overflow vulnerability exists in Poppler PDF library versions 25.03.0 through 25.11.0 in the roleMapResolve() function. The vulnerability allows for denial of service and potential code execution through maliciously crafted PDF files containing deeply nested RoleMap chains.

Vulnerability Details

CVE ID: CVE-2025-66970

Product: Poppler PDF Library

Vendor: freedesktop.org (Poppler project)

Affected Versions: 25.03.0 to 25.11.0

Fixed Version: 25.11.1

Vulnerability Type: Stack Overflow via Unbounded Recursion

Component: poppler/StructElement.cc

Function: StructElement::roleMapResolve()

Lines: 880-897

Technical Analysis

Root Cause

The roleMapResolve() function recursively resolves RoleMap chains without implementing a depth counter (line 890). While the function checks for immediate self-references, it allows unlimited chains of role mappings, leading to stack exhaustion.

Vulnerable Code Pattern:

// Function recursively resolves RoleMap chains without depth limit
// Only checks immediate self-references (A -> A)
// Allows unlimited chains (A -> B -> C -> D -> ... -> Z -> A0 -> ...)

AddressSanitizer Detection

==195101==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc8676bfe8 
(pc 0x7fa32667e3e3 bp 0x7ffc8676c840 sp 0x7ffc8676bff0 T0)
    #0 0x7fa32667e3e3 in strlen ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:423
    #1 0x7fa325ca204e in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::compare(char const*) const /usr/include/c++/14/bits/basic_string.h:3397
    #2 0x7fa325d13028 in decltype ((__char_traits_cmp_cat<std::char_traits<char> >)(0)) std::operator<=><char, std::char_traits<char>, std::allocator<char> >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*) /usr/include/c++/14/bits/basic_string.h:3808
    #3 0x7fa325d14856 in decltype(auto) std::less<void>::_S_cmp<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const* const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const* const&, std::integral_constant<bool, false>) /usr/include/c++/14/bits/stl_function.h:605
    #4 0x7fa325d14896 in decltype (((forward<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>)({parm#1}))<((forward<char const* const&>)({parm#2}))) std::less<void>::operator()<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const* const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const* const&) const /usr/include/c++/14/bits/stl_function.h:590

Proof of Concept

Attack Vector

Craft a malicious PDF with tagged structure containing deeply nested /RoleMap chains:

/A0 → /A1 → /A2 → ... → /A50000

Delivery Methods

  • Email attachment
  • Web hosting
  • Document sharing platforms
  • Server-side upload

Trigger Conditions

  • Opening in Poppler-based applications (Evince, Okular, GIMP, LibreOffice)
  • Running pdfinfo -struct on the malicious PDF
  • Server-side PDF processing using Poppler library

Exploitation Complexity

LOW - The exploit works reliably with no special conditions needed

Impact

Severity: High

Attack Type: Context-dependent

Impacts:

  • Code Execution: Potential for arbitrary code execution through stack manipulation
  • Denial of Service: Crash through stack overflow
  • Escalation of Privileges: Possible privilege escalation in certain contexts
  • Information Disclosure: Potential memory disclosure through stack corruption

Mitigation

Recommended Fix

Add a depth parameter with MAX_DEPTH=100 limit to prevent unbounded recursion:

// Proposed fix
const int MAX_DEPTH = 100;

std::string roleMapResolve(const std::string& role, int depth = 0) {
    if (depth > MAX_DEPTH) {
        return role; // Return original role if depth exceeded
    }
    // Continue with existing logic, passing depth+1 to recursive calls
}

Workarounds

  • Update to Poppler 25.11.1 or later
  • Implement input validation for PDF files
  • Disable tagged PDF structure parsing if not required
  • Run Poppler-based applications in sandboxed environments

Timeline

  • Discovery Date: 2025
  • Vendor Notification: 2025
  • Fixed Version Released: 25.11.1
  • CVE Assigned: CVE-2025-66970

References

Credits

Discoverer: Shadowbyte

PGP Signature: SHA256