Talos Vulnerability Report

TALOS-2019-0880

Investintech Able2Extract Professional BMP decoding biClrUsed code execution vulnerability

November 4, 2019
CVE Number

CVE-2019-5088

Summary

An exploitable memory corruption vulnerability exists in Investintech Able2Extract Professional. A specially crafted BMP file can cause an out-of-bounds memory write, allowing a potential attacker to execute arbitrary code on the victim machine. Can trigger this vulnerability by sending the user a specially crafted BMP file.

Tested Versions

Investintech Able2Extract Professional 14.0.7 x64

Product URLs

https://www.investintech.com

CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-787: Out-of-bounds Write

Details

Able2Extract Professional 14 is a cross-platform PDF tool for Windows, Mac and Linux. It is a PDF converter, creator and editor that lets users create secure PDFs, sign PDFs, edit PDF paragraph text, add images, insert bates numbering, add blank PDF pages, annotate or redact PDFs, and more.

A specially crafted BMP file opened by Able2Extract can cause out-of-bounds memory write (memory corruption). Vulnerable code is provided below:

.text:000000000005347F                 mov     eax, 4
.text:0000000000053484                 mul     rcx
.text:0000000000053487                 mov     rdi, 0FFFFFFFFFFFFFFFFh
.text:000000000005348E                 cmovo   rax, rdi
.text:0000000000053492                 mov     rcx, rax             ; Size
.text:0000000000053495                 call    malloc_mem           ; allocate memory
.text:000000000005349A                 mov     r15, rax
.text:000000000005349D                 mov     [rsp+1C0h+var_170], rax
.text:00000000000534A2                 mov     r8d, [rbx+2Eh]       ; biClrUsed (straight from BITMAP HEADER)
.text:00000000000534A6                 shl     r8, 2                ; r8 = r8d << 2 (size for read operation)
.text:00000000000534AA                 mov     rdx, rax
.text:00000000000534AD                 lea     rcx, [rsp+1C0h+var_160]
.text:00000000000534B2                 call    cs:?read@?$basic_istream@DU?$char_traits@D@std@@@std@@QEAAAEAV12@PEAD_J@Z ; std::basic_istream<char,std::char_traits<char>>::read(char *,__int64)

The size for the read operation is calculated from biClrUsed (straight from the BITMAP HEADER field) despite the fact that the size for the malloc operation executed before is static. This leads to heap memory corruption due to lack of bounds check of the allocated memory block size.

0:008> !heap -s -v
Failed to read heap keySEGMENT HEAP ERROR: failed to initialize the extention
NtGlobalFlag enables following debugging aids for new heaps:
    tail checking
    free checking
    validate parameters
LFH Key                   : 0x919b04ca3ddbb1e6
Termination on corruption : ENABLED
          Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                            (k)     (k)    (k)     (k) length      blocks cont. heap 
-------------------------------------------------------------------------------------
.List corrupted: (Flink->Blink = 0000000000000000) != (Block = 000002143b5742f0)
HEAP 000002143b490000 (Seg 000002143b490000) At 000002143b5742e0 Error: block list entry corrupted

......List corrupted: (Blink->Flink = 0000000000000000) != (Block = 000002144444cec0)
HEAP 000002143b490000 (Seg 0000021444260000) At 000002144444ceb0 Error: block list entry corrupted

HEAP 000002143b490000 (Seg 0000021444260000) At 0000021444458b80 Error: invalid block size

000002143b490000 40000062   48740  35032  48740    758 12174     7    3    2cb      
.000002143b240000 40008060      64      4     64      2     1     1    0      0      
..000002143b480000 40001062    1080    244   1080    124     4     2    0      0      
.000002143b440000 40001062      60     20     60      1     8     1    0      0      
..000002143cef0000 40001062    1080    724   1080      4    40     2    0      0      

Crash Information

