【问题标题】:Request Linux Capabilities During Runtime在运行时请求 Linux 功能
【发布时间】:2021-09-08 07:21:25
【问题描述】:

我正在用 C 语言开发一个程序,该程序需要临时使用一些需要提升才能获得的功能,并且不希望用户只发出 sudo,因为这将是一次设置。

我将如何授予诸如 CAP_CHOWN 之类的功能以启用更改文件所有权或由功能保护的类似操作?

关于可能重复的注释

当我在它作为副本关闭之前问这个问题时。被引用为原始问题的问题与我发布的问题不同。我想要一组非常具体的功能,而不是 root 访问权限。

【问题讨论】:

标签: c linux linux-capabilities


【解决方案1】:

为进程提供额外功能的最常见方法是将文件系统功能分配给其二进制文件。

例如,如果您希望执行/sbin/yourprog 的进程具有CAP_CHOWN 能力,则将该能力添加到该文件的允许和有效集合中:sudo setcap cap_chown=ep /sbin/yourprog

setcap 实用程序由 libcap2-bin 软件包提供,默认安装在大多数 Linux 发行版上。

还可以为原始流程提供能力,并让该流程根据需要操纵其有效的能力集。例如,Wireshark 的dumpcap 通常在有效、允许和可继承集中安装 CAP_NET_ADMIN 和 CAP_NET_RAW 文件系统功能。

我不喜欢将任何文件系统功能添加到可继承集的想法。当功能不在可继承集中时,执行另一个二进制文件会导致内核放弃这些功能(假设 KEECAPPS 为零;有关详细信息,请参阅prctl(PR_SET_KEEPCAPS)man 7 capabilities)。

例如,如果您仅授予/sbin/yourprog CAP_CHOWN 能力并且仅在允许的集合(sudo setcap cap_chown=p /sbin/yourprog)中,则 CAP_CHOWN 能力将不会自动生效,并且如果进程执行其他一些操作,它将被丢弃二进制。要使用 CAP_CHOWN 功能,线程可以在所需操作期间将功能添加到其有效集,然后通过prctl() 调用将其从有效集中删除(但将其保留在允许集中)。请注意,libcap cap_get_proc()/cap_set_proc() 接口会将更改应用于进程中的所有线程,这可能不是您想要的。

对于临时授予能力,可以使用工作子进程。这对于复杂的过程是有意义的,因为它允许将特权操作委托/分离到单独的二进制文件。一个子进程被分叉,通过 Unix 域流或通过 socketpair() 创建的数据报套接字连接到父进程,并执行授予 it 必要功能的辅助二进制文件。然后它使用 Unix 域流套接字来验证身份(进程 ID、用户 ID、组 ID,并通过进程 ID,套接字的另一端正在执行的可执行文件)。不使用管道的原因是需要一个 Unix 域流套接字或数据报套接字对套接字才能使用SO_PEERCRED 套接字选项向内核查询套接字另一端的身份。

存在需要预测和阻止的已知攻击模式。最常见的攻击模式是导致父进程在分叉并执行特权子进程后立即执行受损的二进制文件,时间恰到好处,因此有能力的子进程相信另一端是其正确的父进程执行正确的二进制文件,但实际上控制已被转移到一个完全不同的、被泄露的或不可信的二进制文件中。

关于如何安全地做到这一点的详细信息是一个软件工程问题,而不是一个编程问题,但是使用socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fdpair) 并验证套接字对等点是父进程仍然不止一次在开始时执行预期的二进制文件,是需要的关键步骤。


我能想到的最简单的例子是仅在允许的集合中使用 prctl() 和 CAP_NET_BIND_SERVICE 文件系统功能,以便其他非特权进程可以使用特权端口(1-1024,最好是定义/列出的系统范围子集在 /etc 下某处的根或管理员拥有的配置文件中)以提供网络服务。如果服务将在被告知时关闭并重新打开其侦听套接字(可能通过 SIGUSR1 信号),则不能简单地在开始时创建一次然后删除侦听套接字。它非常适合 “保留在允许的集合中,但只添加到实际需要它的线程的有效集合,然后立即删除它” 模式。

对于 CAP_CHOWN,示例程序可能会通过文件系统功能将其获取到其有效和允许的集合中,但使用受信任的配置文件(仅限 root/admin 可修改)来列出允许根据真实情况进行的所有权更改运行进程的用户和组身份。考虑一个专用的“sudo”风格的“chown”实用程序,旨在让组织允许团队领导在其团队成员之间转移文件所有权,但不使用 sudo。)

【讨论】:

  • 这是一个非常好的答案,写得很好,谢谢你的回答。
【解决方案2】:

实际上不可能在运行时获得能力。需要在您的软件启动之前设置这些功能。

存在一些 API 函数,如 capsetcap_set_proc,但不要指望魔法,因为您可以获得更多功能的情况将是罕见安全监督.

有几种通用方法可以为您的软件提供所需的功能。

  1. 使用setcap 工具为您的二进制文件设置特定功能。
  2. 使用sudo 调用您的程序。您自己已经提到了这一点。
  3. 在您的二进制文件上设置setuid 位并将所有权设置为root。在这种特殊情况下,这在很大程度上等同于使用 sudo 调用您的程序。
  4. 创建一个应用其他方法之一的实用程序。通常,您会在/usr/libexec 之类的地方找到此类实用程序。然后将该实用程序作为子进程调用。对于简单的情况,我认为这不必要地复杂。但是,根据具体情况,这可能比您的软件持续以过多权限运行的潜在安全风险要好。

第一种方法应该被认为是所需的方法。您的软件应在不再需要该功能时立即删除它。

例如,CAP_CHOWN 可用于更改/etc/shadow 的所有权。然后,新所有者可以更改其他用户的密码,例如root,因此实际上它可以等效于授予所有权限。因此,此功能与许多其他功能一样具有潜在危险。

【讨论】:

    猜你喜欢
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多