Buffer overflow in VCFtools 0.1.16

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