Posts CVE-2021-43579: htmldoc: Stack buffer overflow in image_load_bmp()
Post
Cancel

CVE-2021-43579: htmldoc: Stack buffer overflow in image_load_bmp()

On November 4th, 2021, a vulnerability was reported by Scavenger Security member 00xc, which was tagged as CVE-2021-43579. This vulnerability affects the open-source software htmldoc, which is used for generating PDF files from HTML content. The security flaw consists in a stack buffer overflow in the image_load_bmp() function when the program parses a corrupted BMP image. The vulnerable code is the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static int          /* O - 0 = success, -1 = fail */
image_load_bmp(image_t *img,    /* I - Image to load into */
               FILE    *fp, /* I - File to read from */
               int     gray,    /* I - Grayscale image? */
               int     load_data)/* I - 1 = load image data, 0 = just info */
{
  ...
  uchar colormap[256][4];
  ...
  colors_used = read_dword(fp);
  ...
  fread(colormap, colors_used, 4, fp);
  ...
}

colormap is a fixed-size buffer on the stack. colors_used comes from the BMP file, but it used as a size to copy to the buffer without any validation. This means that a stack buffer overflow can be triggered when the program processes a corrupted BMP image that has more used colors than the supported ones.

Exploitation of this vulnerability can occur when the victim renders a malicious HTML which contains a corrupted BMP image, thus requiring the victim’s interaction with the exploit. Once the victim triggers the exploit the attacker loses control over the execution of the exploit. Therefore, the exploit has to be self-contained and cannot require additional memory leaks.

The vulnerability was fixed by the mantainer on November 5th of 2021, one day after it was reported.

Denial of Service - Proof of Concept

In the original report a proof of concept was provided to recreate the reported crash causing a DoS. Here are the steps to replicate it:

  1. Create an HTML file containing the corrupted BMP image. For example using the following html code: <HTML><BODY><P><IMG SRC="./poc.bmp"></IMG></BODY></HTML>

  2. Create the corrupted BMP image. It is important to start the image header with BM characters in order for the program to recognize the image as a valid BMP image. To corrupt the image it is necessary to change the colors_used field setting it to a big enough number to trigger the previously explained bug.

  3. Trigger the crash with the following command: ./htmldoc --webpage -f out.pdf ./poc.html

This command renders the HTML poc.html file, that contains the corrupted BMP image (poc.bmp), into the out.pdf file, triggering the crash. Additionally, it is worth noting that htmldoc also supports rendering HTML documents hosted in a remote server, opening a new attack vector.

Remote Code Execution - Proof of Concept

I developed a functional exploit that executes the /bin/sh command on the victim’s machine when the malicious BMP image is rendered. In this section I explain the exploit details to understand, recreate and test the exploit.

To recreate the exploit, the following exploitation environment must be met:

  • The exploit was developed against htmldoc at commit 86d15437cf0a1d89c63eb236fdd731d45d00e664 and Build ID d989fead1806cdad62d6778f803fc2f4377411ec.
  • The target htmldoc was built using clang version 11.0.1-2 on Debian.
  • The program is built using the default flags, which does not include PIE or stack protector.
  • The md5 hash of the built binary is feb3ed7a0b41228e79067dff4b479bc4.
  • Note that the provided exploit may not work on other builds of the same software.

Exploit Details

The exploit consists a ROP chain, which involves the following steps:

  1. Locate the address of the .data section.
  2. Prepare a ROP chain that uses snprintf() to write the malicious command string to be executed into the .data section. In this case I write /bin/sh command.
  3. ROP into the execve system call to execute /bin/sh.

Note that all gadgets used are part of the binary. Due to the nature of the exploit it is not possible to read additional addresses during its execution.

Once we generate the exploit, we host it on a web server, we trick the user into rendering it and at that point we will get code execution on the compromised host.

Conclusions

It has been very informative and exciting to create a functional proof of concept that demonstrates remote code execution from a denial of service (DoS) proof of concept found by one of our colleagues at Scavenger Security. We hope that this example serves as a learning tool for those interested in the field of computer security and increases awareness of the importance of regularly patching and updating software to prevent potential vulnerabilities.

The full exploit code here.

This post is licensed under CC BY 4.0 by the author.
Contents