是否可以为每个用户配置 Linux 功能?

发布于 2024-08-16 04:12:16 字数 1549 浏览 7 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

巷子口的你 2024-08-23 04:12:16

它可以通过 libcap 来完成 - 它提供了一个 PAM 模块 pam_cap.so。
然而,事情并没有那么简单:)

每个进程都具有三个功能集:

  • 有效(该进程实际具有的上限)
  • 允许(该进程可能具有的上限 - 有效的超集)
  • 可继承(该进程可以传递给子进程的上限)

每个文件都有相同的功能集。当新的二进制文件被 exec()'d 时,进程的能力根据以下规则发生变化,其中:

  • pI/pP 是进程的初始可继承/允许的能力
  • pI'/pP'/pE' 是进程的 new 可继承/允许/有效功能
  • fI/fP/fE 是文件的可继承/允许/有效功能
  • &表示交集
  • |代表工会

    pI' = pI
    pP' = fP | (pI 和 fI)
    pE' = fE & pP'

(从 http://www.friedhoff.org/posixfilecaps.html 简化而来)

在大多数情况下场景中,pE'是我们唯一关心的结果。与 libcap 链接的程序可以调用 setcap() 来更改其有效上限(只要它们尝试请求的上限位于允许集中),但绝大多数程序不会显式触及其上限,因此我们必须安排上限在 exec() 后生效。

有一个具体的例子将有助于理解这里...我厌倦了必须“su”才能运行 openvpn,所以我想授予自己 CAP_NET_ADMIN 功能以允许设置路由等。

查看最后一条规则 (pE' = fE & pP'),很明显,要将 CAP_NET_ADMIN 包含在进程的有效集中,CAP_NET_ADMIN 必须位于文件中的有效集。因此,功能系统不允许我们简单地说“将 CAP_NET_ADMIN 授予用户 sqweek” - 程序的功能始终很重要。

不过,仅位于文件的有效集中还不够,上限还需要位于进程的新许可集中。让我们看看这个规则:pP' = fP | (pI 和 fI)。因此,我们可以通过两种方法获取 pP' 中的上限,要么将 CAP_NET_ADMIN 添加到文件的 Permissible 集中,要么将其添加到文件的 Inheritable 集中并确保它位于进程的 Inheritable 集中。

如果我们将其添加到文件的允许集中,则进程的初始功能变得无关紧要 - openvpn 每次运行时都会获得 CAP_NET_ADMIN,无论谁运行它。这与 setuid 类似,但提供了更细粒度的方法。不过,它不是每个用户的粒度,所以让我们看看另一个选项。

请注意第一条规则,pI' = pI。进程的可继承功能不受 exec() 影响。这意味着,我们只需要一个 libcap 感知程序将 CAP_NET_ADMIN 设置为可继承上限,并且从那里生成的每个进程也将具有 CAP_NET_ADMIN 可继承属性。这就是 pam 模块扮演的角色 - 它在登录期间修改可继承集,然后该集将被该用户的所有进程继承。

总结一下:

  1. 安装 libcap
  2. 配置 pam_cap 模块(将 cap_net_admin sqweek 行添加到 /etc/security/capability.conf 中。如果该文件以前不存在,请添加另一行none *
  3. 在登录期间启用 PAM 模块(将 auth required pam_cap.so 添加到 /etc/pam.d/login 在进行 PAM 更改时,请确保在注销之前在单独的终端中测试您的登录,这样您就不会将自己锁定!
  4. 将 CAP_NET_ADMIN 添加到 openvpn 的有效和可继承集 (setcap )。 cap_net_admin+ie /usr/sbin/openvpn)
  5. openvpn 调用 ip 来更改路由表等,因此需要相同的处理(setcap cap_net_admin+ie /sbin/ip)

请注意,/etc/pam.d/login 仅管理本地登录 - 您可能需要提供 /etc/pam.d。 /sshd 类似的处理。此外,当您的包管理器安装新版本的目标二进制文件时,您通过 setcap 添加的任何功能都将消失,因此您必须重新添加它们。 。

It can sort of be done with libcap - it provides a PAM module pam_cap.so.
However it's not quite that simple :)

Each process has three capability sets:

  • Effective (the caps that this process actually has)
  • Permitted (the caps that this process can possibly have - a superset of Effective)
  • Inheritable (the caps that this process can pass to a child process)

Each file has the same capability sets. When a new binary is exec()'d, the capabilities of the process change according to the following rules, where:

  • pI/pP are the process's initial Inheritable/Permitted capabilities
  • pI'/pP'/pE' are the process's new Inheritable/Permitted/Effective capabilities
  • fI/fP/fE are the file's Inheritable/Permitted/Effective capabilities
  • & represents intersection
  • | represents union

    pI' = pI
    pP' = fP | (pI & fI)
    pE' = fE & pP'

(simplified from http://www.friedhoff.org/posixfilecaps.html)

In most scenarios, pE' is the only result we care about. Programs that are linked against libcap can call setcap() to change their Effective caps (as long as the caps they try to request are in the Permitted set), but the vast majority of programs don't explicitly touch their caps so we have to arrange for the cap to be effective post-exec().

Having a concrete example will help understanding here... I got fed up with having to 'su' to run openvpn, so I wanted to grant myself the CAP_NET_ADMIN capability to allow the setting of routes and such.

Looking at the last rule (pE' = fE & pP') it's clear that to have CAP_NET_ADMIN in the process's Effective set, CAP_NET_ADMIN must be in the file's Effective set. So, the capabilities system doesn't allow us to simply say "grant CAP_NET_ADMIN to user sqweek" - the program's capabilities are always important.

Being in the file's Effective set isn't enough though, the cap also needs to be in the process's new Permitted set. Lets look at that rule: pP' = fP | (pI & fI). So there's two ways we can get the cap in pP', either we add CAP_NET_ADMIN to the file's Permitted set, or we add it to the file's Inheritable set and make sure it is in the process's Inheritable set.

If we add it to the file's Permitted set, then the process's initial capabilities become irrelevant - openvpn will get CAP_NET_ADMIN every time it runs, regardless of who runs it. This is similar to setuid, but provides a more fine-grained approach. Still, it is not a per-user granularity, so lets look at the other option.

Note the first rule, pI' = pI. The process's Inheritable capabilities are unaffected by exec(). What this means is, all we need is a single libcap aware program to set CAP_NET_ADMIN as an Inheritable cap, and every process spawned from there will also have CAP_NET_ADMIN Inheritable. This is the role the pam module plays - it modifies the Inheritable set during login, which is then inherited for all of that user's processes.

To summarise:

  1. Install libcap
  2. Configure the pam_cap module (add the line cap_net_admin sqweek to /etc/security/capability.conf. If the file did not previously exist, add another line none * for a sensible default.
  3. Enable the PAM module during login (add auth required pam_cap.so to /etc/pam.d/login). Make sure to test your login in a separate terminal BEFORE logging out when making PAM changes so you don't lock yourself out!
  4. Add CAP_NET_ADMIN to the Effective and Inheritable sets for openvpn (setcap cap_net_admin+ie /usr/sbin/openvpn)
  5. openvpn calls ip to change the routing table and such, so that needs the same treatment (setcap cap_net_admin+ie /sbin/ip)

Note that /etc/pam.d/login only governs local logins - you might want to give eg. /etc/pam.d/sshd similar treatment. Also, any capabilities you add via setcap will be blown away when your package manager installs a new version of the target binary so you'll have to re-add them.

A君 2024-08-23 04:12:16

是的,您可以使用 setcap 为可执行文件指定功能集,这可以在运行该可执行文件时授予特定功能。

来自 功能(7)手册页:

文件功能
从内核 2.6.24 开始,
内核支持关联
具有可执行文件的功能集
使用 setcap(8) 文件。该文件
能力集存储在
扩展属性(请参阅 setxattr(2))
命名为 security.capability。写信给
此扩展属性需要
CAP_SETFCAP 能力。该文件
能力集,结合
线程的能力集,
确定线程的能力
在 execve(2) 之后。


为每个用户(甚至每个组)授予功能的方法是使用 PAM 模块。 sqweek 的回答展示了如何使用 pam_cap 执行此操作。

Yes, you can use setcap to specify a capability set for an executable, which can grant specific capabilities when that executable is run.

From the capabilities(7) man page:

File Capabilities
Since kernel 2.6.24,
the kernel supports associating
capability sets with an executable
file using setcap(8). The file
capability sets are stored in an
extended attribute (see setxattr(2))
named security.capability. Writing to
this extended attribute requires the
CAP_SETFCAP capability. The file
capability sets, in conjunction with
the capability sets of the thread,
determine the capabilities of a thread
after an execve(2).


The way to grant capabilities per-user (or even per-group) would be with a PAM module. sqweek's answer shows how to do this using pam_cap.

眼泪淡了忧伤 2024-08-23 04:12:16

我还没有确认,但我认为 SELinux 的这个方面可能是您的答案:

http://www.lurking-grue.org/writingselinuxpolicyHOWTO.html#userpol5.1

I've not confirmed, but I think that this aspect of SELinux may be your answer:

http://www.lurking-grue.org/writingselinuxpolicyHOWTO.html#userpol5.1

晨曦慕雪 2024-08-23 04:12:16

看看 CapOver - 它应该可以满足您的需求。

注意:我还没有使用过它,因为它还没有被移植到 2.6.30ish 内核 API。

Have a look at CapOver - it should do what you want.

Note: I haven't used this as it's not (yet?) been ported to the 2.6.30ish kernel API.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文