![vim 如何窃取 root 拥有的文件?](https://linux22.com/image/43877/vim%20%E5%A6%82%E4%BD%95%E7%AA%83%E5%8F%96%20root%20%E6%8B%A5%E6%9C%89%E7%9A%84%E6%96%87%E4%BB%B6%EF%BC%9F.png)
见证以下情况:
sh-3.2$ mkdir testcase
sh-3.2$ cd testcase
sh-3.2$ sudo touch temp
sh-3.2$ ls -al
total 0
drwxr-xr-x 3 glen staff 102 19 Dec 12:38 .
drwxr-xr-x 12 glen staff 408 19 Dec 12:38 ..
-rw-r--r-- 1 root staff 0 19 Dec 12:38 temp
sh-3.2$ echo nope > temp
sh: temp: Permission denied
sh-3.2$ vim temp
# inside vim
itheivery
# press [ESC]
:wq!
# vim exits
sh-3.2$ ls -al
total 8
drwxr-xr-x 3 glen staff 102 19 Dec 12:38 .
drwxr-xr-x 12 glen staff 408 19 Dec 12:38 ..
-rw-r--r-- 1 glen staff 7 19 Dec 12:38 temp
不知何故,vim 获取了这个 root 拥有的文件,并将其更改为用户拥有的文件!
这似乎只有在用户拥有该目录时才有效 - 但仍然感觉这是不可能的。谁能解释这是如何完成的?
答案1
您glen
是 的所有者目录(请参阅.
清单中的文件)。目录只是文件列表,您有权更改此列表(例如添加文件、删除文件、更改所有权以使其再次属于您,等等)。您可能无法更改内容直接读取文件,但您可以读取并取消链接(删除)整个文件并随后添加新文件。1只见证前后,这可能看起来像该文件已被更改。
Vim 使用交换文件并在水下移动文件,这解释了为什么它似乎写入与 shell 中相同的文件,但这不是同一件事。2
所以,Vim 所做的事情可以归结为:
cat temp > .temp.swp # copy file by contents into a new glen-owned file
echo nope >> .temp.swp # or other command to alter the new file
rm temp && mv .temp.swp temp # move temporary swap file back
1这是 Windows 和 Unices 之间文件权限处理的一个重要区别。在 Windows 中,通常无法删除您没有写入权限的文件。
2更新:正如评论中所指出的,Vim 实际上并没有这样做来更改所有权,因为文件上的 inode 号temp
没有改变(ls -li
前后比较)。使用strace
我们可以确切地看到它的vim
作用。有趣的部分在这里:
open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = -1 EACCES (Permission denied)
unlink("temp") = 0
open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = 4
write(4, "more text bla\n", 14) = 14
close(4) = 0
chmod("temp", 0664) = 0
这表明它仅取消链接,但不关闭文件描述符到temp
.它只是覆盖其全部内容(more text bla\n
在我的例子中)。我想这解释了为什么索引节点号没有改变。
答案2
前:
-rw-r--r-- 1 root staff 0 19 Dec 12:38 temp
后:
-rw-r--r-- 1 glen staff 7 19 Dec 12:38 temp
vim并没有突破权限屏障。只要仔细看一下列出的文件信息,你就会发现vim实际上删除了原始文件(因为你有权限删除该文件,但你不能更改它的内容),然后创建了一个你自己的新文件(看到所有者不再是“root”)。
当您在 vim 中编辑原始文件时,它会警告您正在更改只读文件。所以当你输入命令:wq!
(强制操作)时,vim 只能删除现有文件并创建一个同名的新文件。
希望有帮助。
答案3
使用-i
选项ls
查看索引节点号,它是文件或其他对象的唯一标识符(在文件系统内)。
您将看到该文件被替换为不同的对象:inode 号可能会发生变化。
看到相同的索引节点号并不能证明任何事情:索引节点号可以回收。如果我们删除文件的最后一个链接,然后创建一个新文件,我们可能会得到一个具有相同索引节点号的文件。但如果在创建新文件后删除旧文件,则不会发生这种情况。例如mv file file.tmp; touch file; rm file.tmp
。我怀疑 vim 实际上做了类似的事情echo new_content > tmpfile; mv tmpfile file
。该mv
操作将转换为rename
系统调用,因此 inode 编号的分配取决于文件系统如何实现取消链接目标的重命名。