Skip to content

heap-use-after-free in ex_substitute

Low
chrisbra published GHSA-c8qm-x72m-q53q Nov 22, 2023

Package

Vim

Affected versions

< v9.0.2121

Patched versions

v9.0.2121

Description

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 <cb@256bit.org>
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

Gandalf4a

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.

Severity

Low
3.6
/ 10

CVSS base metrics

Attack vector
Local
Attack complexity
High
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
Low
CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:L

CVE ID

No known CVE

Weaknesses

No CWEs

Credits