ericmckean / google-security-research

Automatically exported from code.google.com/p/google-security-research
0 stars 0 forks source link

FreeType 2.5.3 sbix PNG handling heap-based buffer overflow due to integer overflow #168

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
FreeType 2.5.3 supports embedded bitmaps in SFNT-based fonts, in one of the 
three standard graphics formats (PNG), while JPEG and TIFF are not yet 
supported. Such bitmaps can be found in the Apple-defined "sbix" tables (see 
https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html)
, which in the PNG case is internally handled in FreeType by the 
"Load_SBit_Png" function implemented in freetype/src/sfnt/pngshim.c.

In addition to bitmap data itself, additional glyph information such as width, 
height, bit depth etc. is obtained from corresponding PNG headers 
(specifically, IHDR) and used to initialize internal FT structures:

194:    png_uint_32  imgWidth, imgHeight;
195:
196:    int         bitdepth, color_type, interlace;
...
247:    png_get_IHDR( png, info,
248:                  &imgWidth, &imgHeight,
249:                  &bitdepth, &color_type, &interlace,
250:                  NULL, NULL );
...
258:    if ( populate_map_and_metrics )
259:    {
260:      FT_Long  size;
261:
262:
263:      metrics->width  = (FT_Int)imgWidth;
264:      metrics->height = (FT_Int)imgHeight;
265:
266:      map->width      = metrics->width;
267:      map->rows       = metrics->height;
268:      map->pixel_mode = FT_PIXEL_MODE_BGRA;
269:      map->pitch      = map->width * 4;
270:      map->num_grays  = 256;

More importantly, these sizes are further used with no bounds checks, in order 
to calculate the overall buffer size for the PNG data:

272:      size = map->rows * map->pitch;
273:
274:      error = ft_glyphslot_alloc_bitmap( slot, size );

The bitmap pixels are subsequently loaded into the buffer:

349:    for ( i = 0; i < (FT_Int)imgHeight; i++ )
350:      rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;
351:
352:    png_read_image( png, rows );

Now, since PNG supports very large images (the width and height fields in IHDR 
are 32-bit wide) and the "Load_SBit_Png" function blindly trusts the loaded 
dimensions, it is possible to overflow the "map->rows * map->pitch" expression, 
thus under-allocating the resulting buffer and later causing a heap-based 
buffer overflow.

Attached please find a font file (poc.ttf) with a valid embedded PNG file of 
width=65535 and height=16385, which causes "map->pitch" to become 262140, and 
"size" to become (uint32)(262140 * 16385) = (uint32)4295163900 = 196604. Since 
over 4GB of data is attempted to be loaded into a very small buffer, the sample 
triggers a SIGSEGV signal, or the following AddressSanitizer report.

In order to reproduce, run: $ ftview 150 /path/to/poc.ttf

=================================================================
==21730== ERROR: AddressSanitizer: unknown-crash on address 0xf57cf800 at pc 
0xf6121ce0 bp 0xffba2718 sp 0xffba22f8
WRITE of size 262140 at 0xf57cf800 thread T0
    #0 0xf6121cdf (/usr/lib32/libasan.so.0+0xdcdf)
    #1 0xf5b60ea1 (/lib/i386-linux-gnu/libpng12.so.0+0x9ea1)
    #2 0xf5b681f7 (/lib/i386-linux-gnu/libpng12.so.0+0x111f7)
    #3 0xf5b68669 (/lib/i386-linux-gnu/libpng12.so.0+0x11669)
    #4 0xf60460a3 in Load_SBit_Png freetype2/src/sfnt/pngshim.c:352
    #5 0xf604c768 in tt_face_load_sbix_image freetype2/src/sfnt/ttsbit.c:1320
    #6 0xf604cb8e in tt_face_load_sbit_image freetype2/src/sfnt/ttsbit.c:1395
    #7 0xf5f621b6 in load_sbit_image freetype2/src/truetype/ttgload.c:2036
    #8 0xf5f633a6 in TT_Load_Glyph freetype2/src/truetype/ttgload.c:2360
    #9 0xf5f539f9 in tt_glyph_load freetype2/src/truetype/ttdriver.c:404
    #10 0xf5f188f3 in FT_Load_Glyph freetype2/src/base/ftobjs.c:726
    #11 0xf60a315e in ftc_basic_family_load_glyph freetype2/src/cache/ftcbasic.c:173
    #12 0xf60a0937 in FTC_INode_New freetype2/src/cache/ftcimage.c:79
    #13 0xf60a09eb in ftc_inode_new freetype2/src/cache/ftcimage.c:102
    #14 0xf609e4ff in FTC_Cache_NewNode freetype2/src/cache/ftccache.c:461
    #15 0xf60a5115 in FTC_ImageCache_LookupScaler freetype2/src/cache/ftcbasic.c:389
    #16 0x8059ca0 in FTDemo_Index_To_Bitmap ft2demos-2.5.3/src/ftcommon.c:859
    #17 0x8059e42 in FTDemo_Draw_Index ft2demos-2.5.3/src/ftcommon.c:892
    #18 0x804bcce in Render_All ft2demos-2.5.3/src/ftview.c:493
    #19 0x80540c4 in main ft2demos-2.5.3/src/ftview.c:1974
0xf57ff7fc is located 0 bytes to the right of 196604-byte region 
[0xf57cf800,0xf57ff7fc)
allocated by thread T0 here:
    #0 0xf612a854 (/usr/lib32/libasan.so.0+0x16854)
    #1 0xf5f0f387 in ft_alloc freetype2/builds/unix/ftsystem.c:102
    #2 0xf5f37304 in ft_mem_qalloc freetype2/src/base/ftutil.c:76
    #3 0xf5f3716e in ft_mem_alloc freetype2/src/base/ftutil.c:55
    #4 0xf5f1637e in ft_glyphslot_alloc_bitmap freetype2/src/base/ftobjs.c:332
    #5 0xf6045d27 in Load_SBit_Png freetype2/src/sfnt/pngshim.c:274
    #6 0xf604c768 in tt_face_load_sbix_image freetype2/src/sfnt/ttsbit.c:1320
    #7 0xf604cb8e in tt_face_load_sbit_image freetype2/src/sfnt/ttsbit.c:1395
    #8 0xf5f621b6 in load_sbit_image freetype2/src/truetype/ttgload.c:2036
    #9 0xf5f633a6 in TT_Load_Glyph freetype2/src/truetype/ttgload.c:2360
    #10 0xf5f539f9 in tt_glyph_load freetype2/src/truetype/ttdriver.c:404
    #11 0xf5f188f3 in FT_Load_Glyph freetype2/src/base/ftobjs.c:726
    #12 0xf60a315e in ftc_basic_family_load_glyph freetype2/src/cache/ftcbasic.c:173
    #13 0xf60a0937 in FTC_INode_New freetype2/src/cache/ftcimage.c:79
    #14 0xf60a09eb in ftc_inode_new freetype2/src/cache/ftcimage.c:102
    #15 0xf609e4ff in FTC_Cache_NewNode freetype2/src/cache/ftccache.c:461
    #16 0xf60a5115 in FTC_ImageCache_LookupScaler freetype2/src/cache/ftcbasic.c:389
    #17 0x8059ca0 in FTDemo_Index_To_Bitmap ft2demos-2.5.3/src/ftcommon.c:859
    #18 0x8059e42 in FTDemo_Draw_Index ft2demos-2.5.3/src/ftcommon.c:892
    #19 0x804bcce in Render_All ft2demos-2.5.3/src/ftview.c:493
    #20 0x80540c4 in main ft2demos-2.5.3/src/ftview.c:1974
SUMMARY: AddressSanitizer: unknown-crash ??:0 ??
Shadow bytes around the buggy address:
  0x3eaf9eb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3eaf9ec0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3eaf9ed0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3eaf9ee0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x3eaf9ef0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x3eaf9f00:[00]00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x3eaf9f10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x3eaf9f20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x3eaf9f30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x3eaf9f40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x3eaf9f50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Heap righ redzone:     fb
  Freed Heap region:     fd
  Stack left redzone:    f1
  Stack mid redzone:     f2
  Stack right redzone:   f3
  Stack partial redzone: f4
  Stack after return:    f5
  Stack use after scope: f8
  Global redzone:        f9
  Global init order:     f6
  Poisoned by user:      f7
  ASan internal:         fe
==21730== ABORTING

Original issue reported on code.google.com by mjurc...@google.com on 13 Nov 2014 at 9:54

Attachments:

GoogleCodeExporter commented 9 years ago
Reported in https://savannah.nongnu.org/bugs/?43597.

Original comment by mjurc...@google.com on 13 Nov 2014 at 9:58

GoogleCodeExporter commented 9 years ago
Fixed in 
http://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=54abd22891bd5
1ef8b533b24df53b3019b5cee81, and after further discussion complemented by 
http://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=b3500af717010
137046ec4076d1e1c0641e33727.

Original comment by mjurc...@google.com on 21 Nov 2014 at 3:02

GoogleCodeExporter commented 9 years ago
All fixed by upstream:

FreeType 2.5.5

2014-12-30
FreeType 2.5.5 has been released. This is a minor bug fix release: All users of 
PCF fonts should update, since version 2.5.4 introduced a bug that prevented 
reading of such font files if not compressed.

FreeType 2.5.4

2014-12-06
FreeType 2.5.4 has been released. All users should upgrade due to another fix 
for vulnerability CVE-2014-2240 in the CFF driver. The library also contains a 
new round of patches for better protection against malformed fonts.

The main new feature, which is also one of the targets mentioned in the pledgie 
roadmap below, is auto-hinting support for Devanagari and Telugu, two widely 
used Indic scripts. A more detailed description of the remaining changes and 
fixes can be found here.

Original comment by cev...@google.com on 26 Jan 2015 at 5:27

GoogleCodeExporter commented 9 years ago

Original comment by mjurc...@google.com on 25 Feb 2015 at 2:04