Invalid memory access in GAtomicCounter gAtomicIncrement( ) – xpdf-4.01
Loginsoft-2019-1102
26 February, 2019
CVE Number
CVE-2019-9588
CWE
CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
Product Details
Xpdf is a free PDF viewer and toolkit, including a text extractor, image converter, HTML converter, and more. Most of the tools are available as open source.
URL: https://www.xpdfreader.com/download.html
Vulnerable Versions
4.01
Vulnerability Details
During our research there is aInvalid memory access in GAtomicCounter gAtomicIncrement( ) located at GMutex.h in xpdf-4.01. The same be triggered by sending a crafted pdf file to the pdftops binary. It allows an attacker to cause Denial of Service (Segmentation fault) or possibly have unspecified other impact.
SYNOPSIS
In Progress
Vulnerable Source Code
static inline GAtomicCounter gAtomicIncrement(GAtomicCounter *counter) { GAtomicCounter newVal;
Analysis
DEBUG:
GDB:
[ Legend: Modified register | Code | Heap | Stack | String ] ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ──── $rax : 0x000060400000c5f0 → 0x0000000000015519 $rbx : 0x0000611000009c80 → 0x000060700000dfb0 → 0x000060200000fed0 → 0xbebebebe00000008 $rcx : 0x00007fffff7ff1b0 → 0x0000000000000007 $rdx : 0x000060400000c5d0 → 0x000061d00001cc80 → 0x000061300000de80 → 0x00000000005b1dc8 → 0x0000000000518dd8 → <FileStream::~FileStream()+0> push rbp $rsp : 0x00007fffff7ff000 → 0x000000000049d89c → <Dict::incRef()+28> leave $rbp : 0x00007fffff7ff010 → 0x00007fffff7ff030 → 0x00007fffff7ff0e0 → 0x00007fffff7ff110 → 0x00007fffff7ff140 → 0x00007fffff7ff170 → 0x00007fffff7ff1d0 → 0x00007fffff7ff230 $rsi : 0x00007fffff7ff1b0 → 0x0000000000000007 $rdi : 0x000060400000c5f0 → 0x0000000000015519 $rip : 0x000000000049d220 → <_ZL16gAtomicIncrementPl+0> push rbp $r8 : 0x000061d00001d4d8 → 0x0000000000000001 $r9 : 0x1aefa $r10 : 0x80 $r11 : 0x00007ffff7e41ef8 → 0x0000000000000000 $r12 : 0x000000000044ca40 → <_start+0> xor ebp, ebp $r13 : 0x00007fffffffde30 → 0x0000000000000012 $r14 : 0x0 $r15 : 0x0 $eflags: [carry PARITY adjust zero sign trap INTERRUPT direction overflow RESUME virtualx86 identification] $cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ──── 0x00007fffff7ff000│+0x0000: 0x000000000049d89c → <Dict::incRef()+28> leave ← $rsp 0x00007fffff7ff008│+0x0008: 0x000060400000c5d0 → 0x000061d00001cc80 → 0x000061300000de80 → 0x00000000005b1dc8 → 0x0000000000518dd8 → <FileStream::~FileStream()+0> push rbp 0x00007fffff7ff010│+0x0010: 0x00007fffff7ff030 → 0x00007fffff7ff0e0 → 0x00007fffff7ff110 → 0x00007fffff7ff140 → 0x00007fffff7ff170 → 0x00007fffff7ff1d0 → 0x00007fffff7ff230 ← $rbp 0x00007fffff7ff018│+0x0018: 0x000000000050953f → <Object::copy(Object*)+163> jmp 0x50958b <Object::copy(Object*)+239> 0x00007fffff7ff020│+0x0020: 0x00007fffff7ff1b0 → 0x0000000000000007 0x00007fffff7ff028│+0x0028: 0x000061d00001d360 → 0x0000000000000007 0x00007fffff7ff030│+0x0030: 0x00007fffff7ff0e0 → 0x00007fffff7ff110 → 0x00007fffff7ff140 → 0x00007fffff7ff170 → 0x00007fffff7ff1d0 → 0x00007fffff7ff230 → 0x00007fffff7ff290 0x00007fffff7ff038│+0x0038: 0x000000000053a6f8 → <XRef::fetch(int,+0> mov rax, QWORD PTR [rbp-0x88] ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ──── 0x49d21a <DecryptStream::getUndecodedStream()+8> mov rax, QWORD PTR [rbp-0x8] 0x49d21e <DecryptStream::getUndecodedStream()+12> pop rbp 0x49d21f <DecryptStream::getUndecodedStream()+13> ret → 0x49d220 <_ZL16gAtomicIncrementPl+0> push rbp 0x49d221 <_ZL16gAtomicIncrementPl+1> mov rbp, rsp 0x49d224 <_ZL16gAtomicIncrementPl+4> mov QWORD PTR [rbp-0x18], rdi 0x49d228 <_ZL16gAtomicIncrementPl+8> mov rdx, QWORD PTR [rbp-0x18] 0x49d22c <_ZL16gAtomicIncrementPl+12> mov eax, 0x1 0x49d231 <_ZL16gAtomicIncrementPl+17> lock xadd QWORD PTR [rdx], rax ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:/home/aceteam/Downloads/sources/xpdf-4.01/goo/GMutex.h+66 ──── 61 // NB: this must be "long" to work on Windows 62 typedef long GAtomicCounter; 63 64 // Increment *counter by one and return the final value (after the 65 // increment). // counter=0x00007fffff7fefe0 → 66 static inline GAtomicCounter gAtomicIncrement(GAtomicCounter *counter) { 67 GAtomicCounter newVal; 68 69 #if defined(_WIN32) 70 newVal = _InterlockedIncrement(counter); 71 #elif defined(__GNUC__) || defined(__xlC__) ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ──── [#0] Id 1, Name: "pdftops", stopped, reason: SIGSEGV ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ──── [!] Cannot access memory at address 0x7fffff7fefe0 gef➤ ptype counter type = long * gef➤ p/d 0x7fffff7fefe0 $2 = 140737479962592 gef➤ x *counter Cannot access memory at address 0x7fffff7fefe0
Proof of Concept
pdftops -f 2 -l 4 -level2 -noembt1 -preload -nocrop -noshrink -nocenter -pagecrop -userunit -duplex -upw rome $POC out.ps
POC FILE: REPRODUCER
Vendor Disclosure: 2019-2-26
Public Disclosure:
Credit
Discovered by ACE Team – Loginsoft