2

capabilities(7)是一种不将所有 root 权限授予进程的好方法,并且可以使用 AFAIK 代替setuid(2). 根据这个和许多其他人,

“不幸的是,仍然有许多二进制文件setuid设置了位,而应该将它们替换为capabilities。”

举个简单的例子,在 Ubuntu 上,

$ ls -l `which ping`
-rwsr-xr-x 1 root root 44168 May  8  2014 /bin/ping

如您所知,在文件上设置 suid/guid 会将有效用户 ID 更改为 root。因此,如果启用 suid 的程序存在缺陷,则非特权用户可以突破并成为与 root 用户等效的用户。

我的问题是为什么许多 Linux 发行版仍然使用setuid方法,而capabilities可以使用设置来代替安全问题?

4

3 回答 3

1

这可能无法解释为什么某些地方的某些家伙会以某种方式决定,但某些审计工具和接口可能还不知道功能。

一个例子是proc_connector netlink 接口和基于它的程序(如forkstat):有一个进程更改其凭据的事件,但不是它更改其功能的事件。


FWIW,可能无法在类似 Debian 的发行版上获得例如 anet_raw+ep ping(8)而不是 setuid 的原因是因为这取决于安装之前已经存在setcap(8)的软件包中的实用程序。来自:libcap2-binpingiputils-ping.postinst

    if command -v setcap > /dev/null; then
        if setcap cap_net_raw+ep /bin/ping; then
            chmod u-s /bin/ping
        else
            echo "Setcap failed on /bin/ping, falling back to setuid" >&2
            chmod u+s /bin/ping
        fi
    else
        echo "Setcap is not installed, falling back to setuid" >&2
        chmod u+s /bin/ping
    fi

另请注意,ping它本身会在启动时放弃任何 setuid 权限并切换到使用 Linux 上的功能,因此您对此的担忧可能有点夸大了。来自ping.c

int
main(int argc, char **argv)
{
        struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_protocol = IPPROTO
_UDP, .ai_socktype = SOCK_DGRAM, .ai_flags = getaddrinfo_flags };
        struct addrinfo *result, *ai;
        int status;
        int ch;
        socket_st sock4 = { .fd = -1 };
        socket_st sock6 = { .fd = -1 };
        char *target;

        limit_capabilities();

ping_common.c

