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

Heap-buffer-overflow in archive_string_append_from_wcs() (archive_string.c) #1298

Closed
sanjeevk001 opened this issue Dec 28, 2019 · 0 comments
Closed

Comments

@sanjeevk001
Copy link

bsdtar: An error in archive_string_append_from_wcs() (archive_string.c) triggers an out-of-bounds write in heap memory that results into a crash, via a specially crafted archive file. This bug was found using our custom fuzzer.

Basic Information:
versions of libarchive: 3.4.1dev
How you obtained it: built from source
libarchive-3.4.1dev (https://github.com/libarchive/libarchive)
Tested OS: Linux 5.0.0-37-generic x86_64
Tested compiler version : gcc version 7.4.0

What other files were involved?
To trigger the bug, use the the crash file (unzip crash-file.zip)
crash-file.zip

===============
Compile with address address sanitizer (-fsanitize=addrsan)
Command to reproduce the bug:
$ ./bsdtar -t -f crash-file

Output (partial):

==2650==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x607000000298 at pc 0x5586b16c5082 bp 0x7ffc3d24a950 sp 0x7ffc3d24a940
WRITE of size 1 at 0x607000000298 thread T0
    #0 0x5586b16c5081 in archive_string_append_from_wcs libarchive/archive_string.c:831
    #1 0x5586b16c5fd7 in archive_mstring_get_mbs libarchive/archive_string.c:3913
    #2 0x5586b162200f in archive_entry_pathname libarchive/archive_entry.c:562
    #3 0x5586b16177bb in read_archive tar/read.c:275
    #4 0x5586b1618acf in tar_mode_t tar/read.c:94
    #5 0x5586b1613c3d in main tar/bsdtar.c:913
    #6 0x7fb07ba60b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #7 0x5586b1615a89 in _start (libarchive/bsdtar-addrsan+0x46a89)

0x607000000298 is located 0 bytes to the right of 72-byte region [0x607000000250,0x607000000298)
allocated by thread T0 here:
    #0 0x7fb07c9b7f40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
    #1 0x5586b16bc2bd in archive_string_ensure libarchive/archive_string.c:314

SUMMARY: AddressSanitizer: heap-buffer-overflow libarchive/archive_string.c:831 in archive_string_append_from_wcs
Shadow bytes around the buggy address:
  0x0c0e7fff8000: fa fa fa fa 00 00 00 00 00 00 00 00 00 fa fa fa
  0x0c0e7fff8010: fa fa 00 00 00 00 00 00 00 00 00 00 fa fa fa fa
  0x0c0e7fff8020: 00 00 00 00 00 00 00 00 00 00 fa fa fa fa 00 00
  0x0c0e7fff8030: 00 00 00 00 00 00 00 fa fa fa fa fa fd fd fd fd
  0x0c0e7fff8040: fd fd fd fd fd fa fa fa fa fa 00 00 00 00 00 00
=>0x0c0e7fff8050: 00 00 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff8090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff80a0: 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
==2650==ABORTING

Crash analysis :

In archive_string_append_from_wcs() (archive_string.c), upon execution of the crashing input (crash-file):

archive_string_append_from_wcs(){      
....

// Allocated heap memory for as->s is 72 bytes in range (0x607000000250,0x607000000298) 

p = as->s + as->length;
... 
while (*w != L'\0' && len > 0) {
		...

#if HAVE_WCRTOMB
		n = wcrtomb(p, *w++, &shift_state);   // p = 0x611000000628 --> 0x00,  wcrtomb() returns 3, n = 3
#else
		n = wctomb(p, *w++);
#endif
		if (n == -1) {
			if (errno == EILSEQ) {
		    ...
		} else
			p += n;               // p = 0x611000000628 --> 0x00
		len--;
	}
	as->length = p - as->s;      // as->length = 72 
	as->s[as->length] = '\0';    // **Heap overflow** occurs as it tries to write beyond the allocated heap memory
	return (ret_val);
}
mmatuska added a commit to mmatuska/libarchive that referenced this issue Dec 28, 2019
When we grow the archive_string buffer, we have to make sure it fits
at least one maximum-sized multibyte character in the current locale
and the null character.

Fixes libarchive#1298
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant