Buffer overflow in VCFtools 0.1.16
August 14, 2018
Product Details
VCFtools is a suite of functions for use on genetic variation data in the form of VCF and BCF files. The tools provided will be used mainly to summarize data, run calculations on data, filter out data, and convert data into other useful file formats.
URL: https://vcftools.github.io/
Vulnerable Versions
VCFtools 0.1.16
Vulnerability Details
A Buffer overflow was discovered in VCFtools 0.1.16 version.
SYNOPSIS
``` void bcf_file::get_entry(vector<char> &out) { uint32_t size_int[2]; int ret, read_size = 0; ret = read(&size_int[0], 2, sizeof(uint32_t) ); read_size = size_int[0] + size_int[1]; [1] ``` ``` out.resize(read_size+2*sizeof(uint32_t)); [2] memcpy(&out[0], size_int, 2*sizeof(uint32_t)); [3] read(&out[2*sizeof(uint32_t)], 1, read_size); ```
Similar to report #11, while parsing an BCF file type, it calls the function variant_file::write_stats() which calls bcf_file::get_entry() responsible for getting all the entries from the objects. It then performs few computations.
The value of ‘read_size’ becomes -8 while evaluating it with size_int[0] + size_int[1] [1]. The value of read_size is then being passed to out.resize() [2] , resulting in incorrect resultant value, same being used by memcpy [3]as the destination. As the program incorrectly calculates ‘out.resize’ cause the memcpy() to fail and cause the crash.
The function memcpy() does not allow to copy 8 bytes from ‘size_int’ to ‘&out[0]’ as the value of ‘&out[0]’ is 0 , throwing a segmentation fault.
Fix: As a part of fix a bound check if added to check if the resultant value of `read_size` is greater than zero.
+ if (ret && (read_size > 0))
{
Commit: 116ee07aea83262fe81a2399e8fb406555c0ab7a
Analysis
info locals size_int = {0xfffffff9, 0xffffffff} ret = 0x1 read_size = 0xfffffff8 p/d read_size $2 = -8 p &out[0] $3 = 0x0 i r rax 0xfffffffffffffff9 0xfffffffffffffff9 rbx 0x555555895910 0x555555895910 rcx 0x0 0x0 rdx 0x0 0x0 rsi 0x0 0x0 rdi 0x7fffffffd8d0 0x7fffffffd8d0 rbp 0x7fffffffd8a0 0x7fffffffd8a0 rsp 0x7fffffffd860 0x7fffffffd860 r8 0x0 0x0 r9 0x555555898d20 0x555555898d20 r10 0xffffffffffffff90 0xffffffffffffff90 r11 0x7ffff7bb7080 0x7ffff7bb7080 r12 0x55555555a970 0x55555555a970 r13 0x7fffffffe190 0x7fffffffe190 r14 0x0 0x0 r15 0x0 0x0 rip 0x55555557a599 0x55555557a599 <bcf_file::get_entry(std::vector<char, std::allocator >&)+133>
Backtrace
#0 bcf_file::get_entry (this=0x555555895910, out=std::vector of length 0, capacity 0) at bcf_file.cpp:123 #1 0x00005555555f7581 in variant_file::write_stats (this=0x555555895910, params=...) at variant_file_output.cpp:5409 #2 0x0000555555622226 in main (argc=0x3, argv=0x7fffffffe198) at vcftools.cpp:58 #3 0x00007ffff6f061c1 in __libc_start_main (main=0x555555621c82 <main(int, char**)>, argc=0x3, argv=0x7fffffffe198, init=, fini=, rtld_fini=, stack_end=0x7fffffffe188) at ../csu/libc-start.c:308 #4 0x000055555555a99a in _start ()
Timeline
Vendor Disclosure: 2018-08-14
Patch Release: 2018-08-15
Public Disclosure: 2018-08-16
Credit
Discovered by ACE Team – Loginsoft