Talos Vulnerability Report

TALOS-2016-0196

Ichitaro Office JTD Figure handling Code Execution Vulnerability

February 24, 2017

CVE Number

CVE-2017-2789

Summary

A vulnerability was discovered within the Ichitaro word processor. Ichitaro is published by JustSystems and is considered one of the more popular word processors used within Japan. Ichitaro's proprietary file format is a Compound Document similar to .doc for Microsoft Word called .jtd. When processing a Figure stream from a .jtd, the application will allocate space when parsing a Figure. When copying filedata into this buffer, the application will calculate two values to determine how much data to copy from the document. If both of these values are larger than the size of the buffer, the application will choose the smaller of the two and trust it to copy data from the file. This value is larger than the buffer size, which leads to a heap-based buffer overflow. This overflow corrupts an offset in the heap used in pointer arithmetic for writing data and can lead to code-execution under the context of the application.

Tested Versions

JustSystems Ichitaro

Product URLs

http://www.ichitaro.com/

CVSSv3 Score

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

Details

Ichitaro uses the Structured Storage documentation format to read and process a .jtd file. Although there are many streams within a .jtd, the two streams that affect this bug are Figure and FigureData. Figure is the metadata for Figures and FigureData is contents representing the Figure.

The modules involved in the vulnerability are below (as described by lm vm in windbg):

In the following code, the application isolates a 0x3004 byte chunk out of a previously allocated 0x36b00 chunk (esi). This chunk is used to store FigureData which is processed later. The reason this occurs is to write the size of this chunk after the isolation. This leaves the chunk with the size at the end of the object and a pointer to the end of the object.

From this code, one suspect value is saved and will be returned to later (value_1). There is also a second value calculated based on the FigureData itself.

The application reads the subelement lengths from the FigureData header by reading the second byte of each element representing a number of subelements.

To calculate the possible figure length from this header, an accumulation value starts at 0. The application starts by adding 0x4b4 to the accumulation value and 0x4b0 for each subsequent element, as shown below:

After saving the possible length using elements, the application also must take into account subelements. Thus, 0x16 is added to the accumulation value for each of the subelements. This final value will be refered to as value_2.

The application will choose the smaller of the two values, regardless if it is actually greater than the original 0x3006 chunk size. Using this value, the application will overwrite the saved chunk size (offset 0x3006 from the above arithmetic).

During the manual unallocation of the 0x3004 chunk from the larger 0x36b00 chunk, the corrupted size value results in a pointer that is read out of bounds of the 0x36b00 initial chunk and is saved for later use. Because this pointer is trusted by the application and reused later, an attacker can potentially gain arbitrary write conditions leading to arbitrary code execution.