This vulnerability is of use-after-free. The bug exists in latest stable release (radare2-5.5.4). Specifically, the vulnerable code is picked out as follows (libr/io/io_bank.c
):
// ./libr/io/io_bank.c line 229
// the entry->data is a freed pointer address
while (entry && r_io_submap_to (((RIOSubMap *)entry->data)) <= r_io_submap_to (sm)) {
//delete all submaps that are completly included in sm
RRBNode *next = r_rbnode_next (entry);
// this can be optimized, there is no need to do search here
r_crbtree_delete (bank->submaps, entry->data, _find_sm_by_from_vaddr_cb, NULL);
entry = next;
}
Build the radare2 5.5.4 with address sanitizer, download the POC_FILE. Then run
# disable some features of address sanitizer to avoid false positive
export ASAN_OPTIONS=detect_leaks=0:abort_on_error=1:symbolize=0:allocator_may_return_null=1:detect_odr_violation=0
# trigger the crash
radare2 -A -q POC_FILE
The crash stack information is:
=================================================================
==7874==ERROR: AddressSanitizer: heap-use-after-free on address 0x604001aa8d30 at pc 0x7ffff70e69e6 bp 0x7fffffffcf40 sp 0x7fffffffcf38
READ of size 8 at 0x604001aa8d30 thread T0
#0 0x7ffff70e69e5 (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_io.so+0xe29e5)
#1 0x7ffff70b8d9c (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_io.so+0xb4d9c)
#2 0x7ffff381a410 (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_core.so+0x7f8410)
#3 0x7ffff37e2b3a (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_core.so+0x7c0b3a)
#4 0x7ffff37e159d (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_core.so+0x7bf59d)
#5 0x7ffff36a9556 (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_core.so+0x687556)
#6 0x7ffff763b6f3 (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_main.so+0x906f3)
#7 0x7ffff73b80b2 (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#8 0x55555557239d (/src/projects/radare2-5.5.4/radare2/install-asan/bin/radare2+0x1e39d)
0x604001aa8d30 is located 32 bytes inside of 40-byte region [0x604001aa8d10,0x604001aa8d38)
freed by thread T0 here:
#0 0x5555555ed392 (/src/projects/radare2-5.5.4/radare2/install-asan/bin/radare2+0x99392)
#1 0x7ffff7b37d39 (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_util.so+0x4b3d39)
#2 0x7ffff7b38fb3 (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_util.so+0x4b4fb3)
previously allocated by thread T0 here:
#0 0x5555555ed772 (/src/projects/radare2-5.5.4/radare2/install-asan/bin/radare2+0x99772)
#1 0x7ffff7b3368a (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_util.so+0x4af68a)
#2 0x7ffff70e5700 (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_io.so+0xe1700)
SUMMARY: AddressSanitizer: heap-use-after-free (/src/projects/radare2-5.5.4/radare2/install-asan/lib/libr_io.so+0xe29e5)
Shadow bytes around the buggy address:
0x0c088034d150: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d160: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d170: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d180: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
0x0c088034d190: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
=>0x0c088034d1a0: fa fa fd fd fd fd[fd]fa fa fa fd fd fd fd fd fa
0x0c088034d1b0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
0x0c088034d1c0: fa fa 00 00 00 00 00 fa fa fa fd fd fd fd fd fa
0x0c088034d1d0: fa fa 00 00 00 00 00 fa fa fa fd fd fd fd fd fa
0x0c088034d1e0: fa fa 00 00 00 00 00 fa fa fa fd fd fd fd fd fa
0x0c088034d1f0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 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
==7874==ABORTING
#0 0x00007ffff73d718b in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff73b6859 in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x000055555560ba77 in __sanitizer::Abort() ()
#3 0x0000555555609fa1 in __sanitizer::Die() ()
#4 0x00005555555f14e4 in __asan::ScopedInErrorReport::~ScopedInErrorReport() ()
#5 0x00005555555f30aa in __asan::ReportGenericError(unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long, unsigned int, bool) ()
#6 0x00005555555f3948 in __asan_report_load8 ()
#7 0x00007ffff70e69e6 in r_io_bank_map_add_top (io=<optimized out>, bankid=<optimized out>, mapid=<optimized out>) at io_bank.c:229
#8 0x00007ffff70b8d9d in r_io_map_add (io=0x61b000001c80, fd=<optimized out>, perm=<optimized out>, delta=<optimized out>, addr=<optimized out>, size=<optimized out>) at io_map.c:158
#9 0x00007ffff381a411 in add_section (core=0x7fffec26a800, sec=0x60200037fd70, addr=18446744073709495128, fd=-16512) at cbin.c:2681
#10 bin_sections (r=0x7fffec26a800, pj=<optimized out>, mode=<optimized out>, laddr=<optimized out>, va=<optimized out>, at=<optimized out>, name=<optimized out>, chksum=<optimized out>, print_segments=<optimized out>) at cbin.c:3096
#11 0x00007ffff37e2b3b in r_core_bin_info (core=0x7fffec26a800, action=<optimized out>, pj=<optimized out>, mode=<optimized out>, va=1, filter=<optimized out>, chksum=<optimized out>) at cbin.c:4221
#12 0x00007ffff37e159e in r_core_bin_set_env (r=0x7fffec26a800, binfile=<optimized out>) at cbin.c:340
#13 0x00007ffff36a9557 in r_core_file_do_load_for_io_plugin (r=0x7fffec26a800, baseaddr=18446744073709551615, loadaddr=0) at cfile.c:439
#14 r_core_bin_load (r=0x7fffec26a800, filenameuri=<optimized out>, baddr=<optimized out>) at cfile.c:635
#15 0x00007ffff763b6f4 in r_main_radare2 (argc=<optimized out>, argv=<optimized out>) at radare2.c:1176
#16 0x00007ffff73b80b3 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#17 0x000055555557239e in _start ()
The bug is of Heap-use-after-free. The POC attached here can be directly used to launch DoS attack. Besides, it is very possible for the attacker to finally accomplish RCE (Remote Code Execution).