Headline
CVE-2019-5100: TALOS-2019-0892 || Cisco Talos Intelligence Group
An exploitable integer overflow vulnerability exists in the BMP header parsing functionality of LEADTOOLS 20. A specially crafted BMP image file can cause an integer overflow, potentially resulting in code execution. An attacker can specially craft a BMP image to trigger this vulnerability.
Summary
An exploitable integer overflow vulnerability exists in the BMP header parsing functionality of LEADTOOLS 20. A specially crafted BMP image file can cause an integer overflow, potentially resulting in code execution. An attacker can specially craft a BMP image to trigger this vulnerability.
Tested Versions
LEADTOOLS 20.0.2019.3.15
Product URLs
https://www.leadtools.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-190: Integer Overflow or Wraparound
Details
LEADTOOLS, according to the website, “is a collection of comprehensive toolkits to integrate document, medical, multimedia, and imaging technologies into desktop, server, tablet, and mobile applications”. It offers prebuilt and portable libraries with an SDK for most platforms (Windows, Linux, Android, etc), that are all geared towards building applications for medical systems.
The module used for this analysis is below:
Loaded symbol image file: lfBmpX.DLL
Mapped memory image file: C:\LEADTOOLS 20\Bin\CDLL\x64\lfBmpX.DLL
Image path: C:\LEADTOOLS 20\Bin\CDLL\x64\lfBmpX.DLL
Image name: lfBmpX.DLL
Browse all global symbols functions data
Timestamp: Thu Feb 21 13:22:56 2019 (5C6EFA90)
CheckSum: 0001C9A0
ImageSize: 00014000
File version: 20.0.0.1
Product version: 20.0.0.0
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04e4
LEADTOOLS begins parsing BMP files by checking if the two signature bytes are AM or BM.
lfbmpx+2745
.text:0000000000002745 lea rdx, [rsp+550h+var_508]
.text:000000000000274A mov r8d, 2
.text:0000000000002750 mov rcx, rax
.text:0000000000002753 mov [rsp+550h+arg_10], r12
.text:000000000000275B call cs:L_RedirectedRead
.text:0000000000002761 cmp eax, 2
.text:0000000000002764 jnz loc_30B8
.text:000000000000276A movzx eax, [rsp+550h+var_508]
.text:000000000000276F mov r12d, 'MB' ; Possible signature bytes
.text:0000000000002775 mov ebx, 'AB' ; Possible signature bytes
.text:000000000000277A cmp ax, r12w
.text:000000000000277E jz short loc_278E
.text:0000000000002780 cmp ax, bx
.text:0000000000002783 jz short loc_278E
.text:0000000000002785 test ax, ax
.text:0000000000002788 jnz loc_30B8
Assuming the file has the correct signature, the parser proceeds to read the BITMAPINFOHEADER, which includes the biWidth field.
lfbmpx+28fb
.text:00000000000028FB lea rdx, [rsp+550h+var_4F0]
.text:0000000000002900 mov r8d, 28h
.text:0000000000002906 mov rcx, rdi
.text:0000000000002909 call cs:L_RedirectedRead ; Internal read
.text:000000000000290F cmp eax, 28h
.text:0000000000002912 jnz loc_2E8E
.text:0000000000002918 cmp dword ptr [rsp+550h+var_4F0], eax
.text:000000000000291C jnz loc_2E8E
.text:0000000000002922 mov r8d, dword ptr [rsp+550h+var_4F0+4]
.text:0000000000002927 movzx r15d, word ptr [rsp+550h+var_4E8+6]
.text:000000000000292D mov [rbp+450h+var_4C8], eax
.text:0000000000002930 mov eax, dword ptr [rsp+550h+var_4E8]
.text:0000000000002934 mov [rsp+550h+biWidth_], r8d ; biWidth field saved locally
In preparation for copying file data, the parser allocates a buffer four times the provided biWidth value.
lfbmpx+1f85
.text:0000000000001F85 mov edx, r12d
.text:0000000000001F88 mov [rbp+37h+var_98], eax
.text:0000000000001F8B lea eax, [rbx*4] ; biWidth
.text:0000000000001F92 mov r8d, 2E4h
.text:0000000000001F98 movsxd rcx, eax
.text:0000000000001F9B call cs:L_LocalAlloc
To determine how many bytes to copy into this buffer, the biSize field from the BITMAPINFOHEADER is used.
lfbmpx+1ebe
.text:0000000000001EBE biSize_is_8:
.text:0000000000001EBE lea eax, [rdx+3] ; rdx -> biWidth
.text:0000000000001EC1 mov r8d, edx
.text:0000000000001EC4 and eax, 0FFFFFFFCh
.text:0000000000001EC7 retn
.text:0000000000001EC8 biSize_is_16:
.text:0000000000001EC8 lea r8d, [rdx+rdx] ; rdx -> biWidth
.text:0000000000001ECC lea eax, [r8+3]
.text:0000000000001ED0 and eax, 0FFFFFFFCh
.text:0000000000001ED3 retn
.text:0000000000001ED4 biSize_is_24:
.text:0000000000001ED4 lea r8d, [rdx+rdx*2] ; rdx -> biWidth
.text:0000000000001ED8 lea eax, [r8+3]
.text:0000000000001EDC and eax, 0FFFFFFFCh
.text:0000000000001EDF retn
The allocated buffer is then populated with memmove using the calculated value from the biSize switch statement above.
lfbmpx+20c5
.text:00000000000020C5 mov eax, r13d
.text:00000000000020C8 mov r12d, esi
.text:00000000000020CB movsxd rdx, edi
.text:00000000000020CE sub eax, edi
.text:00000000000020D0 mov rcx, r14 ; Dst
.text:00000000000020D3 cmp eax, esi
.text:00000000000020D5 cmovb r12d, eax
.text:00000000000020D9 add rdx, r15 ; Src
.text:00000000000020DC mov r8d, r12d ; Size
.text:00000000000020DF mov ebx, r12d
.text:00000000000020E2 call memmove
It is possible for a BMP file to have a biWidth value that will be overflown when multiplied to allocate the buffer to hold image data. Because this buffer is too small, the memmove will cause an out of bounds write, resulting in a buffer overflow, potentially resulting in code execution.
Crash Information
rax=ddd8ddc5dddddddd rbx=000000000000139c rcx=000001d35c0b1010
rdx=000000000a411410 rsi=00000000c0000008 rdi=0000000000000000
rip=00007ffd858aa632 rsp=00000012396ef978 rbp=00000012396efa29
r8=000000000000139c r9=000000000000009b r10=dddddddddddddddd
r11=000001d35c0b0ff0 r12=000000000000139c r13=000000000000139c
r14=000001d35c0b0ff0 r15=000001d3664c2400
iopl=0 nv up ei pl nz na pe nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
lfBmpX!LEAD_Load+0x4652:
00007ffd`858aa632 488941f0 mov qword ptr [rcx-10h],rax ds:000001d3`5c0b1000=????????????????
> !analyze -v
FAILURE_EXCEPTION_CODE: c0000005
FAILURE_IMAGE_NAME: lfBmpX.DLL
BUCKET_ID_IMAGE_STR: lfBmpX.DLL
FAILURE_MODULE_NAME: lfBmpX
BUCKET_ID_MODULE_STR: lfBmpX
FAILURE_FUNCTION_NAME: LEAD_Load
BUCKET_ID_FUNCTION_STR: LEAD_Load
BUCKET_ID_OFFSET: 4652
BUCKET_ID_MODTIMEDATESTAMP: 5c6efa90
BUCKET_ID_MODCHECKSUM: 1c9a0
BUCKET_ID_MODVER_STR: 20.0.0.1
BUCKET_ID_PREFIX_STR: APPLICATION_FAULT_INVALID_POINTER_WRITE_AVRF_
FAILURE_PROBLEM_CLASS: APPLICATION_FAULT
FAILURE_SYMBOL_NAME: lfBmpX.DLL!LEAD_Load
Timeline
2019-08-11 - Vendor Disclosure
2019-11-03 - Vendor patched
2019-11-05 - Public Release
Discovered by Cory Duplantis of Cisco Talos.