RHEL-155438 CVE-2026-28417 vim: Vim: Arbitrary code execution via OS command injection in the netrw plugin
Resolves: RHEL-155438
This commit is contained in:
parent
134732a8be
commit
8203ae04cd
@ -0,0 +1,56 @@
|
||||
diff -up vim91/runtime/autoload/netrw.vim.CVE-2026-28417 vim91/runtime/autoload/netrw.vim
|
||||
--- vim91/runtime/autoload/netrw.vim.CVE-2026-28417 2026-03-17 19:22:17.101915588 +0100
|
||||
+++ vim91/runtime/autoload/netrw.vim 2026-03-17 19:32:29.134514079 +0100
|
||||
@@ -3376,13 +3376,26 @@ endif
|
||||
|
||||
" s:NetrwValidateHostname: Validate that the hostname is valid {{{2
|
||||
" Input:
|
||||
-" hostname
|
||||
+" hostname, may include an optional username, e.g. user@hostname
|
||||
+" allow a alphanumeric hostname or an IPv(4/6) address
|
||||
" Output:
|
||||
" true if g:netrw_machine is valid according to RFC1123 #Section 2
|
||||
fun! s:NetrwValidateHostname(hostname)
|
||||
- " RFC1123#section-2 mandates, a valid hostname starts with letters or digits
|
||||
- " so reject everyhing else
|
||||
- return a:hostname =~? '^[a-z0-9]'
|
||||
+ " Username:
|
||||
+ let user_pat = '\%([a-zA-Z0-9._-]\+@\)\?'
|
||||
+ " Hostname: 1-64 chars, alphanumeric/dots/hyphens.
|
||||
+ " No underscores. No leading/trailing dots/hyphens.
|
||||
+ let host_pat = '[a-zA-Z0-9]\%([-a-zA-Z0-9.]{,62}[a-zA-Z0-9]\)\?$'
|
||||
+
|
||||
+ " IPv4: 1-3 digits separated by dots
|
||||
+ let ipv4_pat = '\%(\d\{1,3}\.\)\{3\}\d\{1,3\}$'
|
||||
+
|
||||
+ " IPv6: Hex, colons, and optional brackets
|
||||
+ let ipv6_pat = '\[\?\%([a-fA-F0-9:]\{2,}\)\+\]\?$'
|
||||
+
|
||||
+ return a:hostname =~? '^'.user_pat.host_pat ||
|
||||
+ \ a:hostname =~? '^'.user_pat.ipv4_pat ||
|
||||
+ \ a:hostname =~? '^'.user_pat.ipv6_pat
|
||||
endfun
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
@@ -11880,15 +11893,15 @@ endfun
|
||||
" a correct command for use with a system() call
|
||||
fun! s:MakeSshCmd(sshcmd)
|
||||
" call Dfunc("s:MakeSshCmd(sshcmd<".a:sshcmd.">) user<".s:user."> machine<".s:machine.">")
|
||||
- if s:user == ""
|
||||
- let sshcmd = substitute(a:sshcmd,'\<HOSTNAME\>',s:machine,'')
|
||||
- else
|
||||
- let sshcmd = substitute(a:sshcmd,'\<HOSTNAME\>',s:user."@".s:machine,'')
|
||||
+ let machine = shellescape(s:machine, 1)
|
||||
+ if s:user != ''
|
||||
+ let machine = shellescape(s:user, 1).'@'.machine
|
||||
endif
|
||||
+ let sshcmd = substitute(a:sshcmd,'\<HOSTNAME\>',machine,'')
|
||||
if exists("g:netrw_port") && g:netrw_port != ""
|
||||
- let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.g:netrw_port,'')
|
||||
+ let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.shellescape(g:netrw_port,1),'')
|
||||
elseif exists("s:port") && s:port != ""
|
||||
- let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.s:port,'')
|
||||
+ let sshcmd= substitute(sshcmd,"USEPORT",g:netrw_sshport.' '.shellescape(s:port,1),'')
|
||||
else
|
||||
let sshcmd= substitute(sshcmd,"USEPORT ",'','')
|
||||
endif
|
||||
@ -0,0 +1,39 @@
|
||||
diff -up vim91/runtime/autoload/netrw.vim.validateportnum vim91/runtime/autoload/netrw.vim
|
||||
--- vim91/runtime/autoload/netrw.vim.validateportnum 2026-03-17 19:35:34.062575124 +0100
|
||||
+++ vim91/runtime/autoload/netrw.vim 2026-03-17 19:39:39.005999509 +0100
|
||||
@@ -3376,7 +3376,8 @@ endif
|
||||
|
||||
" s:NetrwValidateHostname: Validate that the hostname is valid {{{2
|
||||
" Input:
|
||||
-" hostname, may include an optional username, e.g. user@hostname
|
||||
+" hostname, may include an optional username and port number, e.g.
|
||||
+" user@hostname:port
|
||||
" allow a alphanumeric hostname or an IPv(4/6) address
|
||||
" Output:
|
||||
" true if g:netrw_machine is valid according to RFC1123 #Section 2
|
||||
@@ -3385,17 +3386,19 @@ fun! s:NetrwValidateHostname(hostname)
|
||||
let user_pat = '\%([a-zA-Z0-9._-]\+@\)\?'
|
||||
" Hostname: 1-64 chars, alphanumeric/dots/hyphens.
|
||||
" No underscores. No leading/trailing dots/hyphens.
|
||||
- let host_pat = '[a-zA-Z0-9]\%([-a-zA-Z0-9.]{,62}[a-zA-Z0-9]\)\?$'
|
||||
+ let host_pat = '[a-zA-Z0-9]\%([-a-zA-Z0-9.]\{0,62}[a-zA-Z0-9]\)\?'
|
||||
+ " Port: 16 bit unsigned integer
|
||||
+ let port_pat = '\%(:\d\{1,5\}\)\?$'
|
||||
|
||||
" IPv4: 1-3 digits separated by dots
|
||||
- let ipv4_pat = '\%(\d\{1,3}\.\)\{3\}\d\{1,3\}$'
|
||||
+ let ipv4_pat = '\%(\d\{1,3}\.\)\{3\}\d\{1,3\}'
|
||||
|
||||
" IPv6: Hex, colons, and optional brackets
|
||||
- let ipv6_pat = '\[\?\%([a-fA-F0-9:]\{2,}\)\+\]\?$'
|
||||
+ let ipv6_pat = '\[\?\%([a-fA-F0-9:]\{2,}\)\+\]\?'
|
||||
|
||||
- return a:hostname =~? '^'.user_pat.host_pat ||
|
||||
- \ a:hostname =~? '^'.user_pat.ipv4_pat ||
|
||||
- \ a:hostname =~? '^'.user_pat.ipv6_pat
|
||||
+ return a:hostname =~? '^'.user_pat.host_pat.port_pat ||
|
||||
+ \ a:hostname =~? '^'.user_pat.ipv4_pat.port_pat ||
|
||||
+ \ a:hostname =~? '^'.user_pat.ipv6_pat.port_pat
|
||||
endfun
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
65
0001-runtime-netrw-upstream-snapshot-of-v179.patch
Normal file
65
0001-runtime-netrw-upstream-snapshot-of-v179.patch
Normal file
@ -0,0 +1,65 @@
|
||||
diff -up vim91/runtime/autoload/netrw.vim.validatehostname vim91/runtime/autoload/netrw.vim
|
||||
--- vim91/runtime/autoload/netrw.vim.validatehostname 2024-02-09 06:33:54.000000000 +0100
|
||||
+++ vim91/runtime/autoload/netrw.vim 2026-03-17 19:16:22.210561235 +0100
|
||||
@@ -1453,6 +1453,10 @@ fun! netrw#Obtain(islocal,fname,...)
|
||||
call s:SetupNetrwStatusLine('%f %h%m%r%=%9*Obtaining '.a:fname)
|
||||
endif
|
||||
call s:NetrwMethod(b:netrw_curdir)
|
||||
+ if !s:NetrwValidateHostname(g:netrw_machine)
|
||||
+ call netrw#ErrorMsg(s:ERROR,"Rejecting invalid hostname: <" .. g:netrw_machine .. ">",107)
|
||||
+ return
|
||||
+ endif
|
||||
|
||||
if b:netrw_method == 4
|
||||
" obtain file using scp
|
||||
@@ -2143,6 +2147,10 @@ fun! netrw#NetRead(mode,...)
|
||||
" call Dret("netrw#NetRead : unsupported method")
|
||||
return
|
||||
endif
|
||||
+ if !s:NetrwValidateHostname(g:netrw_machine)
|
||||
+ call netrw#ErrorMsg(s:ERROR,"Rejecting invalid hostname: <" .. g:netrw_machine .. ">",107)
|
||||
+ return
|
||||
+ endif
|
||||
let tmpfile= s:GetTempfile(b:netrw_fname) " apply correct suffix
|
||||
|
||||
" Check whether or not NetrwBrowse() should be handling this request
|
||||
@@ -2565,6 +2573,10 @@ fun! netrw#NetWrite(...) range
|
||||
" call Dfunc("netrw#NetWrite : unsupported method")
|
||||
return
|
||||
endif
|
||||
+ if !s:NetrwValidateHostname(g:netrw_machine)
|
||||
+ call netrw#ErrorMsg(s:ERROR,"Rejecting invalid hostname: <" .. g:netrw_machine .. ">",107)
|
||||
+ return
|
||||
+ endif
|
||||
|
||||
" =============
|
||||
" NetWrite: Perform Protocol-Based Write {{{3
|
||||
@@ -3362,6 +3374,17 @@ if has("win95") && exists("g:netrw_win95
|
||||
endfun
|
||||
endif
|
||||
|
||||
+" s:NetrwValidateHostname: Validate that the hostname is valid {{{2
|
||||
+" Input:
|
||||
+" hostname
|
||||
+" Output:
|
||||
+" true if g:netrw_machine is valid according to RFC1123 #Section 2
|
||||
+fun! s:NetrwValidateHostname(hostname)
|
||||
+ " RFC1123#section-2 mandates, a valid hostname starts with letters or digits
|
||||
+ " so reject everyhing else
|
||||
+ return a:hostname =~? '^[a-z0-9]'
|
||||
+endfun
|
||||
+
|
||||
" ---------------------------------------------------------------------
|
||||
" NetUserPass: set username and password for subsequent ftp transfer {{{2
|
||||
" Usage: :call NetUserPass() -- will prompt for userid and password
|
||||
@@ -8842,6 +8865,10 @@ fun! s:NetrwUpload(fname,tgt,...)
|
||||
|
||||
elseif a:tgt =~ '^ftp:'
|
||||
call s:NetrwMethod(a:tgt)
|
||||
+ if !s:NetrwValidateHostname(g:netrw_machine)
|
||||
+ call netrw#ErrorMsg(s:ERROR,"Rejecting invalid hostname: <" .. g:netrw_machine .. ">",107)
|
||||
+ return
|
||||
+ endif
|
||||
|
||||
if b:netrw_method == 2
|
||||
" handle uploading a list of files via ftp+.netrc
|
||||
21
vim.spec
21
vim.spec
@ -27,7 +27,7 @@ Summary: The VIM editor
|
||||
URL: http://www.vim.org/
|
||||
Name: vim
|
||||
Version: %{baseversion}.%{patchlevel}
|
||||
Release: 25%{?dist}
|
||||
Release: 26%{?dist}
|
||||
License: Vim and MIT
|
||||
Source0: ftp://ftp.vim.org/pub/vim/unix/vim-%{baseversion}-%{patchlevel}.tar.bz2
|
||||
Source1: virc
|
||||
@ -155,6 +155,15 @@ Patch3057: 0001-patch-9.1.1551-security-path-traversal-issue-in-zip..patch
|
||||
# 0001-patch-9.1.2133-Another-case-of-buffer-overflow-with-.patch
|
||||
Patch3058: 0001-patch-9.1.2132-security-buffer-overflow-in-helpfile-.patch
|
||||
Patch3059: 0001-patch-9.1.2133-Another-case-of-buffer-overflow-with-.patch
|
||||
# RHEL-155438 CVE-2026-28417 vim: Vim: Arbitrary code execution via OS command injection in the netrw plugin
|
||||
# 3 patches:
|
||||
# 0001-runtime-netrw-upstream-snapshot-of-v179.patch - introduces NetrwValidateHostname
|
||||
# 0001-patch-9.2.0073-security-possible-command-injection-u.patch - CVE patch which sanitizes hostnames
|
||||
# and reports invalid characters in SSH commands
|
||||
# 0001-patch-9.2.0089-netrw-does-not-take-port-into-account.patch - include portnumber in hostname checking
|
||||
Patch3060: 0001-runtime-netrw-upstream-snapshot-of-v179.patch
|
||||
Patch3061: 0001-patch-9.2.0073-security-possible-command-injection-u.patch
|
||||
Patch3062: 0001-patch-9.2.0089-netrw-does-not-take-port-into-account.patch
|
||||
|
||||
|
||||
# gcc is no longer in buildroot by default
|
||||
@ -402,6 +411,9 @@ perl -pi -e "s,bin/nawk,bin/awk,g" runtime/tools/mve.awk
|
||||
%patch -P 3057 -p1 -b .CVE-2025-53906
|
||||
%patch -P 3058 -p1 -b .tag-overflow
|
||||
%patch -P 3059 -p1 -b .tag-overflow2
|
||||
%patch -P 3060 -p1 -b .validatehostname
|
||||
%patch -P 3061 -p1 -b .CVE-2026-28417
|
||||
%patch -P 3062 -p1 -b .validateportnum
|
||||
|
||||
%build
|
||||
cd src
|
||||
@ -410,8 +422,8 @@ autoconf
|
||||
sed -e "s+VIMRCLOC = \$(VIMLOC)+VIMRCLOC = /etc+" Makefile > Makefile.tmp
|
||||
mv -f Makefile.tmp Makefile
|
||||
|
||||
export CFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2"
|
||||
export CXXFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2"
|
||||
export CFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -O0"
|
||||
export CXXFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -O0"
|
||||
|
||||
cp -f os_unix.h os_unix.h.save
|
||||
cp -f ex_cmds.c ex_cmds.c.save
|
||||
@ -954,6 +966,9 @@ touch %{buildroot}/%{_datadir}/%{name}/vimfiles/doc/tags
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Mar 19 2026 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-26
|
||||
- RHEL-155438 CVE-2026-28417 vim: Vim: Arbitrary code execution via OS command injection in the netrw plugin
|
||||
|
||||
* Tue Feb 10 2026 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-25
|
||||
- RHEL-147941 CVE-2026-25749 vim: Heap Overflow in Vim
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user