bugThe FreeType Project - Bugs: bug #59308, Heap buffer overflow due to...

 
 

bug #59308: Heap buffer overflow due to integer truncation in Load_SBit_Png

Submitted by:  Sergei Glazunov <glazunov>
Submitted on:  Mon 19 Oct 2020 08:25:43 PM UTC  
 
Severity:  3 - Normal Item Group:  Crash
Status:  Fixed Privacy:  Public
Assigned to:  Werner LEMBERG <wl> Open/Closed:  Closed
Planned Release:  2.10.4

Add a New Comment (Rich Markup)
   

You are not logged in

Please log in, so followups can be emailed to you.

 

Mon 19 Oct 2020 10:19:13 PM UTC, comment #5: 

Also, good to know that the suggested change in comment #1 is almost exactly what is being used to patch this in Chromium at the moment (e.g. https://chromium.googlesource.com/chromium/src/third_party/freetype2.git/+/refs/heads/chromium/branch-heads/4240%5E%21/#F0 ). (Only difference being the order of imgWidth and imgHeight tests.)

bungeman <bungeman>
Mon 19 Oct 2020 10:16:57 PM UTC, comment #4: 

I see change https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/ChangeLog?id=a3bab162b2ae616074c8877a04556932998aeacd "[sfnt] Fix heap buffer overflow (#59308)." but it seems to be just a changelog entry and doesn't seem to have the change to pnhshim.c?

bungeman <bungeman>
Mon 19 Oct 2020 09:25:59 PM UTC, comment #3: 

Thank you for the prompt reply! I can confirm that your patch prevents the crash. Just in case, I'm attaching the same font file in a password protected zip archive (pw: infected).

(file #50023)

Sergei Glazunov <glazunov>
Mon 19 Oct 2020 09:21:33 PM UTC, comment #2: 

Too bad that the fuzzer run by the Chrome people didn't catch that in the last few years...

Werner LEMBERG <wl>
Project AdministratorIn charge of this item.
Mon 19 Oct 2020 09:09:14 PM UTC, comment #1: 

For some unknown reason I'm not able to download the testcase font; however, here's a patch that should fix the issue – please test!

diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
index 2e64e5846..f55016122 100644
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -332,6 +332,13 @@

     if ( populate_map_and_metrics )
     {
+      /* reject too large bitmaps similarly to the rasterizer */
+      if ( imgHeight > 0x7FFF || imgWidth > 0x7FFF )
+      {
+        error = FT_THROW( Array_Too_Large );
+        goto DestroyExit;
+      }
+
       metrics->width  = (FT_UShort)imgWidth;
       metrics->height = (FT_UShort)imgHeight;

@@ -340,13 +347,6 @@
       map->pixel_mode = FT_PIXEL_MODE_BGRA;
       map->pitch      = (int)( map->width * 4 );
       map->num_grays  = 256;
-
-      /* reject too large bitmaps similarly to the rasterizer */
-      if ( map->rows > 0x7FFF || map->width > 0x7FFF )
-      {
-        error = FT_THROW( Array_Too_Large );
-        goto DestroyExit;
-      }
     }

     /* convert palette/gray image to rgb */

Werner LEMBERG <wl>
Project AdministratorIn charge of this item.
Mon 19 Oct 2020 08:25:43 PM UTC, original submission:  

A heap buffer overflow vulnerability exists due to integer truncation in Load_SBit_Png.

VULNERABILITY DETAILS
src/sfnt/pngshim.c:251:
```
FT_LOCAL_DEF( FT_Error )
  Load_SBit_Png( FT_GlyphSlot     slot,
                 FT_Int           x_offset,
                 FT_Int           y_offset,
                 FT_Int           pix_bits,
                 TT_SBit_Metrics  metrics,
                 FT_Memory        memory,
                 FT_Byte*         data,
                 FT_UInt          png_len,
                 FT_Bool          populate_map_and_metrics,
                 FT_Bool          metrics_only )
  {

[...]

    png_get_IHDR( png, info,
                  &imgWidth, &imgHeight,
                  &bitdepth, &color_type, &interlace,
                  NULL, NULL ); // *** 1 ***

[...]

    if ( populate_map_and_metrics )
    {
      metrics->width  = (FT_UShort)imgWidth; // *** 2 ***
      metrics->height = (FT_UShort)imgHeight;

      map->width      = metrics->width;
      map->rows       = metrics->height;
      map->pixel_mode = FT_PIXEL_MODE_BGRA;
      map->pitch      = (int)( map->width * 4 );

[...]

    if ( populate_map_and_metrics )
    {
      /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
      FT_ULong  size = map->rows * (FT_ULong)map->pitch; // *** 3 ***

      error = ft_glyphslot_alloc_bitmap( slot, size ); // *** 4 ***
      if ( error )
        goto DestroyExit;
    }

[...]

    png_read_image( png, rows ); // *** 5 ***
```

A vulnerability exists in the function `Load_SBit_Png`, which processes PNG images embedded into fonts. This function:

1) Obtains the image width and height from the header as 32-bit integers.
2) Truncates the obtained values to 16 bit and stores them in a `TT_SBit_Metrics` structure.
3) Uses the truncated values to calculate the bitmap size.
4) Allocates the backing store of that size.
5) Passes `png_struct` and the backing store to a libpng function.

The issue is that libpng uses the original 32-bit values, which are saved in `png_struct`. Therefore, if the original width and/or height are greater than 65535, the allocated buffer won't be able to fit the bitmap.

I've verified that the emergency fix below breaks the proof-of-concept, but a long-term patch will require a more thorough code review:

