0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
Graphite2 - GlyphCache::GlyphCache Heap Based Buffer Overflow
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=749 The following crash due to a heap-based buffer overflow can be observed in a slightly modified ASAN build of the standard Graphite2 gr2FontTest utility (git trunk), triggered with the following command: $ ./gr2fonttest /path/to/file text My change in gr2FontTest was to hardcode the tested text to include all characters in the 0x1..0xfff range, instead of having to specify them in command line. The patch is as follows: --- cut --- --- graphite_original/gr2fonttest/gr2FontTest.cpp 2016-02-27 19:35:16.308071127 +0100 +++ graphite/gr2fonttest/gr2FontTest.cpp 2016-02-26 13:57:13.389186376 +0100 @@ -437,7 +437,17 @@ if (mainArgOffset < 1) argError = true; else if (mainArgOffset > 1) { - if (!useCodes && pText != NULL) + const unsigned int kCodeLimit = 0x1000; + + charLength = kCodeLimit - 1; + + pText32 = (unsigned int *)malloc(sizeof(unsigned int) * kCodeLimit); + for (unsigned int i = 1; i < kCodeLimit; ++i) { + pText32[i - 1] = i; + } + pText32[kCodeLimit - 1] = 0; + + /*if (!useCodes && pText != NULL) { charLength = convertUtf<gr2::utf8>(pText, pText32); if (!pText32) @@ -466,7 +476,7 @@ { pText32[charLength] = 0; fprintf(log, "\n"); - } + }*/ } return (argError) ? false : true; } --- cut --- The resulting ASAN crash is as follows: --- cut --- ==27575==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000efd0 at pc 0x00000055daad bp 0x7ffdfb0bfe90 sp 0x7ffdfb0bfe88 WRITE of size 8 at 0x60200000efd0 thread T0 #0 0x55daac in graphite2::GlyphCache::GlyphCache(graphite2::Face const&, unsigned int) graphite/src/GlyphCache.cpp:133:20 #1 0x549503 in graphite2::Face::readGlyphs(unsigned int) graphite/src/Face.cpp:98:29 #2 0x56d3f4 in (anonymous namespace)::load_face(graphite2::Face&, unsigned int) graphite/src/gr_face.cpp:54:14 #3 0x56cf04 in gr_make_face_with_ops graphite/src/gr_face.cpp:89:16 #4 0x56f240 in gr_make_file_face graphite/src/gr_face.cpp:242:23 #5 0x4ec193 in Parameters::testFileFont() const (graphite/gr2fonttest/gr2fonttest+0x4ec193) #6 0x4ef595 in main (graphite/gr2fonttest/gr2fonttest+0x4ef595) 0x60200000efd1 is located 0 bytes to the right of 1-byte region [0x60200000efd0,0x60200000efd1) allocated by thread T0 here: #0 0x4b86dc in calloc llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:56 #1 0x56ac8a in graphite2::GlyphFace const** graphite2::grzeroalloc<graphite2::GlyphFace const*>(unsigned long) graphite/src/./inc/Main.h:96:28 #2 0x55cb26 in graphite2::GlyphCache::GlyphCache(graphite2::Face const&, unsigned int) graphite/src/GlyphCache.cpp:119:45 #3 0x549503 in graphite2::Face::readGlyphs(unsigned int) graphite/src/Face.cpp:98:29 #4 0x56d3f4 in (anonymous namespace)::load_face(graphite2::Face&, unsigned int) graphite/src/gr_face.cpp:54:14 #5 0x56cf04 in gr_make_face_with_ops graphite/src/gr_face.cpp:89:16 #6 0x56f240 in gr_make_file_face graphite/src/gr_face.cpp:242:23 #7 0x4ec193 in Parameters::testFileFont() const (graphite/gr2fonttest/gr2fonttest+0x4ec193) #8 0x4ef595 in main (graphite/gr2fonttest/gr2fonttest+0x4ef595) SUMMARY: AddressSanitizer: heap-buffer-overflow graphite/src/GlyphCache.cpp:133:20 in graphite2::GlyphCache::GlyphCache(graphite2::Face const&, unsigned int) Shadow bytes around the buggy address: 0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c047fff9df0: fa fa 00 fa fa fa 01 fa fa fa[01]fa fa fa 00 04 0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e40: 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 Heap right 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 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==27575==ABORTING --- cut --- A cursory analysis shows that the direct reason of the crash is the wrong assumption made by GlyphCache::GlyphCache() that the _num_glyphs field is always greater than 0. A buffer is allocated in line 128: --- cut --- 128 GlyphFace * const glyphs = new GlyphFace [_num_glyphs]; --- cut --- And regardless of the _num_glyphs value, data is written to its first entry in line 133: --- cut --- 132 // The 0 glyph is definately required. 133 _glyphs[0] = _glyph_loader->read_glyph(0, glyphs[0], &numsubs); --- cut --- While this could just end as an off-by-one error and a fixed ~8 byte overflow, it gets worse. The subsequent loop in lines 139-140 also assumes that _num_glyphs is non-zero, and additionally wrongly (in the context of the misassumption) uses the != operator instead of < in the loop end condition: --- cut --- 138 const GlyphFace * loaded = _glyphs[0]; 139 for (uint16 gid = 1; loaded && gid != _num_glyphs; ++gid) 140 _glyphs[gid] = loaded = _glyph_loader->read_glyph(gid, glyphs[gid], &numsubs); --- cut --- This essentially means that the size of the overflown area is fully controlled by an attacker; it must only be a multiple of the native word size: typically 4 or 8 bytes. The bug was reported at https://bugzilla.mozilla.org/show_bug.cgi?id=1251869. Attached are three font files which trigger the crash. Proof of Concept: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39859.zip # 0day.today [2024-12-23] #