Headline
CVE-2023-48706: heap-use-after-free in ex_substitute
Vim is a UNIX editor that, prior to version 9.0.2121, has a heap-use-after-free vulnerability. When executing a :s
command for the very first time and using a sub-replace-special atom inside the substitution part, it is possible that the recursive :s
call causes free-ing of memory which may later then be accessed by the initial :s
command. The user must intentionally execute the payload and the whole process is a bit tricky to do since it seems to work only reliably for the very first :s command. It may also cause a crash of Vim. Version 9.0.2121 contains a fix for this issue.
Affected versions
< v9.0.2121
Patched versions
v9.0.2121
Summary
vim v9.0.2034 has heap-use-after-free at /src/charset.c:1770:12 in skipwhite
Version
$ git show
commit 5a679b2263f597950f99c60a99d4d1a192e9f639 (HEAD -> master, tag: v9.0.2034, origin/master, origin/HEAD)
Author: Christian Brabandt <[email protected]>
Date: Mon Oct 16 10:17:13 2023 +0200
Platform
$ uname -a
Linux user-GE40-2PC-Dragon-Eyes 6.2.0-33-generic #33~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 7 10:33:52 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
PoC
https://github.com/gandalf4a/crash_report/blob/main/vim/vim_huaf
Reproduce
vim -u NONE -i NONE -n -m -X -Z -e -s -S poc_file -c :qa!
Asan
/home/user/fuzzing_vim/vim/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S '/home/user/fuzzing_vim/out_vim2/default/crashes/id:000000,sig:06,src:042736,time:713020002,execs:4985840,op:havoc,rep:8' -c :qa!
=================================================================
==1287672==ERROR: AddressSanitizer: heap-use-after-free on address 0x6020000089b5 at pc 0x561eaf1e0665 bp 0x7ffe75a7cc20 sp 0x7ffe75a7cc18
READ of size 1 at 0x6020000089b5 thread T0
#0 0x561eaf1e0664 in skipwhite /home/user/fuzzing_vim/vim/src/charset.c:1770:12
#1 0x561eaefda3fd in get_func_tv /home/user/fuzzing_vim/vim/src/userfunc.c:2022:9
#2 0x561eae939d9b in eval_func /home/user/fuzzing_vim/vim/src/eval.c:2563:8
#3 0x561eae938689 in eval9 /home/user/fuzzing_vim/vim/src/eval.c:4467:9
#4 0x561eae93f1bd in eval8 /home/user/fuzzing_vim/vim/src/eval.c:4028:11
#5 0x561eae93e0fb in eval7 /home/user/fuzzing_vim/vim/src/eval.c:3832:9
#6 0x561eae93c80d in eval6 /home/user/fuzzing_vim/vim/src/eval.c:3611:9
#7 0x561eae93bd95 in eval5 /home/user/fuzzing_vim/vim/src/eval.c:3500:9
#8 0x561eae93b1c5 in eval4 /home/user/fuzzing_vim/vim/src/eval.c:3351:9
#9 0x561eae93a253 in eval3 /home/user/fuzzing_vim/vim/src/eval.c:3212:9
#10 0x561eae91464a in eval2 /home/user/fuzzing_vim/vim/src/eval.c:3086:9
#11 0x561eae91464a in eval1 /home/user/fuzzing_vim/vim/src/eval.c:2932:9
#12 0x561eae9252a7 in eval0_retarg /home/user/fuzzing_vim/vim/src/eval.c:2841:11
#13 0x561eae9176b1 in eval_to_string_eap /home/user/fuzzing_vim/vim/src/eval.c
#14 0x561eaed18377 in vim_regsub_both /home/user/fuzzing_vim/vim/src/regexp.c:2112:25
#15 0x561eaed18d55 in vim_regsub_multi /home/user/fuzzing_vim/vim/src/regexp.c:1946:14
#16 0x561eae9b0800 in ex_substitute /home/user/fuzzing_vim/vim/src/ex_cmds.c:4496:12
#17 0x561eae9c80be in do_one_cmd /home/user/fuzzing_vim/vim/src/ex_docmd.c:2582:2
#18 0x561eae9c80be in do_cmdline /home/user/fuzzing_vim/vim/src/ex_docmd.c:994:17
#19 0x561eaedfbada in do_source_ext /home/user/fuzzing_vim/vim/src/scriptfile.c:1762:5
#20 0x561eae9c80be in do_one_cmd /home/user/fuzzing_vim/vim/src/ex_docmd.c:2582:2
#21 0x561eae9c80be in do_cmdline /home/user/fuzzing_vim/vim/src/ex_docmd.c:994:17
#22 0x561eaedfbada in do_source_ext /home/user/fuzzing_vim/vim/src/scriptfile.c:1762:5
#23 0x561eae9c80be in do_one_cmd /home/user/fuzzing_vim/vim/src/ex_docmd.c:2582:2
#24 0x561eae9c80be in do_cmdline /home/user/fuzzing_vim/vim/src/ex_docmd.c:994:17
#25 0x561eaedfbada in do_source_ext /home/user/fuzzing_vim/vim/src/scriptfile.c:1762:5
#26 0x561eaedf984b in do_source /home/user/fuzzing_vim/vim/src/scriptfile.c:1908:12
#27 0x561eaedf984b in cmd_source /home/user/fuzzing_vim/vim/src/scriptfile.c:1253:14
#28 0x561eae9c80be in do_one_cmd /home/user/fuzzing_vim/vim/src/ex_docmd.c:2582:2
#29 0x561eae9c80be in do_cmdline /home/user/fuzzing_vim/vim/src/ex_docmd.c:994:17
#30 0x561eaf1f47f3 in exe_commands /home/user/fuzzing_vim/vim/src/main.c:3173:2
#31 0x561eaf1f47f3 in vim_main2 /home/user/fuzzing_vim/vim/src/main.c:790:2
#32 0x561eaf1f1b8e in main /home/user/fuzzing_vim/vim/src/main.c:441:12
#33 0x7f58a3629d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#34 0x7f58a3629e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#35 0x561eae711264 in _start (/home/user/fuzzing_vim/vim/src/vim+0x1ea264) (BuildId: 0ffce6a72ff4fc85410d48d0995022f3450941d7)
0x6020000089b5 is located 5 bytes inside of 15-byte region [0x6020000089b0,0x6020000089bf)
freed by thread T0 here:
#0 0x561eae793e02 in free (/home/user/fuzzing_vim/vim/src/vim+0x26ce02) (BuildId: 0ffce6a72ff4fc85410d48d0995022f3450941d7)
#1 0x561eae9b2e04 in ex_substitute /home/user/fuzzing_vim/vim/src/ex_cmds.c:3848:3
#2 0x561eae9c80be in do_one_cmd /home/user/fuzzing_vim/vim/src/ex_docmd.c:2582:2
#3 0x561eae9c80be in do_cmdline /home/user/fuzzing_vim/vim/src/ex_docmd.c:994:17
#4 0x561eaefe2599 in call_user_func /home/user/fuzzing_vim/vim/src/userfunc.c:3110:2
#5 0x561eaefe2599 in call_user_func_check /home/user/fuzzing_vim/vim/src/userfunc.c:3283:10
#6 0x561eaefdc580 in call_func /home/user/fuzzing_vim/vim/src/userfunc.c:3907:15
#7 0x561eaefda270 in get_func_tv /home/user/fuzzing_vim/vim/src/userfunc.c:1997:8
#8 0x561eae939d9b in eval_func /home/user/fuzzing_vim/vim/src/eval.c:2563:8
#9 0x561eae938689 in eval9 /home/user/fuzzing_vim/vim/src/eval.c:4467:9
#10 0x561eae93f1bd in eval8 /home/user/fuzzing_vim/vim/src/eval.c:4028:11
#11 0x561eae93e0fb in eval7 /home/user/fuzzing_vim/vim/src/eval.c:3832:9
#12 0x561eae93c80d in eval6 /home/user/fuzzing_vim/vim/src/eval.c:3611:9
#13 0x561eae93bd95 in eval5 /home/user/fuzzing_vim/vim/src/eval.c:3500:9
#14 0x561eae93b1c5 in eval4 /home/user/fuzzing_vim/vim/src/eval.c:3351:9
#15 0x561eae93a253 in eval3 /home/user/fuzzing_vim/vim/src/eval.c:3212:9
#16 0x561eae91464a in eval2 /home/user/fuzzing_vim/vim/src/eval.c:3086:9
#17 0x561eae91464a in eval1 /home/user/fuzzing_vim/vim/src/eval.c:2932:9
#18 0x561eae9252a7 in eval0_retarg /home/user/fuzzing_vim/vim/src/eval.c:2841:11
#19 0x561eae9176b1 in eval_to_string_eap /home/user/fuzzing_vim/vim/src/eval.c
#20 0x561eaed18377 in vim_regsub_both /home/user/fuzzing_vim/vim/src/regexp.c:2112:25
#21 0x561eaed18d55 in vim_regsub_multi /home/user/fuzzing_vim/vim/src/regexp.c:1946:14
#22 0x561eae9b0800 in ex_substitute /home/user/fuzzing_vim/vim/src/ex_cmds.c:4496:12
#23 0x561eae9c80be in do_one_cmd /home/user/fuzzing_vim/vim/src/ex_docmd.c:2582:2
#24 0x561eae9c80be in do_cmdline /home/user/fuzzing_vim/vim/src/ex_docmd.c:994:17
#25 0x561eaefe2599 in call_user_func /home/user/fuzzing_vim/vim/src/userfunc.c:3110:2
#26 0x561eaefe2599 in call_user_func_check /home/user/fuzzing_vim/vim/src/userfunc.c:3283:10
#27 0x561eaefdc580 in call_func /home/user/fuzzing_vim/vim/src/userfunc.c:3907:15
#28 0x561eaefda270 in get_func_tv /home/user/fuzzing_vim/vim/src/userfunc.c:1997:8
#29 0x561eae939d9b in eval_func /home/user/fuzzing_vim/vim/src/eval.c:2563:8
#30 0x561eae938689 in eval9 /home/user/fuzzing_vim/vim/src/eval.c:4467:9
#31 0x561eae93f1bd in eval8 /home/user/fuzzing_vim/vim/src/eval.c:4028:11
#32 0x561eae93e0fb in eval7 /home/user/fuzzing_vim/vim/src/eval.c:3832:9
#33 0x561eae93c80d in eval6 /home/user/fuzzing_vim/vim/src/eval.c:3611:9
#34 0x561eae93bd95 in eval5 /home/user/fuzzing_vim/vim/src/eval.c:3500:9
previously allocated by thread T0 here:
#0 0x561eae7940ae in __interceptor_malloc (/home/user/fuzzing_vim/vim/src/vim+0x26d0ae) (BuildId: 0ffce6a72ff4fc85410d48d0995022f3450941d7)
#1 0x561eae7cf2d7 in lalloc /home/user/fuzzing_vim/vim/src/alloc.c:246:11
SUMMARY: AddressSanitizer: heap-use-after-free /home/user/fuzzing_vim/vim/src/charset.c:1770:12 in skipwhite
Shadow bytes around the buggy address:
0x0c047fff90e0: fa fa 00 07 fa fa 00 02 fa fa 00 05 fa fa 05 fa
0x0c047fff90f0: fa fa 00 00 fa fa 00 04 fa fa 02 fa fa fa 07 fa
0x0c047fff9100: fa fa 00 04 fa fa 01 fa fa fa fd fa fa fa fd fa
0x0c047fff9110: fa fa fd fd fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff9120: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd
=>0x0c047fff9130: fa fa fd fd fa fa[fd]fd fa fa fd fd fa fa fd fd
0x0c047fff9140: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd
0x0c047fff9150: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fd
0x0c047fff9160: fa fa fd fd fa fa 00 01 fa fa 00 01 fa fa fd fa
0x0c047fff9170: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
0x0c047fff9180: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd 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
==1287672==ABORTING
Credit****Description of the issue****CVE-2023-48706: Use-After-Free in ex_substitute()
Date: 22.11.2023
Severity: Low
When executing a :s command for the very first time and using a sub-replace-special atom
inside the substitution part, it is possible that the recursive :s call causes free-ing
of memory which may later then be accessed by the initial :s comamnd.
Impact is low since the user must intentionally execute the payload and
the whole process is a bit tricky to do (since it seems to work only
reliably for the very first :s command). It may also cause a crash of Vim.
The Vim project would like to thank github user gandalf4a for reporting this issue
which is now fixed in Vim patch 9.0.2121.
Related news
Ubuntu Security Notice 6557-1 - It was discovered that Vim could be made to dereference invalid memory. An attacker could possibly use this issue to cause a denial of service. This issue only affected Ubuntu 18.04 LTS, Ubuntu 20.04 LTS, and Ubuntu 22.04 LTS. It was discovered that Vim could be made to recurse infinitely. An attacker could possibly use this issue to cause a denial of service. This issue only affected Ubuntu 14.04 LTS, Ubuntu 16.04 LTS, Ubuntu 18.04 LTS, Ubuntu 20.04 LTS, and Ubuntu 22.04 LTS.