CVE-2018-19532: Null pointer dereference vulnerability in PdfTranslator::setTarget() – podofo 0.9.6
Loginsoft-2018-1034
November 15, 2018
CVE Number
CVE-2018-19532
CWE
CWE-476: NULL Pointer Dereference
Product Details
PoDoFo is a library to work with the PDF file format.
URL: https://sourceforge.net/projects/podofo/
Vulnerable Versions
0.9.6-trunk r1949
Vulnerability Details
During our research on the podofo, a NULL pointer dereference vulnerability is discovered in the pdofo (0.9.6 – Trunk r1949) .The same is triggered by sending a crafted pdf file to the podofoimpose binary.It allows an attacker to cause Denial of Service (Segmentation fault) or possibly have an unspecified other impact.
SYNOPSIS
As per our research,the vulnerability exits in function PdfTranslator::setTarget()
in pdftranslator.cpp.
The pointer page,consists of pdf page details in it.
Gdb : gef➤ p page $53 = (PoDoFo::PdfPage *) 0x82a2d30 gef➤ p *page $56 = { = { _vptr.PdfElement = 0x822b4c0, m_pObject = 0x82a5f78 }, = { _vptr.PdfCanvas = 0x822b504 }, members of PoDoFo::PdfPage: m_pContents = 0x82a7870, m_pResources = 0x82a8870, m_mapAnnotations = std::map with 0 elements, m_mapAnnotationsDirect = std::map with 0 elements
In line PdfXObject *xobj = new PdfXObject (page->GetMediaBox(), targetDoc),
while storing the pdf objects in xobj,if a crafted pdf file is supplied to the binary,a NULL dereference issue is identified as the page pointer points to a non-existing address 0x0 .
Analysis
Source code : for (int i = 0; i GetPage ( i ); PdfMemoryOutputStream outMemStream ( 1 ); PdfXObject *xobj = new PdfXObject ( page->GetMediaBox(), targetDoc ); if ( page->GetContents()->HasStream() ) { page->GetContents()->GetStream()->GetFilteredCopy ( &outMemStream ); } GDB : 259 PdfXObject *xobj = new PdfXObject ( page->GetMediaBox(), targetDoc ); 1: page = (PoDoFo::PdfPage *) 0x0 [ Legend: Modified register | Code | Heap | Stack | String ] ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ──── $eax : 0x0 $ebx : 0x082a9de4 → 0x082aa7f0 → 0x08219b78 → 0x0813d594 → push ebp $ecx : 0x3 $edx : 0x082aaef0 → 0x00000000 $esp : 0xbffff470 → 0xb7bab000 → 0x00172664 $ebp : 0xbffff528 → 0xbffff568 → 0x00000000 $esi : 0xbffff4d8 → 0x00000000 $edi : 0xb7a16000 → 0x001b1db0 $eip : 0x0811bd62 → <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string mov eax, DWORD PTR [ebp-0x90] $eflags: [carry parity adjust zero SIGN trap INTERRUPT direction overflow resume virtualx86 IDENTIFICATION] $cs: 0x0073 $ss: 0x007b $ds: 0x007b $es: 0x007b $fs: 0x0000 $gs: 0x0033 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ──── 0xbffff470│+0x0000: 0xb7bab000 → 0x00172664 ← $esp 0xbffff474│+0x0004: 0xb7b08756 → <__gnu_cxx::stdio_sync_filebuf add ebx, 0xa28aa 0xbffff478│+0x0008: 0x08293b30 → 0x08293b38 → "test" 0xbffff47c│+0x000c: 0x082a1c48 → 0x082a1e10 → 0x0822aa54 → 0x081727a6 → push ebp 0xbffff480│+0x0010: 0x08293a40 → 0xb7ba9c68 → 0xb7b2d9e0 → <std::basic_ostream push ebx 0xbffff484│+0x0014: 0x082a9348 → 0x00000020 0xbffff488│+0x0018: 0x00000001 0xbffff48c│+0x001c: 0x00000001 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ──── 0x811bd59 <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string push eax 0x811bd5a <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string call 0x813fa66 0x811bd5f <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string add esp, 0x10 → 0x811bd62 <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string mov eax, DWORD PTR [ebp-0x90] 0x811bd68 <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string mov eax, DWORD PTR [eax] 0x811bd6a <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string add eax, 0x18 0x811bd6d <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string mov eax, DWORD PTR [eax] 0x811bd6f <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string lea edx, [ebp-0x50] 0x811bd72 <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string sub esp, 0x8 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:/home/loginsoft/podofo-code-r1949-podofo-trunk/tools/podofoimpose/pdftranslator.cpp+259 ──── 254 for ( int i = 0; i GetPage ( i ); 257 PdfMemoryOutputStream outMemStream ( 1 ); 258 // page=0xbffff498 → 0x00000000, xobj=0xbffff49c → [...] → push ebp → 259 PdfXObject *xobj = new PdfXObject ( page->GetMediaBox(), targetDoc ); 260 if ( page->GetContents()->HasStream() ) 261 { 262 page->GetContents()->GetStream()->GetFilteredCopy ( &outMemStream ); 263 } 264 else if ( page->GetContents()->IsArray() ) ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ──── [#0] Id 1, Name: "podofoimpose", stopped, reason: BREAKPOINT ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ──── [#0] 0x811bd62 → PoDoFo::Impose::PdfTranslator::setTarget(this=0x82a1c48, target="test") [#1] 0x8119af1 → main(argc=0x4, argv=0xbffff614) gef➤ p page $58 = (PoDoFo::PdfPage *) 0x0 gef➤ p *page Cannot access memory at address 0x0 gef➤ i r eax 0x0 0x0 ecx 0x3 0x3 edx 0x82aaef0 0x82aaef0 ebx 0x82a9de4 0x82a9de4 esp 0xbffff470 0xbffff470 ebp 0xbffff528 0xbffff528 esi 0xbffff4d8 0xbffff4d8 edi 0xb7a16000 0xb7a16000 eip 0x811bd62 0x811bd62 <PoDoFo::Impose::PdfTranslator::setTarget(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)+320> eflags 0x200282 [ SF IF ID ] cs 0x73 0x73 ss 0x7b 0x7b ds 0x7b 0x7b es 0x7b 0x7b fs 0x0 0x0 gs 0x33 0x33 gef➤ bt #0 0x0811bd68 in PoDoFo::Impose::PdfTranslator::setTarget (this=0x82a1c70, target="test.pdf") at /home/loginsoft/podofo-code-r1949-podofo-trunk/tools/podofoimpose/pdftranslator.cpp:259 #1 0x08119af1 in main (argc=0x4, argv=0xbffff604) at /home/loginsoft/podofo-code-r1949-podofo-trunk/tools/podofoimpose/podofoimpose.cpp:108
Proof of Concept
podofoimpose $POC outfile.pdf native
Timeline
Vendor Disclosure: 2018-11-15
Public Disclosure: 2018-11-20
Patch : https://sourceforge.net/p/podofo/code/1950
Credit
Discovered by ACE Team – Loginsoft