Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two Integer Overflow bugs in image.cxx #471

Closed
Zzero00 opened this issue Mar 10, 2022 · 5 comments
Closed

Two Integer Overflow bugs in image.cxx #471

Zzero00 opened this issue Mar 10, 2022 · 5 comments
Assignees
Labels
bug Something isn't working priority-high
Milestone

Comments

@Zzero00
Copy link

Zzero00 commented Mar 10, 2022

Hi, there is two integer overflow bugs in the latest version of htmldoc.
They are similar to CVE-2021-20308.

os: ubuntu 20.04
version: 1.9.16(the latest)

First

First, in image_load_jpeg function, image.cxx.
When it calls malloc,'img->width' and 'img->height' are enough large to cause an integer overflow
So, the malloc function may return a heap block smaller than the expected size, and it will cause a buffer overflow/Address boundary error in the jpeg_read_scanlines function.

htmldoc/htmldoc/image.cxx

Lines 1390 to 1395 in cb4cdee

static int /* O - 0 = success, -1 = fail */
image_load_jpeg(image_t *img, /* I - Image pointer */
FILE *fp, /* I - File to load from */
int gray, /* I - 0 = color, 1 = grayscale */
int load_data)/* I - 1 = load image data, 0 = just info */
{

htmldoc/htmldoc/image.cxx

Lines 1452 to 1466 in cb4cdee

img->pixels = (uchar *)malloc((size_t)(img->width * img->height * img->depth));
if (img->pixels == NULL)
{
jpeg_destroy_decompress(&cinfo);
return (-1);
}
jpeg_start_decompress(&cinfo);
while (cinfo.output_scanline < cinfo.output_height)
{
row = (JSAMPROW)(img->pixels + (size_t)cinfo.output_scanline * (size_t)cinfo.output_width * (size_t)cinfo.output_components);
jpeg_read_scanlines(&cinfo, &row, (JDIMENSION)1);
}

Asan report:

./htmldoc --webpage -f out.pdf ./test.html
PAGES: 4
Corrupt JPEG data: premature end of data segment
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1326478==ERROR: AddressSanitizer: SEGV on unknown address 0x621000020000 (pc 0x7f0bd38812e1 bp 0x7ffd6a49c500 sp 0x7ffd6a49c460 T0)
==1326478==The signal is caused by a WRITE memory access.
    #0 0x7f0bd38812e1  (/lib/x86_64-linux-gnu/libjpeg.so.8+0x422e1)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libjpeg.so.8+0x422e1)
==1326478==ABORTING

And this is the poc file:
poc1.zip

Second

There is another integer overflow bug in image_load_png function, image.cxx, similar to the first one.

htmldoc/htmldoc/image.cxx

Lines 1631 to 1647 in cb4cdee

img->pixels = (uchar *)calloc(1, (size_t)(img->width * img->height * depth));
/*
* Allocate pointers...
*/
rows = (png_bytep *)calloc(png_get_image_height(pp, info), sizeof(png_bytep));
for (i = 0; i < (int)png_get_image_height(pp, info); i ++)
rows[i] = img->pixels + i * img->width * depth;
/*
* Read the image, handling interlacing as needed...
*/
for (i = png_set_interlace_handling(pp); i > 0; i --)
png_read_rows(pp, rows, NULL, (png_uint_32)img->height);

It calls calloc to get heap block.
However, the width and height of the png file are both four bytes long, so 'img->width' and 'img->height' are enough large to cause an integer overflow.
The calloc function may return a heap block smaller than the expected size, and finally cause a heap overflow in the png_read_rows function when memcpy.

This is the Asan report:

./htmldoc --webpage -f out.pdf ./test.html
PAGES: 4
=================================================================
==1327797==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000008631 at pc 0x000000434be3 bp 0x7ffc5424be70 sp 0x7ffc5424b630
WRITE of size 196608 at 0x602000008631 thread T0
    #0 0x434be2 in memcpy (/root/fuzz_workdir/htmldoc/install/bin/htmldoc+0x434be2)
    #1 0x7f847c9e379c  (/lib/x86_64-linux-gnu/libpng16.so.16+0x1d79c)
    #2 0x7f847c9d680b in png_read_row (/lib/x86_64-linux-gnu/libpng16.so.16+0x1080b)
    #3 0x7f847c9d81d8 in png_read_rows (/lib/x86_64-linux-gnu/libpng16.so.16+0x121d8)
    #4 0x5e8c0b in image_load_png(image_t*, _IO_FILE*, int, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/image.cxx:1647:5
    #5 0x5e169d in image_load /root/fuzz_workdir/tmp/htmldoc/htmldoc/image.cxx:845:14
    #6 0x54314f in write_image(_IO_FILE*, render_str*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:10305:5
    #7 0x55015e in pdf_write_page(_IO_FILE*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:2695:13
    #8 0x5175c6 in pdf_write_outpage(_IO_FILE*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:2607:9
    #9 0x5175c6 in pdf_write_document(unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, tree_str*, tree_str*) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:2321:5
    #10 0x5175c6 in pspdf_export /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:910:7
    #11 0x4e30ca in main /root/fuzz_workdir/tmp/htmldoc/htmldoc/htmldoc.cxx:1291:3
    #12 0x7f847c3d60b2 in __libc_start_main /build/glibc-sMfBJT/glibc-2.31/csu/../csu/libc-start.c:308:16
    #13 0x41e86d in _start (/root/fuzz_workdir/htmldoc/install/bin/htmldoc+0x41e86d)

0x602000008631 is located 0 bytes to the right of 1-byte region [0x602000008630,0x602000008631)
allocated by thread T0 here:
    #0 0x499c42 in calloc (/root/fuzz_workdir/htmldoc/install/bin/htmldoc+0x499c42)
    #1 0x5e897d in image_load_png(image_t*, _IO_FILE*, int, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/image.cxx:1631:26
    #2 0x5e169d in image_load /root/fuzz_workdir/tmp/htmldoc/htmldoc/image.cxx:845:14
    #3 0x54314f in write_image(_IO_FILE*, render_str*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:10305:5
    #4 0x55015e in pdf_write_page(_IO_FILE*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:2695:13

SUMMARY: AddressSanitizer: heap-buffer-overflow (/root/fuzz_workdir/htmldoc/install/bin/htmldoc+0x434be2) in memcpy
Shadow bytes around the buggy address:
  0x0c047fff9070: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
  0x0c047fff9080: fa fa 00 02 fa fa 06 fa fa fa 06 fa fa fa 07 fa
  0x0c047fff9090: fa fa 06 fa fa fa 02 fa fa fa 00 07 fa fa fd fd
  0x0c047fff90a0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fd
  0x0c047fff90b0: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
=>0x0c047fff90c0: fa fa fd fa fa fa[01]fa fa fa fa fa fa fa fa fa
  0x0c047fff90d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff90e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff90f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==1327797==ABORTING

And this is the poc file:
poc2.zip
(wrong poc)
This is the correct poc:
real_poc2.zip

@michaelrsweet michaelrsweet self-assigned this Mar 10, 2022
@michaelrsweet michaelrsweet added bug Something isn't working priority-high labels Mar 10, 2022
@michaelrsweet michaelrsweet added this to the Stable milestone Mar 10, 2022
michaelrsweet added a commit that referenced this issue Mar 10, 2022
#471)

All images are now limited to 4GiB of memory usage (37837x37837 pixels).
@michaelrsweet
Copy link
Owner

I wasn't able to reproduce the issue with poc2, but I added range checks to the JPEG and PNG load functions to limit images to <4GiB - a little lazy but for the intended usage I don't see a problem limiting images like this.

[master 31f7804] Fix a potential integer overflow bug in the JPEG and PNG loaders (Issue #471)

@Zzero00
Copy link
Author

Zzero00 commented Mar 11, 2022

I wasn't able to reproduce the issue with poc2, but I added range checks to the JPEG and PNG load functions to limit images to <4GiB - a little lazy but for the intended usage I don't see a problem limiting images like this.

[master 31f7804] Fix a potential integer overflow bug in the JPEG and PNG loaders (Issue #471)

Oh, I‘m sorry, this is the correct poc2 file:
real_poc2.zip

I forgot to modify the html file in the above poc2 file.
As follows:

$ unzip real_poc2.zip
Archive:  real_poc2.zip
  inflating: poc.png
  inflating: test.html
$ ls
htmldoc*  htmldoc_noasan*  poc.png  real_poc2.zip  test.html
$ ./htmldoc_noasan --webpage -f out.pdf ./test.html
PAGES: 4
fish: “./htmldoc_noasan --webpage -f o…” terminated by signal SIGSEGV (Address boundary error)
$ ./htmldoc --webpage -f out.pdf ./test.html
PAGES: 4
=================================================================
==1369912==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000008631 at pc 0x000000434be3 bp 0x7ffe31cc2070 sp 0x7ffe31cc1830
WRITE of size 196608 at 0x602000008631 thread T0
......

@michaelrsweet
Copy link
Owner

Re-confirmed that the changes I pushed also address this test file.

@BrianInglis
Copy link

BrianInglis commented May 21, 2022

Currently tracked as htmldoc 1.9.16 vulnerabilty CVE-2022-27114 score 5.5 MEDIUM.
Please consider making an updated release soon or ask to have the affected version corrected.

@michaelrsweet
Copy link
Owner

@BrianInglis a release was done a few days ago.

Please refamiliarize yourself with the license terms of this free software that comes with no warranties or guarantees of any kind!

Repository owner locked as resolved and limited conversation to collaborators May 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working priority-high
Projects
None yet
Development

No branches or pull requests

3 participants