Skip to content

Buffer-overflow (out-of-bounds read) occured in two positions #95

Description

@bladchan

Hi,

I am running some experiments for AFLAPI and it has found two buffer-overflows (read) in cparse::packToken::str[abi:cxx11] and cparse::calculator::toRPN.

Environment: Ubuntu 18.04 + clang 6.0.0

Poc 1:

// heap_overflow_1.cc
#include "shunting-yard.h"

using namespace cparse;

int main(){
	TokenMap vars;
	calculator::calculate("C'\\", &vars);
}

Poc 2

// heap_overflow_2.cc
#include "shunting-yard.h"

using namespace cparse;

int main(){
	TokenMap vars;
	vars["pi"] = 1535;	
calculator::calculate("7pi~pp\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\u0005\x84ipp\u0005?", &vars);
}

Files are here:
heap_overflow_files.zip

To reproduce:

  1. Complie the pocs and the whole project with ASAN;
  2. Run pocs

For Poc1, ASAN says:

$ ./heap_overflow_1 
=================================================================
==28967==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000005e7b64 at pc 0x000000540fac bp 0x7ffecd066850 sp 0x7ffecd066848
READ of size 1 at 0x0000005e7b64 thread T0
    #0 0x540fab in cparse::calculator::toRPN(char const*, cparse::TokenMap, char const*, char const**, cparse::Config_t) /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:359:14
    #1 0x54cd52 in cparse::calculator::calculate(char const*, cparse::TokenMap, char const*, char const**) /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:512:27
    #2 0x518a1a in main /home/ubuntu/some_c_test/cparse/fuzz/heap_overflow_1.cc:7:2
    #3 0x7f7132a53c86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
    #4 0x41bf89 in _start (/home/ubuntu/some_c_test/cparse/fuzz/heap_overflow_1+0x41bf89)

0x0000005e7b64 is located 0 bytes to the right of global variable '<string literal>' defined in 'heap_overflow_1.cc:7:24' (0x5e7b60) of size 4
  '<string literal>' is ascii string 'C'\'
SUMMARY: AddressSanitizer: global-buffer-overflow /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:359:14 in cparse::calculator::toRPN(char const*, cparse::TokenMap, char const*, char const**, cparse::Config_t)
Shadow bytes around the buggy address:
  0x0000800b4f10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b4f20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b4f30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b4f40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b4f50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0000800b4f60: 00 00 00 00 00 00 00 00 00 00 00 00[04]f9 f9 f9
  0x0000800b4f70: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b4f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b4f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b4fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b4fb0: 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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==28967==ABORTING

For poc2, ASAN says:

$ ./heap_overflow_2
=================================================================
==31104==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000000208 at pc 0x00000058b95e bp 0x7ffdc41d0710 sp 0x7ffdc41d0708
READ of size 8 at 0x603000000208 thread T0
    #0 0x58b95d in cparse::packToken::str[abi:cxx11](unsigned int) const /home/ubuntu/some_c_test/cparse/packToken.cpp:200:25
    #1 0x58b95d in cparse::packToken::str[abi:cxx11](cparse::TokenBase const*, unsigned int) /home/ubuntu/some_c_test/cparse/packToken.cpp:218
    #2 0x52bc86 in cparse::rpnBuilder::handle_token(cparse::TokenBase*) /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:220:69
    #3 0x536221 in cparse::calculator::toRPN(char const*, cparse::TokenMap, char const*, char const**, cparse::Config_t) /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:346:16
    #4 0x54cc32 in cparse::calculator::calculate(char const*, cparse::TokenMap, char const*, char const**) /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:512:27
    #5 0x518c85 in main /home/ubuntu/some_c_test/cparse/fuzz/heap_overflow_2.cc:7:21
    #6 0x7fae23be5c86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
    #7 0x41bf89 in _start (/home/ubuntu/some_c_test/cparse/fuzz/heap_overflow_2+0x41bf89)

0x603000000208 is located 0 bytes to the right of 24-byte region [0x6030000001f0,0x603000000208)
allocated by thread T0 here:
    #0 0x5143f0 in operator new(unsigned long) (/home/ubuntu/some_c_test/cparse/fuzz/heap_overflow_2+0x5143f0)
    #1 0x51c7b5 in cparse::Token<long>::clone() const /home/ubuntu/some_c_test/cparse/fuzz/../shunting-yard.h:74:12
    #2 0x52bc86 in cparse::rpnBuilder::handle_token(cparse::TokenBase*) /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:220:69
    #3 0x536221 in cparse::calculator::toRPN(char const*, cparse::TokenMap, char const*, char const**, cparse::Config_t) /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:346:16
    #4 0x54cc32 in cparse::calculator::calculate(char const*, cparse::TokenMap, char const*, char const**) /home/ubuntu/some_c_test/cparse/shunting-yard.cpp:512:27
    #5 0x518c85 in main /home/ubuntu/some_c_test/cparse/fuzz/heap_overflow_2.cc:7:21
    #6 0x7fae23be5c86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ubuntu/some_c_test/cparse/packToken.cpp:200:25 in cparse::packToken::str[abi:cxx11](unsigned int) const
Shadow bytes around the buggy address:
  0x0c067fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff8000: fa fa fd fd fd fd fa fa 00 00 00 00 fa fa fd fd
  0x0c067fff8010: fd fd fa fa 00 00 00 00 fa fa fd fd fd fa fa fa
  0x0c067fff8020: 00 00 00 fa fa fa fd fd fd fd fa fa 00 00 00 00
  0x0c067fff8030: fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00
=>0x0c067fff8040: 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==31104==ABORTING

Notes that for normal using, it seems that usage above won't happen. However for library's robustness, I report these bugs here.
Hope that helps. 😄

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions