CVE-2019-9589: NULL POINTER DEREFERENCE Vulnerability in function PSOutputDev::setupResources( ) – xpdf-4.01

NULL POINTER DEREFERENCE Vulnerability in function PSOutputDev::setupResources( ) – xpdf-4.01

Loginsoft-2019-1103

27 February, 2019

CVE Number

CVE-2019-9589

CWE

CWE-476: NULL Pointer Dereference

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 a null pointer dereference vulnerability, in PSOutputDev::setupResources( ) located in PSOutputDev.cc 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
if ((gsDict.dictGetValNF(i, &gsRef)->isRef())) {
        ref0 = gsRef.getRef();
→    skip = (GBool)visitedResources[ref0.num];
        visitedResources[ref0.num] = 1;
            }
Analysis

DEBUG:
GDB:

[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0000602fa004e880  →  0x0000000000000000
$rbx   : 0x000060300004e820  →  0x000060705b800009  →  0x0000000000000000
$rcx   : 0x00007fffffffda30  →  0x000060f000000009  →  0x0000000000000000
$rdx   : 0x000060300004e880  →  0x0000000000000000
$rsp   : 0x00007fffffffd990  →  0x000060400000d3d0  →  0x000061d00001cc80  →  0x000061300000de80  →  0x00000000005b1dc8  →  0x0000000000518dd8  →   push rbp
$rbp   : 0x00007fffffffda90  →  0x00007fffffffdb40  →  0x00007fffffffdbe0  →  0x00007fffffffdc80  →  0x00007fffffffdd50  →  0x000000000058efd0  →   push r15
$rsi   : 0x00007fffffffda30  →  0x000060f000000009  →  0x0000000000000000
$rdi   : 0x00007fffffffda30  →  0x000060f000000009  →  0x0000000000000000
$rip   : 0x0000000000451b2d  →   movzx eax, BYTE PTR [rax]
$r8    : 0x0               
$r9    : 0x185d1           
$r10   : 0x58              
$r11   : 0x00007ffff7f1d820  →  0x0000000000000000
$r12   : 0x00007fffffffdaf0  →  0xbebebebe0000000d
$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 ────
0x00007fffffffd990│+0x0000: 0x000060400000d3d0  →  0x000061d00001cc80  →  0x000061300000de80  →  0x00000000005b1dc8  →  0x0000000000518dd8  →   push rbp     ← $rsp
0x00007fffffffd998│+0x0008: 0x0000616000002180  →  0x0000000000595a68  →  0x000000000044fa1e  →   push rbp
0x00007fffffffd9a0│+0x0010: 0x000060c000007840  →  0x000000004a000006
0x00007fffffffd9a8│+0x0018: 0x0000000000000000
0x00007fffffffd9b0│+0x0020: 0x00000000a0000000  →  0x0000000000000000
0x00007fffffffd9b8│+0x0028: 0x000000000050ee6f  →   add rsp, 0x30
0x00007fffffffd9c0│+0x0030: 0xffffffff0000000d
0x00007fffffffd9c8│+0x0038: 0x00007ffff5da9242  →   mov QWORD PTR [rbx+0x28], rax
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x451b21  add    BYTE PTR [rbx-0xdf7b], cl
     0x451b27  dec    DWORD PTR [rax-0x68]
     0x451b2a  add    rax, rdx
→   0x451b2d  movzx  eax, BYTE PTR [rax]
     0x451b30  movsx  eax, al
     0x451b33  mov    DWORD PTR [rbp-0xe8], eax
     0x451b39  mov    rax, QWORD PTR [rbp-0xf8]
     0x451b40  mov    rdx, QWORD PTR [rax+0x138]
     0x451b47  mov    eax, DWORD PTR [rbp-0xe0]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:/home/aceteam/Downloads/sources/xpdf-4.01/xpdf/PSOutputDev.cc+1991 ────
   1986     
   1987           // check for an already-visited ExtGState
   1988           skip = gFalse;
   1989           if ((gsDict.dictGetValNF(i, &gsRef)->isRef())) {
   1990         ref0 = gsRef.getRef();
→ 1991         skip = (GBool)visitedResources[ref0.num];
   1992         visitedResources[ref0.num] = 1;
   1993           }
   1994           if (!skip) {
   1995     
   1996         // process the ExtGState's SMask's transparency group's resource dict
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "pdftops", stopped, reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x451b2d → PSOutputDev::setupResources(this=0x616000002180, resDict=0x60400000d3d0)
[#1] 0x450cdc → PSOutputDev::writeDocSetup(this=0x616000002180, catalog=0x611000008880)
[#2] 0x44f990 → PSOutputDev::init(this=0x616000002180, outputFuncA=0x44eb56 , outputStreamA=0x616000001e80, fileTypeA=psFile, docA=0x60700000dfb0, firstPageA=0x2, lastPageA=0x4, modeA=psModePS, imgLLXA=0x0, imgLLYA=0x0, imgURXA=0x0, imgURYA=0x0, manualCtrlA=0x0, honorUserUnitA=0x1)
[#3] 0x44ee44 → PSOutputDev::PSOutputDev(this=0x616000002180, fileName=0x60200004e290 "out.ps", docA=0x60700000dfb0, firstPageA=0x2, lastPageA=0x4, modeA=psModePS, imgLLXA=0x0, imgLLYA=0x0, imgURXA=0x0, imgURYA=0x0, manualCtrlA=0x0, customCodeCbkA=0x0, customCodeCbkDataA=0x0, honorUserUnitA=0x1)
[#4] 0x47dbbc → main(argc=0x3, argv=0x7fffffffde38)


gef➤  ptype visitedResources
type = char *
gef➤  x visitedResources[0]
0x0:    Cannot access memory at address 0x0
 
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-27
Public Disclosure: 2019-3-6

Credit

Discovered by ACE Team – Loginsoft