root 无法写入普通用户拥有的文件

Mar*_*ter 26 shell root permissions strace

我以普通用户身份创建一个文件testuser

$ cat > /tmp/zz
Run Code Online (Sandbox Code Playgroud)

该文件由该用户拥有(如预期):

$ ls -lA /tmp/zz 
-rw------- 1 testuser testuser 0 Feb 20 15:32 zz
Run Code Online (Sandbox Code Playgroud)

现在,当我尝试将其截断为 时root,我的权限被拒绝:

# truncate --size=0 /tmp/zz
truncate: cannot open '/tmp/zz' for writing: Permission denied
Run Code Online (Sandbox Code Playgroud)

当我尝试使用 时strace,我看到以下内容:

openat(AT_FDCWD, "/tmp/zz", O_WRONLY|O_CREAT|O_NONBLOCK, 0666) = -1 EACCES (Permission denied)
write(2, "truncate: ", 10truncate: )              = 10
write(2, "cannot open '/tmp/zz' for writin"..., 33cannot open '/tmp/zz' for writing) = 33
...
write(2, ": Permission denied", 19: Permission denied)     = 19
write(2, "\n", 1
Run Code Online (Sandbox Code Playgroud)

为什么 root 无权写入该文件?root 可以删除该文件,但不能写入。

A.B*_*A.B 51

这是自4.19 版本以来 Linux 内核上提供的一种新行为,用于防止使用/tmp/技巧进行攻击。该选项的默认值可能稍后启用或根据发行版的不同而有所不同。

(特色)避免无意写入攻击者控制的 FIFO 或常规文件:禁止在全局可写粘性目录中打开不属于用户的 FIFO 或常规文件,除非所有者与目录或文件的所有者相同或打开的文件没有 O_CREAT旗帜。目的是使数据欺骗攻击变得更加困难。protected_fifos可以通过 sysctl 分别为 FIFO ( ) 和常规文件 ( )打开和关闭此保护protected_regular,就像符号链接/硬链接保护提交一样

这是为了保护用户(包括通常具有足够权限的 root)写入某个目录中预先存在的文件,例如/tmp/var/tmp当它打算自己创建该文件时。

它是通过此sysctl切换启用的:fs.protected_regular。人们可以通过以下方式恢复以前的行为:

sysctl -w fs.protected_regular=0
Run Code Online (Sandbox Code Playgroud)

但这可能会降低整体安全性,同时使一些奇怪的“错误”(例如OP的情况)消失。

至于为什么 root 仍然可以删除该文件,那是因为附加安全功能仅在打开文件进行写入时触发,而不是在取消链接时触发:打开文件进行写入,不truncate -s ...打开文件进行写入(它使用或)。rmunlinkunlinkat

  • @Joshua Kernel 4.19 [已经发布 3 年多了](https://lkml.org/lkml/2018/10/22/184),世界还没有结束。我想我们会在这次变化中幸存下来。 (17认同)
  • 这会弄得一团糟。永远都会有错误来来回回。 (5认同)
  • @trlkly 此功能特别旨在影响 root 用户:权限升级的目标。 (5认同)
  • @Joshua Fair,看来它最初默认是关闭的。看起来这确实是从 20.04 开始在 Ubuntu 中启用的,大约两年前。默认情况下,较保守的发行版启用此功能的速度可能会较慢,但在流行发行版中已有约 2 年的经验,我仍然认为此更改的影响并不那么严重。 (4认同)
  • @400theCat 如果用户可以提前猜出文件名,则它可以使用其他帐户(root)认为它自己写入的数据来预置它。如果此数据以任何方式参与身份验证...列表中的最后一个 CVE (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7489) 有一个示例:http: //www.vapidlabs.com/advisory.php?v=173 。这是一项防止应用程序中出现一类错误的功能。当然,应用程序应该被修复,但是...... (3认同)
  • @JohnBollinger 我做了更正,但是是的,即使那样也很难解析。引号中的文本应解读为“除非[文件]的所有者与目录的所有者相同”。如果user1创建了一个a+wt目录,如果其中模式为666的文件foo的所有者为user1,那么任何用户都可以写入它。如果它有 user1 之外的其他所有者,例如 user2,则只有 user2 可以对其进行写入。特别是 user1 和 root(也不是 user3)。 (3认同)