Dear all, Using AFLFast (https://github.com/mboehme/aflfast), a fork of AFL, with ASAN enabled we found a heap buffer overflow in bfd/peicode.h. The bug was found on Ubuntu 14.04 64-bit & binutils was checked out from https://github.com/bminor/binutils-gdb repository. Its commit is 268ebe95201d2ebdcf68cad9dc67ff6d1e25be9e (Fri Nov 18 14:15:12 2016). To reproduce: printf "\x00\x00\xff\xff\x00\x00\x4c\x01\xfb\x5b\x89\x7a\x02\x00\x00\x00\x3a\x7a\x7a\x7a\x7a\x84\x7a\x7a\x7a\x7a\x7e\x5b\x01\x00\x5b\x09\x09\xe6\xff\x00\x00\x00\x7f\xff\x8b\xb3\x09\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x2d\x09\x00\x80\x24\x29\x41\x02\x00\x00\x99\x20\x02\x40" > fd addr2line -e fd OR size @- fd OR strings -w -d fd When we run "strings -w -d fd", ASAN says: ==139869==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62100001dce0 at pc 0x7f5482b026d3 bp 0x7ffd60c03920 sp 0x7ffd60c030d0 READ of size 4049 at 0x62100001dce0 thread T0 #0 0x7f5482b026d2 (/usr/lib/x86_64-linux-gnu/libasan.so.3+0x3c6d2) #1 0x560beb in pe_ILF_object_p ../../bfd/peicode.h:1272 #2 0x560beb in pe_bfd_object_p ../../bfd/peicode.h:1407 #3 0x41848c in bfd_check_format_matches ../../bfd/format.c:311 #4 0x40b137 in strings_object_file ../../binutils/strings.c:411 #5 0x40b137 in strings_file ../../binutils/strings.c:454 #6 0x40b137 in main ../../binutils/strings.c:321 #7 0x7f5481807f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44) #8 0x40c376 (/home/ubuntu/subjects/binutils-asan/obj-asan/binutils/strings+0x40c376) 0x62100001dce0 is located 0 bytes to the right of 4064-byte region [0x62100001cd00,0x62100001dce0) allocated by thread T0 here: #0 0x7f5482b883a8 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xc23a8) #1 0x671e38 in objalloc_create ../../libiberty/objalloc.c:95 #2 0x41f61b in _bfd_new_bfd ../../bfd/opncls.c:73 #3 0x41fb71 in bfd_fopen ../../bfd/opncls.c:199 #4 0x40b122 in strings_object_file ../../binutils/strings.c:402 #5 0x40b122 in strings_file ../../binutils/strings.c:454 #6 0x40b122 in main ../../binutils/strings.c:321 #7 0x7f5481807f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44) SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/lib/x86_64-linux-gnu/libasan.so.3+0x3c6d2) Shadow bytes around the buggy address: 0x0c427fffbb40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c427fffbb50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c427fffbb60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c427fffbb70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c427fffbb80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c427fffbb90: 00 00 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa 0x0c427fffbba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c427fffbbb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c427fffbbc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c427fffbbd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c427fffbbe0: 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 After checking the code in peicode.h and debugging it in GDB, we found that although the size to allocate ptr is just 36 but after calling bfd_bread, the string length of ptr is much bigger than that. So, ASAN detects the heap buffer overflow in the call strlen(sym_name). The bug allows source_dll pointing to some location outside the boundary of symbol_name/ptr and it could lead to some bad thing if source_dll is not checked & used properly. ptr = (bfd_byte *) bfd_alloc (abfd, size); if (ptr == NULL) return NULL; if (bfd_bread (ptr, size, abfd) != size) { bfd_release (abfd, ptr); return NULL; } symbol_name = (char *) ptr; source_dll = symbol_name + strlen (symbol_name) + 1; Best regards, Thuan
The master branch has been updated by Nick Clifton <nickc@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=fa6631b4eecfcca00c13b9594e6336dffd40982f commit fa6631b4eecfcca00c13b9594e6336dffd40982f Author: Nick Clifton <nickc@redhat.com> Date: Mon Dec 5 16:34:45 2016 +0000 Fix seg-fault in the binutils utilities when reading a corrupt input file. PR binutils/20905 * peicode.h (pe_ILF_object_p): Use strnlen to avoid running over the end of the string buffer.
Hi Thuan, Thanks for reporting this bug. I have checked in a patch to prevent the code from trying to read of the end of buffer, which should fix this problem. Cheers Nick
This is CVE-2017-7226