Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack-based buffer overflow in setbit() #195

Closed
SegfaultMasters opened this issue Oct 15, 2018 · 16 comments
Closed

Stack-based buffer overflow in setbit() #195

SegfaultMasters opened this issue Oct 15, 2018 · 16 comments

Comments

@SegfaultMasters
Copy link

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

@simsong
Copy link
Owner

simsong commented Oct 15, 2018 via email

@carnil
Copy link

carnil commented Oct 17, 2018

This issue was assigned CVE-2018-18409

@simsong
Copy link
Owner

simsong commented Oct 20, 2018 via email

@simsong simsong closed this as completed Oct 20, 2018
@dkogan
Copy link
Contributor

dkogan commented Nov 16, 2018

Hi. The patch that fixes this produces code that doesn't build. It defines this function:

static void setbit(uint8_t *addr,size_t addr, size_t i)

Note that there are two arguments called "addr".

@dkogan
Copy link
Contributor

dkogan commented Nov 16, 2018

And there's a bug where this function is used. We have this:

static void un_pair(uint8_t *addr1,uint8_t *addr2,size_t addr12len,size_t *depth1,size_t *depth2,const uint8_t *addr,size_t addrlen,size_t depth){
    for(size_t i=0;i<addrlen*8/2;i++){
        if(iptreet<uint64_t,32>::bit(addr,i*2))
            iptreet<uint64_t,32>::setbit(addr1,sizeof(addr1),i);
        if(iptreet<uint64_t,32>::bit(addr,i*2+1))
            iptreet<uint64_t,32>::setbit(addr2,sizeof(addr2),i);
    }

Note that addr1 and addr2 are uint8_t*, so sizeof(addr1) and sizeof(addr2) doesn't do what you intend. Thanks.

@simsong
Copy link
Owner

simsong commented Nov 16, 2018 via email

@simsong
Copy link
Owner

simsong commented Nov 18, 2018 via email

@dkogan
Copy link
Contributor

dkogan commented Nov 21, 2018

Thanks for addressing this. Are you going to release 1.5.1 in the near future?

@simsong
Copy link
Owner

simsong commented Nov 21, 2018 via email

@dkogan
Copy link
Contributor

dkogan commented Nov 21, 2018 via email

@simsong
Copy link
Owner

simsong commented Nov 21, 2018 via email

@dkogan
Copy link
Contributor

dkogan commented Nov 21, 2018

Hi. Thanks for the new release. It doesn't include any code to fix the two setbit() issues noted above. So 1.5.1 doesn't build. Can you make a 1.5.2 that includes those fixes?

@simsong
Copy link
Owner

simsong commented Nov 21, 2018 via email

@simsong
Copy link
Owner

simsong commented Nov 21, 2018

Hi @dkogan , I misread the original comment.

@simsong simsong reopened this Nov 21, 2018
@simsong
Copy link
Owner

simsong commented Nov 21, 2018

Fixed in v.1.5.2

@simsong simsong closed this as completed Nov 21, 2018
@dkogan
Copy link
Contributor

dkogan commented Nov 22, 2018 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants