Whilst experimenting with radare2
, built from version 5.6.8, we are able to induce a vulnerability at new_rbtree.c:411
in function r_rbnode_next
, using radare2
as a harness.
409: R_API RRBNode *r_rbnode_next(RRBNode *node) {
410: r_return_val_if_fail (node, NULL);
//use-after-free here
411: if (node->link[1]) {
412: node = node->link[1];
413: while (node->link[0]) {
414: node = node->link[0];
415: }
416: return node;
417: }
418: RRBNode *parent = node->parent;
419: while (parent && parent->link[1] == node) {
420: node = parent;
421: parent = node->parent;
422: }
423: return parent;
424: }
Due to not properly handling pointers, a heap-based use-after-free will be triggered when the software encounters a malformed file, which could result in denial of service.
We found that the vulnerability exists in the latest master branch as well.
Ubuntu 20.04 LTS x86_64
gcc 10.3.0
The POC is: poc
The reproducing process is:
# build with address sanitizer
SANITIZE=address ./sys/sanitize.sh
# disable some features of address sanitizer to avoid false positives
export ASAN_OPTIONS=detect_leaks=0:abort_on_error=1:symbolize=1:allocator_may_return_null=1:detect_odr_violation=0
# trigger the crash
./radare2 -A -q POC_FILE
The ASAN report is:
=================================================================
==119195==ERROR: AddressSanitizer: heap-use-after-free on address 0x604001aab958 at pc 0x7ffff73a7e3d bp 0x7fffffffd6c0 sp 0x7fffffffd6b0
READ of size 8 at 0x604001aab958 thread T0
#0 0x7ffff73a7e3c in r_rbnode_next /work/libraries/radare2-version/libr/util/new_rbtree.c:411
#1 0x7ffff6c489a6 in r_io_bank_map_add_top /work/libraries/radare2-version/libr/io/io_bank.c:240
#2 0x7ffff6c37454 in r_io_map_add /work/libraries/radare2-version/libr/io/io_map.c:158
#3 0x7ffff46dc4ba in add_section /work/libraries/radare2-version/libr/core/cbin.c:2704
#4 0x7ffff46e0134 in bin_sections /work/libraries/radare2-version/libr/core/cbin.c:3120
#5 0x7ffff46e7f24 in r_core_bin_info /work/libraries/radare2-version/libr/core/cbin.c:4256
#6 0x7ffff46c9a6b in r_core_bin_set_env /work/libraries/radare2-version/libr/core/cbin.c:349
#7 0x7ffff463e893 in r_core_file_do_load_for_io_plugin /work/libraries/radare2-version/libr/core/cfile.c:440
#8 0x7ffff464014f in r_core_bin_load /work/libraries/radare2-version/libr/core/cfile.c:636
#9 0x7ffff7182a0d in r_main_radare2 /work/libraries/radare2-version/libr/main/radare2.c:1189
#10 0x5555555556ff in main /work/libraries/radare2-version/binr/radare2/radare2.c:96
#11 0x7ffff6f6a0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#12 0x55555555528d in _start (/work/libraries/radare2-version/binr/radare2/radare2+0x128d)
0x604001aab958 is located 8 bytes inside of 40-byte region [0x604001aab950,0x604001aab978)
freed by thread T0 here:
#0 0x7ffff769b8f7 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127
#1 0x7ffff73a786f in r_crbtree_take /work/libraries/radare2-version/libr/util/new_rbtree.c:359
#2 0x7ffff73a7b53 in r_crbtree_delete /work/libraries/radare2-version/libr/util/new_rbtree.c:376
#3 0x7ffff6c48a5d in r_io_bank_map_add_top /work/libraries/radare2-version/libr/io/io_bank.c:244
#4 0x7ffff6c37454 in r_io_map_add /work/libraries/radare2-version/libr/io/io_map.c:158
#5 0x7ffff46dc4ba in add_section /work/libraries/radare2-version/libr/core/cbin.c:2704
#6 0x7ffff46e0134 in bin_sections /work/libraries/radare2-version/libr/core/cbin.c:3120
#7 0x7ffff46e7f24 in r_core_bin_info /work/libraries/radare2-version/libr/core/cbin.c:4256
#8 0x7ffff46c9a6b in r_core_bin_set_env /work/libraries/radare2-version/libr/core/cbin.c:349
#9 0x7ffff463e893 in r_core_file_do_load_for_io_plugin /work/libraries/radare2-version/libr/core/cfile.c:440
#10 0x7ffff464014f in r_core_bin_load /work/libraries/radare2-version/libr/core/cfile.c:636
#11 0x7ffff7182a0d in r_main_radare2 /work/libraries/radare2-version/libr/main/radare2.c:1189
#12 0x5555555556ff in main /work/libraries/radare2-version/binr/radare2/radare2.c:96
#13 0x7ffff6f6a0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
previously allocated by thread T0 here:
#0 0x7ffff769be17 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
#1 0x7ffff73a5308 in _node_new /work/libraries/radare2-version/libr/util/new_rbtree.c:104
#2 0x7ffff73a58cd in r_crbtree_insert /work/libraries/radare2-version/libr/util/new_rbtree.c:161
#3 0x7ffff6c48307 in r_io_bank_map_add_top /work/libraries/radare2-version/libr/io/io_bank.c:181
#4 0x7ffff6c37454 in r_io_map_add /work/libraries/radare2-version/libr/io/io_map.c:158
#5 0x7ffff6c30f3d in r_io_open_at /work/libraries/radare2-version/libr/io/io.c:90
#6 0x7ffff46dc047 in io_create_mem_map /work/libraries/radare2-version/libr/core/cbin.c:2652
#7 0x7ffff46dc318 in add_section /work/libraries/radare2-version/libr/core/cbin.c:2683
#8 0x7ffff46e0134 in bin_sections /work/libraries/radare2-version/libr/core/cbin.c:3120
#9 0x7ffff46e7f24 in r_core_bin_info /work/libraries/radare2-version/libr/core/cbin.c:4256
#10 0x7ffff46c9a6b in r_core_bin_set_env /work/libraries/radare2-version/libr/core/cbin.c:349
#11 0x7ffff463e893 in r_core_file_do_load_for_io_plugin /work/libraries/radare2-version/libr/core/cfile.c:440
#12 0x7ffff464014f in r_core_bin_load /work/libraries/radare2-version/libr/core/cfile.c:636
#13 0x7ffff7182a0d in r_main_radare2 /work/libraries/radare2-version/libr/main/radare2.c:1189
#14 0x5555555556ff in main /work/libraries/radare2-version/binr/radare2/radare2.c:96
#15 0x7ffff6f6a0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: heap-use-after-free /work/libraries/radare2-version/libr/util/new_rbtree.c:411 in r_rbnode_next
Shadow bytes around the buggy address:
0x0c088034d6d0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d6e0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d6f0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d700: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d710: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00 fa
=>0x0c088034d720: fa fa 00 00 00 00 00 fa fa fa fd[fd]fd fd fd fa
0x0c088034d730: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00 fa
0x0c088034d740: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d750: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
0x0c088034d760: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
0x0c088034d770: 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
Shadow gap: cc
==119195==ABORTING
Aborted
This vulnerability was found by Xingyuan Mo from 360 IceSword Lab