Skip to content

Stack-based buffer overflow in setbit() #195

Closed
@SegfaultMasters

Description

@SegfaultMasters

There exists a stack-based buffer overflow in setbit() function at iptree.h, invoked by get_histogram() in src/netviz/address_histogram.cpp. The issue gets triggered when the value of depth in get_histogram() is set greater than 127 & being passed to i in setbit().

The setbit() function sets the ith bit to 1, in case where the i value exceeds more than 127, the computation goes wrong & a stack overflow is triggered.

Tested version -

1.5.0 (Master)

Command -

tcpflow -a -D -b -m -o -Fk –r $POC

Debugging:

 /* set the ith bit to 1 */
    static void setbit(uint8_t *addr,size_t i){
        addr[i / 8] |= (1<<((7-i)&7));   //Buffer overflow
    }
gef➤  p/d i
$6 = 127


gef➤  p/d (1<<((7-i)&7))
$8 = 1

gef➤  p/d addr[127 / 8]
$14 = 0
gef➤  p/d addr[126 / 8]
$15 = 0
gef➤  p/d addr[128 / 8]
$16 = 96

gef➤  p/d (1<<((7-127)&7))
$18 = 1
gef➤  p/d (1<<((7-128)&7))
$19 = 128

Backtrace:

.
.
.
.
.
#3 0x438649 in iptreet<unsigned long, 16ul>::get_histogram(std::vector<iptreet<unsigned long, 16ul>::addr_elem, std::allocator<iptreet<unsigned long, 16ul>::addr_elem> >&) const iptree.h:402
#4 0x437d92 in address_histogram::address_histogram(iptreet<unsigned long, 16ul> const&) netviz/address_histogram.cpp:30
#5 0x4489eb in one_page_report::render(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) netviz/one_page_report.cpp:268
#6 0x4f7307 in scan_netviz /home/ace/Desktop/tcpflow/src/scan_netviz.cpp:74
#7 0x493ebd in be13::plugin::phase_shutdown(feature_recorder_set&, std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >*) be13_api/plugin.cpp:403
#8 0x4c75ec in main /home/ace/Desktop/tcpflow/src/tcpflow.cpp:909
#9 0x7ffff4ec082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#10 0x408f58 in _start (/usr/bin/tcpflow+0x408f58)

ASAN Report

==24797==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffffffb840 at pc 0x000000439d28 bp 0x7fffffffb710 sp 0x7fffffffb700
READ of size 1 at 0x7fffffffb840 thread T0
    #0 0x439d27 in iptreet<unsigned long, 16ul>::setbit(unsigned char*, unsigned long) iptree.h:245
    #1 0x438fda in iptreet<unsigned long, 16ul>::get_histogram(int, unsigned char const*, iptreet<unsigned long, 16ul>::node const*, std::vector<iptreet<unsigned long, 16ul>::addr_elem, std::allocator<iptreet<unsigned long, 16ul>::addr_elem> >&) const iptree.h:393
    #2 0x438649 in iptreet<unsigned long, 16ul>::get_histogram(std::vector<iptreet<unsigned long, 16ul>::addr_elem, std::allocator<iptreet<unsigned long, 16ul>::addr_elem> >&) const iptree.h:402
    #3 0x437d92 in address_histogram::address_histogram(iptreet<unsigned long, 16ul> const&) netviz/address_histogram.cpp:30
    #4 0x4489eb in one_page_report::render(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) netviz/one_page_report.cpp:268
    #5 0x4f7307 in scan_netviz /home/ace/Desktop/tcpflow/src/scan_netviz.cpp:74
    #6 0x493ebd in be13::plugin::phase_shutdown(feature_recorder_set&, std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >*) be13_api/plugin.cpp:403
    #7 0x4c75ec in main /home/ace/Desktop/tcpflow/src/tcpflow.cpp:909
    #8 0x7ffff4ec082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #9 0x408f58 in _start (/usr/bin/tcpflow+0x408f58)

Address 0x7fffffffb840 is located in stack of thread T0 at offset 208 in frame
    #0 0x438ded in iptreet<unsigned long, 16ul>::get_histogram(int, unsigned char const*, iptreet<unsigned long, 16ul>::node const*, std::vector<iptreet<unsigned long, 16ul>::addr_elem, std::allocator<iptreet<unsigned long, 16ul>::addr_elem> >&) const iptree.h:379

  This frame has 3 object(s):
    [32, 72) '<unknown>'
    [128, 144) 'addr0'
    [192, 208) 'addr1' <== Memory access at offset 208 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow iptree.h:245 iptreet<unsigned long, 16ul>::setbit(unsigned char*, unsigned long)
Shadow bytes around the buggy address:
  0x10007fff76b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff76c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff76d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff76e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
  0x10007fff76f0: f1 f1 00 00 00 00 00 f4 f4 f4 f2 f2 f2 f2 00 00
=>0x10007fff7700: f4 f4 f2 f2 f2 f2 00 00[f4]f4 f3 f3 f3 f3 00 00
  0x10007fff7710: 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f4 f4 f3 f3
  0x10007fff7720: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff7730: f1 f1 f1 f1 00 f4 f4 f4 f2 f2 f2 f2 00 00 00 f4
  0x10007fff7740: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff7750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==24797==ABORTING
[Inferior 1 (process 24797) exited with code 01]

Note: Issue reproducible when compiled with AddressSanitizer

Please check if you are able to reproduce the issue via the Reproducer file

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions