vim 如何窃取 root 拥有的文件?

vim 如何窃取 root 拥有的文件?

见证以下情况:

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 编号的分配取决于文件系统如何实现取消链接目标的重命名。

相关内容