void limit_capabilities(void)
{
        ...
        if (setuid(getuid()) < 0) {
                perror("setuid");
                exit(-1);
        }
于 2020-03-23T23:30:31.547 回答
0

考虑一个不同的星球,如果功能补丁被拒绝,提交者必须更加努力地进行邻里改进,并想出了这个:

  • 文件系统可以挂载 suid、nosuid 或 capsuid。

  • 如果挂载了 capsuid,则 ${file} 上的 setuid 位不计算在内,除非 .${file}.suid_capability 也存在,是 setuid,并且长度为 0 或以某种标准化格式可解析:

    -r-sr-xr-x. 1 carton carton 3812 Dec 27 15:39 t1
    -r-Sr--r--. 1 carton carton    0 Dec 27 15:39 .t1.suid_capability
    
  • 如果文件为空,setuid 位将正常工作。如果它具有可解析的内容,则它可以作为部分根功能。

  • 如果需要,可以使用以下字段对 .t1.suid_capability 文件进行注释:

    • 绑定到其匹配的“t1”文件的哈希

    • 绑定到一个绝对路径,例如,一个 chroot 中的 setuid 文件在你 chroot 进入它之前不会变得“热”。

    • 绑定到在引导时加载的公钥或散列随机数,以识别已安装的系统,如 uuid。如果私钥或 nonce 对备份服务器隐藏,传统的密码重置仍然有效,但某些形式的 rootkit 持久性会变得更加困难。它还允许您使用子目录中其他系统的映像,即使您对安装选项没有纪律并选择不使用绝对路径功能,也会自动使它们有效地“nosuid”安装。

现在回答一些关于这个星球相对于我们自己的问题:

  • 与我们的原生星球相比,是否缺少任何功能?

  • 哪个系统与“ls”、“tar”、“rsync”、“cpio”、“find”、“pax”、“mtree”配合得更好?用gentoo的ebuild沙箱?与LXC?

  • 哪个系统更适合在 NFS 或 9p 根上运行的无盘或来宾系统?

  • 哪个系统更适合tripwire?

现在重复这些问题,考虑三个系统而不是两个:

  • 我们的星球:文件系统中的神秘功能元数据

  • 使用文明 Unix 方法的替代星球

  • mosvy 的“ping”示例,二进制文件在启动后立即删除权限

随着第三个系统最终开始失去与现状相关的功能:有人可以编写一个假设的功能感知绊线,在“ping”示例中效果不佳。不过,有人这样做过吗?. . . NSA 以外的任何人——是否有人将这种复杂性强加给我们,以从复杂性中提供(相对较小的)价值?如果这是我们想要死去的功能山(而不是减少攻击面),是否有更好的方法来获得它,比如 dm-verity,它再次引发了复杂性?

现在让我们对 mosvy 的 'ping' 做一点改进:

  • crt.o或者一些早期的运行时启动代码读取 sidecar 文件和/etc/suid_capability_hash_nonce. 如果/etc/suid_capability_hash_nonce存在则删除 suid 但sidecar 文件不存在(在“替代星球”术语中,存在/etc/suid_capability_hash_nonce使整个系统'-o capsuid'-mounted)。早期的运行时启动代码会处理 Sidecar 的解析和枚举功能,这样就不必将逻辑一个一个地编码到 main.c 中。

老实说,我认为 'ping' 的例子更胜一筹,因为程序知道他们需要什么能力,而且只有当程序的源代码发生变化时,需求才会改变。通过将它们设置为 drop_privileges() 风格的函数,需求永远不会不同步。扇出发行版不必争先恐后地更新功能集。

如果您不同意并想要 sidecar/capabilities 风格的系统,则可以在不篡改内核、挂载选项、启动等任何内容的情况下实现等效的东西:旧的 dracut-nfsroot initrds 将继续工作。这只是风格问题。

这完全是一种苏格拉底式的说法,除了 dm-verity + 'ping' 式的特权删除之外,什么都不能提供。避开不会减轻其重量的复杂性并没有什么“不幸”的。

每隔几年,CADT 开发人员就会发明一些新形式的元数据来填充文件系统目录:Finder 元数据、POSIX ACL、SELinux 上下文、NFS ACL。他们接下来会怎么想?更新所有文件系统、所有网络协议、所有 fileutils 工具、所有非 Linux 存储操作系统、所有花哨的许可“企业”磁带备份套件需要多长时间?会有人来更新所有这些东西,还是我们会随着不合标准的工具一瘸一拐地走?甚至核心功能是否会被有用地记录下来,还是会成为一些令人讨厌的“发行版”的无证玩物?该功能会在大多数情况下工作,但会阻止系统意外启动并产生鸡与蛋的恢复问题吗?该功能真的会阻止任何攻击吗?

对于所有必须清理它们并容忍他们自己的系统中的复杂性做出不同、更简单的选择的人,这是否公平,只是为了打破他们的新功能破坏的互操作性?

在这种情况下,交付的价值特别低,但我们有足够的经验为此类提案设置高价值标准。我认为在 Linux 中接受该功能并赞扬任何避免它的发行版是错误的。

于 2020-12-27T21:42:19.130 回答
0

2008 年,当文件功能被添加到内核时,功能支持才真正启用。所以,那是 13 年并且计数替换setuid。你的问题非常有效。

如果能力支持没有在 Linux 中以向后兼容的方式实现,它要么在出生时就被拒绝,要么现在肯定会改变!我怀疑这一切都归结为这样一个事实,即当发现某些代码中的错误可被利用时,它们的好处只是暂时显而易见时,没有经济动机来采用它们。

我认为人们已经接受了 setuid 二进制文件似乎可被利用的所有方式以及人们在另一个漏洞出现时迅速推出的点修复。缓冲区溢出 -> 启动 shell -> 根漏洞利用 -> 代码修复 -> 重新开始。他们对用户身份 = 特权(即 root)这一想法感到满意。当一连串的漏洞利用可以产生所有特权时,这溢出了人们想要描述将所有强大的根分解为独立功能是徒劳的。显然,特权和身份应该等同的普遍观念是环境能力甚至存在的原因。

然而,当按预期使用功能时,它们并不是身份 = 特权。它们是有能力的二进制文件= 特权 - 通过这些能力位和具有它们的实际程序中的代码的组合,相对于执行任意代码的用户身份,特权会降低。

如果您编写编辑文件的代码,很明显不必担心被直接滥用以形成原始以太网数据包或加载内核模块。利用该代码中的错误很可能允许恶意编辑文件,但与 setuid 不同的是,它不允许在网络上发送奇怪的数据包。至少在不诱使某些独立可执行的代码通过代理执行此操作的情况下并非如此。

但是,没有人故意编写错误代码,所以我认为您的问题的答案归结为另一个问题:“限制漏洞利用的可利用性到底有什么好处?”。

我怀疑,如果某些发行版要弄清楚如何重组其代码库以消除 setuid-root 二进制文件,以支持文件功能,那么随着时间的推移,它会更好(当然不会更糟),因为发现代码漏洞而不是其他发行版紧贴到setuid-root。但是,在这样的分布出现之前,我不能错误地认为这只是一种观点。

于 2021-05-22T03:18:04.617 回答