```
diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
index 2e64e5846..7c98c2282 100644
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -335,6 +335,11 @@
       metrics->width  = (FT_UShort)imgWidth;
       metrics->height = (FT_UShort)imgHeight;

+      /* bail out if the width and/or height were truncated */
+      if ( metrics->width != imgWidth ||
+           metrics->height != imgHeight )
+        goto DestroyExit;
+
       map->width      = metrics->width;
       map->rows       = metrics->height;
       map->pixel_mode = FT_PIXEL_MODE_BGRA;
```

REPRODUCTION CASE
The attached font file should produce an AddressSanitizer error report when open with, e.g., ftview:
```
LD_LIBRARY_PATH=libpng-asan/.libs/ ./ftview 150 font.ttf

=================================================================
==41205==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61d00002ba60 at pc 0x7f96739ed36f bp 0x7ffc0dab7a80 sp 0x7ffc0dab7a70
WRITE of size 4 at 0x61d00002ba60 thread T0
    #0 0x7f96739ed36e in png_combine_row (/home/user/libpng/.libs/libpng16.so.16+0x9f36e)
    #1 0x7f9673991a23 in png_read_row (/home/user/libpng/.libs/libpng16.so.16+0x43a23)
    #2 0x7f9673992cbe in png_read_image (/home/user/libpng/.libs/libpng16.so.16+0x44cbe)
    #3 0x7f967380d234 in Load_SBit_Png (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x15e234)
    #4 0x7f9673852689 in tt_face_load_sbix_image (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x1a3689)
    #5 0x7f9673852be9 in tt_face_load_sbit_image (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x1a3be9)
    #6 0x7f9673737eea in load_sbit_image (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x88eea)
    #7 0x7f967373989c in TT_Load_Glyph (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x8a89c)
    #8 0x7f967372870d in tt_glyph_load (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x7970d)
    #9 0x7f96736e5b96 in FT_Load_Glyph (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x36b96)
    #10 0x55921b2dc298 in Render_All /home/user/freetype2-demos/src/ftview.c:538
    #11 0x55921b2dc298 in main /home/user/freetype2-demos/src/ftview.c:2044
    #12 0x7f96733a71e2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x271e2)
    #13 0x55921b2ddefd in _start (/home/user/freetype2-demos/bin/.libs/ftview+0x7efd)

0x61d00002ba60 is located 60 bytes to the right of 1956-byte region [0x61d00002b280,0x61d00002ba24)
allocated by thread T0 here:
    #0 0x7f9673b54ae8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dae8)
    #1 0x7f96736d9ac8 in ft_alloc (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x2aac8)
    #2 0x7f9673708715 in ft_mem_qalloc (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x59715)
    #3 0x7f967370856d in ft_mem_alloc (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x5956d)
    #4 0x7f96736e3a6e in ft_glyphslot_alloc_bitmap (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x34a6e)
    #5 0x7f967380cf92 in Load_SBit_Png (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x15df92)
    #6 0x7f9673852689 in tt_face_load_sbix_image (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x1a3689)
    #7 0x7f9673852be9 in tt_face_load_sbit_image (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x1a3be9)
    #8 0x7f9673737eea in load_sbit_image (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x88eea)
    #9 0x7f967373989c in TT_Load_Glyph (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x8a89c)
    #10 0x7f967372870d in tt_glyph_load (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x7970d)
    #11 0x7f96736e5b96 in FT_Load_Glyph (/home/user/freetype2/objs/.libs/libfreetype.so.6+0x36b96)
    #12 0x55921b2dc298 in Render_All /home/user/freetype2-demos/src/ftview.c:538
    #13 0x55921b2dc298 in main /home/user/freetype2-demos/src/ftview.c:2044

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/user/libpng/.libs/libpng16.so.16+0x9f36e) in png_combine_row
Shadow bytes around the buggy address:
  0x0c3a7fffd6f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3a7fffd700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3a7fffd710: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3a7fffd720: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3a7fffd730: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c3a7fffd740: 00 00 00 00 04 fa fa fa fa fa fa fa[fa]fa fa fa
  0x0c3a7fffd750: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fffd760: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fffd770: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fffd780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fffd790: 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
==41205==ABORTING
```

Note that this vulnerability was originally reported to Google Chrome today (2020-10-19) under
a 7 day deadline, which is used for vulnerabilities that have been detected in an "in the wild" exploit (e.g. the vulnerability is being actively exploited). We're expecting to release the technical details for this bug on our issue tracker on 2020-10-26.

This issue has been assigned CVE-2020-15999.

CREDIT INFORMATION
Sergei Glazunov of Google Project Zero

Sergei Glazunov <glazunov>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #50023:  font.zip added by glazunov (574B - application/zip)
file #50021:  font.ttf added by glazunov (940B - application/octet-stream)
file #50022:  asan.log added by glazunov (4KiB - application/octet-stream)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by bungeman (Posted a comment)
  • -email is unavailable- added by wl (Updated the item)
  • -email is unavailable- added by glazunov (Submitted the item)
  • -email is unavailable- added by glazunov
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

     

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-10-19 wl StatusNone => Fixed
        PrivacyPrivate => Public
        Open/ClosedOpen => Closed
        Planned ReleaseNone => 2.10.4
    2020-10-19 glazunov Attached File- => Added font.zip, #50023
    2020-10-19 wl Assigned toNone => wl
    2020-10-19 glazunov Attached File- => Added font.ttf, #50021
        Attached File- => Added asan.log, #50022
        Carbon-Copy- => Added hawkes

    Back to the top


    Powered by Savane 3.5