Talos Vulnerability Report

TALOS-2019-0945

LEADTOOLS JPEG2000 Isot parsing Memory Corruption Vulnerability

December 10, 2019
CVE Number

CVE-2019-5154

Summary

An exploitable heap overflow vulnerability exists in the JPEG2000 parsing functionality of LEADTOOLS 20.0.2019.3.15. A specially crafted J2K image file can cause an out of bounds write of a null byte in a heap buffer, potentially resulting in code execution. An attack can specially craft a J2K 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-122: Heap-based Buffer Overflow

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:

Mapped memory image file: C:\LEADTOOLS 20\Bin\CDLL\win32\lfJ2kU.DLL
Image path: C:\LEADTOOLS 20\Bin\CDLL\win32\lfJ2kU.DLL
Image name: lfJ2kU.DLL
Browse all global symbols  functions  data
Timestamp:        Fri Mar  1 07:35:20 2019 (5C795138)
CheckSum:         00058242
ImageSize:        0005D000
File version:     20.0.0.4
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

The JPEG2000 file format contains a number of different headers for various parts of the image. The jp2c header is used for designating a continuous codestream. This codestream has its own set of markers for storing the information in the codestream. The marker containing an image and tile size is 0xFF51. A description of the structure of this marker is below:

Parameter Size (bits) Values
SIZ       16          0xFF51
Lsiz      16          4-49 191
Rsiz      16          NA
Xsiz      32          1 - (23**2 - 1)
Ysiz      32          1 - (23**2 - 1)
XOsiz     32          0 - (23**2 - 2)
YOsiz     32          0 - (23**2 - 2)
XTsiz     32          1 - (23**2 - 1)
YTsiz     32          1 - (23**2 - 1)
XTOsiz    32          0 - (23**2 - 2)
YTOsiz    32          0 - (23**2 - 2)
Csiz      16          1 - 16 384
Ssiz(i)   8           NA
XRsiz(i)  8           1 - 255
YRsiz(i)  8           1 - 255

When determining the size of the buffer for this image, LEADTOOLS performs the following calculation and allocates a buffer for the structure of the image:

buffer_size = ((Xsiz / XTsiz + 1) * (Ysiz / YTsiz + 1)) * 4

Another codestream marker available in JPEG2000 is SOT, start of tile-part. This marker marks the beginning of a tile-part. Its structure is found below:

Parameter Size (bits) Values
SOT       16          0xFF90
Lsot      16          10
Isot      16          0 - 65535
Psot      32          0 - (2**32 - 1)
TPsot     8           0 - 255
TNsot     8           0 - 255

One particular field in the SOT is the Isot, which contains the number of tiles. When parsing the SOT, the buffer allocated from the SIZ parsing is referenced by the Isot value. The buffer containing the image structure information is indexed by the Isot value.

lfj2ku+0xa1b3
.text:0000A1B3                 mov     ecx, [edi]
.text:0000A1B5                 mov     ebx, [ebp+var_18] ; Isot value from file
.text:0000A1B8                 mov     [ebp+var_28], eax
.text:0000A1BB                 mov     [ebp+var_34], ecx
.text:0000A1BE                 mov     eax, [ecx+0B0h]   ; Buffer allocated from SIZ
.text:0000A1C4                 mov     ebx, [eax+ebx*4]  ; Value read from indexed buffer

Assuming the read from the buffer is a pointer (and isn't -1), the assumed structure offset of 0xA7 is checked to be null. If the value is not null, a null is written in its place.

lfj2ku+0xa251
.text:0000A251                 cmp     byte ptr [ebx+0A7h], 0 ; ebx - buffer
.text:0000A258                 jz      short loc_A27A

lfj2ku+0xa25a
.text:0000A25A                 mov     ecx, [ebp+var_14]
.text:0000A25D                 mov     edx, ebx               ; edx - buffer
.text:0000A25F                 call    sub_9230

...
lfj2ku+0x923b
.text:0000923B                 mov     esi, edx
.text:0000923D                 mov     [esp+14h+var_4], ecx
.text:00009241                 push    edi
.text:00009242                 mov     edi, 1
.text:00009247                 mov     [esp+18h+var_8], edi
.text:0000924B                 mov     eax, [esi]
.text:0000924D                 mov     byte ptr [esi+0A7h], 0 ; esi - buffer

If the heap has been aligned correctly, it is possible for an attacker set the values of the above calculations to write an arbitrary null out of bounds, potentially leading to code execution.

Timeline

2019-10-31 - Vendor disclosure
2019-11-06 - Vendor provided timeline for patch
2019-12-05 - Vendor patched
2019-12-10 - Public disclosure

Credit

Discovered by Cory Duplantis of Cisco Talos.