Invalid memory access in GfxIndexedColorSpace::mapColorToBase( )
13 March, 2019
CVE Number
CVE-2019-9878
CWE
CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
Product Details
pdfalto is a command line executable for parsing PDF files and producing structured XML representations of the PDF content in ALTO format
URL: https://github.com/kermitt2/pdfalto
Vulnerable Versions
0.2
Vulnerability Details
During our research we discovered invalid memory access in function GfxIndexedColorSpace::mapColorToBase( ) located in GfxState.cc in pdfalto-0.2. 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
As per our research, we discovered that the vulnerability exists in function GfxIndexedColorSpace::mapColorToBase( ) at file GfxState.cc. The function GfxState::getFillRGB( ) invokes the function GfxIndexedColorSpace::getRGB() which constructs an index color space and calls the function GfxIndexedColorSpace::mapColorToBase( ) . When a crafted file is passed to the binary at this line of code baseColor->c[i] = dblToCol(low[i] + (p[i] / 255.0) * here p is an unsigned charecter pointer where memory cannot be accessed here p takes values of k and n where k=high index(maximum pixel value) where the vulnerability is being triggered as invalid memory access.
vulnerable Source code
for (i = 0; i c[i] = dblToCol(low[i] + (p[i] / 255.0) * range[i]); }
Analysis
DEBUG:
GDB :
Gdb: [ Legend: Modified register | Code | Heap | Stack | String ] ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ──── $rax : 0xfffffffffffffffd $rbx : 0x00000ffffffff9a6 → 0x0000000000000000 $rcx : 0xfffffffffffffffd $rdx : 0x200000007fff7fff $rsp : 0x00007fffffffccf0 → 0x00007fffffffcd30 → 0x0000000041b58ab3 $rbp : 0x00007fffffffcfd0 → 0x00007fffffffd100 → 0x00007fffffffd120 → 0x00007fffffffd2a0 → 0x00007fffffffd2d0 → 0x00007fffffffd330 → 0x00007fffffffd640 → 0x00007fffffffd750 $rsi : 0x3 $rdi : 0x0 $rip : 0x00000000005cd542 → movzx edx, BYTE PTR [rdx] $r8 : 0x00000000005cc2ea → push rbp $r9 : 0x7a1a $r10 : 0x0000602000073650 → 0xbebebebebebebe00 $r11 : 0x00007ffff7eec448 → 0x0000000000000000 $r12 : 0x00007fffffffcd30 → 0x0000000041b58ab3 $r13 : 0x00007fffffffcfb0 → 0x00000ffffffffa00 → 0x0000000000000000 $r14 : 0x00007fffffffcd30 → 0x0000000041b58ab3 $r15 : 0x00007fffffffd170 → 0x0000000041b58ab3 $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 ──── 0x00007fffffffccf0│+0x0000: 0x00007fffffffcd30 → 0x0000000041b58ab3 ← $rsp 0x00007fffffffccf8│+0x0008: 0x00007fffffffd020 → 0x0000003000000020 → 0x0000000000000000 0x00007fffffffcd00│+0x0010: 0x000061700000e108 → 0x00007fff00000000 0x00007fffffffcd08│+0x0018: 0x000060400000d050 → 0x00000000009688d0 → 0x00000000005cc590 → push rbp 0x00007fffffffcd10│+0x0020: 0x00000ffffffff9c4 → 0x0000000000000000 0x00007fffffffcd18│+0x0028: 0x0000000000000020 0x00007fffffffcd20│+0x0030: 0x00000003ffffffff → 0x0000000000000000 0x00007fffffffcd28│+0x0038: 0xfffffffffffffffd ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ──── 0x5cd533 enter 0x8948, 0xc2 0x5cd537 shr rdx, 0x3 0x5cd53b add rdx, 0x7fff8000 → 0x5cd542 movzx edx, BYTE PTR [rdx] 0x5cd545 test dl, dl 0x5cd547 setne sil 0x5cd54b mov rdi, rax 0x5cd54e and edi, 0x7 0x5cd551 cmp dil, dl ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:/home/aceteam/Downloads/sources/pdfalto/xpdf-4.00/xpdf/GfxState.cc+1149 ──── 1144 } else if (k > indexHigh) { 1145 k = indexHigh; 1146 } 1147 p = &lookup[k * n]; 1148 for (i = 0; i c[i] = dblToCol(low[i] + (p[i] / 255.0) * range[i]); 1150 } 1151 return baseColor; 1152 } 1153 1154 void GfxIndexedColorSpace::getGray(GfxColor *color, GfxGray *gray, ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ──── [#0] Id 1, Name: "pdfalto", stopped, reason: SIGSEGV ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ──── [#0] 0x5cd542 → GfxIndexedColorSpace::mapColorToBase(this=0x60400000d050, color=0x61700000e108, baseColor=0x7fffffffd020) [#1] 0x5cdaa4 → GfxIndexedColorSpace::getRGB(this=0x60400000d050, color=0x61700000e108, rgb=0x7fffffffd190, ri=gfxRenderingIntentRelativeColorimetric) [#2] 0x5f6b4f → GfxState::getFillRGB(this=0x61700000e080, rgb=0x7fffffffd190) [#3] 0x445f21 → XmlAltoOutputDev::fill(this=0x61500000f300, state=0x61700000e080) [#4] 0x6c4f54 → Gfx::opFill(this=0x60f00000e140, args=0x7fffffffd3d0, numArgs=0x0) [#5] 0x6bc95f → Gfx::execOp(this=0x60f00000e140, cmd=0x7fffffffd390, args=0x7fffffffd3d0, numArgs=0x0) [#6] 0x6bbf7a → Gfx::go(this=0x60f00000e140, topLevel=0x1) [#7] 0x6bb562 → Gfx::display(this=0x60f00000e140, objRef=0x60800000bed0, topLevel=0x1) [#8] 0x61cf67 → Page::displaySlice(this=0x60800000bea0, out=0x61500000f300, hDPI=72, vDPI=72, rotate=0x0, useMediaBox=0x0, crop=0x0, sliceX=0xffffffff, sliceY=0xffffffff, sliceW=0xffffffff, sliceH=0xffffffff, printing=0x0, abortCheckCbk=0x0, abortCheckCbkData=0x0) [#9] 0x61c7af → Page::display(this=0x60800000bea0, out=0x61500000f300, hDPI=72, vDPI=72, rotate=0x0, useMediaBox=0x0, crop=0x1, printing=0x0, abortCheckCbk=0x0, abortCheckCbkData=0x0) gef➤ p/d k * n $24 = -3 gef➤ p &lookup[k * n] $25 = (Guchar *) 0xfffffffffffffffd gef➤ p (p[i] / 255.0) Cannot access memory at address 0xfffffffffffffffd
Proof of Concept
./pdfalto -f 1 -l 2 -noText -noImage -outline -annotation -cutPages -blocks -readingOrder -ocr -fullFontName $POC
Vendor Disclosure: 2019-3-13
Public Disclosure: 2019-3-20
Credit
Discovered by ACE Team – Loginsoft