0:008> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for Able2ExtractPro.exe - 
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for J:\fuzz_software\able_pdf\Qt5Core.dll - 
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for J:\fuzz_software\able_pdf\platforms\qwindows.dll - 
GetUrlPageData2 (WinHttp) failed: 12002.

DUMP_CLASS: 2

DUMP_QUALIFIER: 0

FAULTING_IP: 
ntdll!RtlReportCriticalFailure+56
00007ffd`259b91f2 cc              int     3

EXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 00007ffd259b91f2 (ntdll!RtlReportCriticalFailure+0x0000000000000056)
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 1
   Parameter[0]: 0000000000000000

FAULTING_THREAD:  00003844

BUGCHECK_STR:  HEAP_CORRUPTION

DEFAULT_BUCKET_ID:  HEAP_CORRUPTION

PROCESS_NAME:  Able2ExtractPro.exe

ERROR_CODE: (NTSTATUS) 0x80000003 - {EXCEPTION}  Breakpoint  A breakpoint has been reached.

EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - One or more arguments are invalid

EXCEPTION_CODE_STR:  80000003

EXCEPTION_PARAMETER1:  0000000000000000

WATSON_BKT_PROCSTAMP:  5c2fb034

WATSON_BKT_PROCVER:  14.0.7.0

PROCESS_VER_PRODUCT:  Able2Extract Professional

WATSON_BKT_MODULE:  ntdll.dll

WATSON_BKT_MODSTAMP:  c5943461

WATSON_BKT_MODOFFSET:  f91f2

WATSON_BKT_MODVER:  10.0.18362.207

MODULE_VER_PRODUCT:  Microsoft Windows Operating System

BUILD_VERSION_STRING:  10.0.18362.86 (WinBuild.160101.0800)

MODLIST_WITH_TSCHKSUM_HASH:  70b751afc6753ba89a66cd6b207e538ba0dc1cf7

MODLIST_SHA1_HASH:  bb49bcb3f54dd66c735ff21f675f26c969ae1c41

NTGLOBALFLAG:  70

PROCESS_BAM_CURRENT_THROTTLED: 0

PROCESS_BAM_PREVIOUS_THROTTLED: 0

APPLICATION_VERIFIER_FLAGS:  0

PRODUCT_TYPE:  1

SUITE_MASK:  272

DUMP_TYPE:  fe

ANALYSIS_SESSION_HOST:  CLAB

ANALYSIS_SESSION_TIME:  07-18-2019 12:35:33.0180

ANALYSIS_VERSION: 10.0.16299.15 amd64fre

THREAD_ATTRIBUTES: 
ADDITIONAL_DEBUG_TEXT:  Enable Pageheap/AutoVerifer ; Followup set based on attribute [Is_ChosenCrashFollowupThread] from Frame:[0] on thread:[PSEUDO_THREAD]

THREAD_SHA1_HASH_MOD_FUNC:  9d18e30de9833362035ae9d4b61ffd9614e7b704

THREAD_SHA1_HASH_MOD_FUNC_OFFSET:  10dd5a75075420a26839939bfe61462c6a6dd8b8

OS_LOCALE:  ENU

PROBLEM_CLASSES: 

    ID:     [0n250]
    Type:   [HEAP_CORRUPTION]
    Class:  Primary
    Scope:  DEFAULT_BUCKET_ID (Failure Bucket ID prefix)
            BUCKET_ID
    Name:   Add
    Data:   Omit
    PID:    [0xd54]
    TID:    [0x3844]
    Frame:  [5] : ntdll!RtlpAllocateHeap

    ID:     [0n250]
    Type:   [HEAP_CORRUPTION]
    Class:  Primary
    Scope:  BUCKET_ID
    Name:   Add
    Data:   Omit
    PID:    [0xd54]
    TID:    [0x3844]
    Frame:  [5] : ntdll!RtlpAllocateHeap

PRIMARY_PROBLEM_CLASS:  HEAP_CORRUPTION

LAST_CONTROL_TRANSFER:  from 00007ffd259c1622 to 00007ffd259b91f2

STACK_TEXT:  
00000000`00000000 00000000`00000000 heap_corruption!Able2ExtractPro.exe+0x0


THREAD_SHA1_HASH_MOD:  ca4e26064d24ef7512d2e94de5a93c38dbe82fe9

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  heap_corruption!Able2ExtractPro.exe

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: heap_corruption

IMAGE_NAME:  heap_corruption

DEBUG_FLR_IMAGE_TIMESTAMP:  0

STACK_COMMAND:  ** Pseudo Context ** ManagedPseudo ** Value: 20afbe51f90 ** ; kb

BUCKET_ID:  HEAP_CORRUPTION_heap_corruption!Able2ExtractPro.exe

FAILURE_EXCEPTION_CODE:  80000003

FAILURE_IMAGE_NAME:  heap_corruption

BUCKET_ID_IMAGE_STR:  heap_corruption

FAILURE_MODULE_NAME:  heap_corruption

BUCKET_ID_MODULE_STR:  heap_corruption

FAILURE_FUNCTION_NAME:  Able2ExtractPro.exe

BUCKET_ID_FUNCTION_STR:  Able2ExtractPro.exe

BUCKET_ID_OFFSET:  0

BUCKET_ID_MODTIMEDATESTAMP:  0

BUCKET_ID_MODCHECKSUM:  0

BUCKET_ID_MODVER_STR:  0.0.0.0

BUCKET_ID_PREFIX_STR:  

FAILURE_PROBLEM_CLASS:  HEAP_CORRUPTION

FAILURE_SYMBOL_NAME:  heap_corruption!Able2ExtractPro.exe

FAILURE_BUCKET_ID:  HEAP_CORRUPTION_80000003_heap_corruption!Able2ExtractPro.exe

WATSON_STAGEONE_URL:  http://watson.microsoft.com/StageOne/Able2ExtractPro.exe/14.0.7.0/5c2fb034/ntdll.dll/10.0.18362.207/c5943461/80000003/000f91f2.htm?Retriage=1

TARGET_TIME:  2019-07-18T10:36:24.000Z

OSBUILD:  18362

OSSERVICEPACK:  86

SERVICEPACK_NUMBER: 0

OS_REVISION: 0

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

OSEDITION:  Windows 10 WinNt SingleUserTS

USER_LCID:  0

OSBUILD_TIMESTAMP:  unknown_date

BUILDDATESTAMP_STR:  160101.0800

BUILDLAB_STR:  WinBuild

BUILDOSVER_STR:  10.0.18362.86

ANALYSIS_SESSION_ELAPSED_TIME:  11bce

ANALYSIS_SOURCE:  UM

FAILURE_ID_HASH_STRING:  um:heap_corruption_80000003_heap_corruption!able2extractpro.exe

FAILURE_ID_HASH:  {5d0a1a6f-8749-cb8d-ccc6-e10cd71d1064}

Followup:     MachineOwner
---------

0:008> g
(d54.3844): Unknown exception - code c0000374 (first chance)
(d54.3844): Unknown exception - code c0000374 (!!! second chance !!!)
ntdll!RtlReportFatalFailure+0x9:
00007ffd`259b9269 eb00            jmp     ntdll!RtlReportFatalFailure+0xb (00007ffd`259b926b)
0:008> g
WARNING: Continuing a non-continuable exception
(d54.3844): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll!RtlpAllocateHeap+0x28e:
00007ffd`258fd10e 498b0424        mov     rax,qword ptr [r12] ds:013332f6`30033333=????????????????

Timeline

2019-08-01 - Initial Contact
2019-08-06 - Plain text file issued; Vendor confirmed
2019-09-23 - 30+ day follow up; Vendor acknowledged issue under review
2019-10-15 - 60+ day follow up
2019-11-01 - Vendor patched
2019-11-03 - Public Release

Credit

Discovered by Piotr Bania of Cisco Talos.