CVE-2019-9878: Invalid memory access in GfxIndexedColorSpace::mapColorToBase( ) -pdfalto-0.2

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