stevegrubb/libcap-ng
GitHub: stevegrubb/libcap-ng
libcap-ng 是一个用于简化 Linux POSIX 权能管理的库和工具集,帮助开发者和管理员降低应用权限风险。
Stars: 91 | Forks: 39
# roper nouns, tool/library/framework names, and technical jargon in their original English form." So for "libcap-ng", it is a tool/library name, so keep it as "libcap-ng".
libcap-ng 库旨在使利用 POSIX 权能进行编程变得更加简单。该库提供了一些实用工具,可帮助您分析系统中可能存在过度权限的应用程序。
附带的实用工具旨在帮助管理员和开发者从多个角度识别那些可能正以过高权限运行的应用程序。例如,任何调查都应从面向网络的应用程序开始,因为它们最有可能成为入侵的目标。**netcap** 程序将检查所有具有监听套接字的正在运行的应用程序,并显示结果。以下是 netcap 的示例输出:
```
ppid pid acct command type port capabilities
1 2295 root nasd tcp 8000 full
2323 2383 root dnsmasq tcp 53 net_admin, net_raw +
1 2286 root sshd tcp 22 full
1 2365 root cupsd tcp 631 full
1 2286 root sshd tcp6 22 full
1 2365 root cupsd tcp6 631 full
2323 2383 root dnsmasq udp 53 net_admin, net_raw +
2323 2383 root dnsmasq udp 67 net_admin, net_raw +
1 2365 root cupsd udp 631 full
```
检查完网络应用程序后,您应使用 **pscap** 检查所有正在运行的应用程序。如果您是一名开发者,且必须为您的应用程序赋予 CAP_DAC_OVERRIDE 权能,那么您必然是在访问无权访问的文件。通常可以通过将用户添加到正确的用户组来解决此问题。尽量避免需要 CAP_DAC_OVERRIDE…如果必须要它,那您基本上就等同于 root 了。
一些应用程序开发者选择使用基于文件系统的权能,而不是设置 setuid root 并随后放弃权能。Libcap-ng 提供了 **filecap** 工具,可递归搜索目录并显示哪些文件具有权能以及具体是什么权能。
有一个新的实用工具 **cap-audit**,它可以审计一个程序所需的权能。下文将详细讨论它。
## C 语言示例
作为一名应用程序开发者,您可能关心以下 6 个用例:放弃所有权能、保留单个权能、保留多个权能、检查是否拥有任何权能、检查特定权能以及在 UID 更改后保留权能。
1. 放弃所有权能
capng_clear(CAPNG_SELECT_BOTH);
capng_apply(CAPNG_SELECT_BOTH);
2. 保留单个权能
capng_clear(CAPNG_SELECT_BOTH);
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_CHOWN);
capng_apply(CAPNG_SELECT_BOTH);
3. 保留多个权能
capng_clear(CAPNG_SELECT_BOTH);
capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETUID, CAP_SETGID, -1);
capng_apply(CAPNG_SELECT_BOTH);
4. 检查是否拥有任何权能
if (capng_have_capabilities(CAPNG_SELECT_CAPS) > CAPNG_NONE)
do_something();
5. 检查特定权能
if (capng_have_capability(CAPNG_EFFECTIVE, CAP_CHOWN))
do_something();
6. 在 UID 更改后保留权能
capng_clear(CAPNG_SELECT_BOTH);
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_CHOWN);
if (capng_change_id(99, 99, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING))
error();
现在,这是不是简单多了?请注意,使用较旧的权能库实现最后一个示例大约需要 60 行代码。从 0.6 版本开始,提供了一个 m4 宏文件,用于帮助将 libcap-ng 添加到您的 autotools 配置系统中。在 `configure.ac` 文件中,添加 `LIBCAP_NG_PATH`。然后在 `Makefile.am` 文件中,找到链接到 libcap-ng 的应用程序,在其 `LDADD` 条目中添加 `$(CAPNG_LDADD)`。最后,用 `#ifdef HAVE_LIBCAP_NG` 包围可选的权能代码。
## - Similarly for "Python".
Libcap-ng 0.6 及更高版本提供了 Python 绑定。(自 0.8.4 版本起仅支持 python3。)您只需在脚本中添加 `import capng` 即可。以下是用 Python 编写的与上述相同的示例:
1. 放弃所有权能
capng.capng_clear(capng.CAPNG_SELECT_BOTH)
capng.capng_apply(capng.CAPNG_SELECT_BOTH)
2. 保留单个权能
capng.capng_clear(capng.CAPNG_SELECT_BOTH)
capng.capng_update(capng.CAPNG_ADD, capng.CAPNG_EFFECTIVE|capng.CAPNG_PERMITTED, capng.CAP_CHOWN)
capng.capng_apply(capng.CAPNG_SELECT_BOTH)
3. 保留多个权能
capng.capng_clear(capng.CAPNG_SELECT_BOTH)
capng.capng_updatev(capng.CAPNG_ADD, capng.CAPNG_EFFECTIVE|capng.CAPNG_PERMITTED, capng.CAP_SETUID, capng.CAP_SETGID, -1)
capng.capng_apply(capng.CAPNG_SELECT_BOTH)
4. 检查是否拥有任何权能
if capng.capng_have_capabilities(capng.CAPNG_SELECT_CAPS) > capng.CAPNG_NONE:
do_something()
5. 检查特定权能
if capng.capng_have_capability(capng.CAPNG_EFFECTIVE, capng.CAP_CHOWN):
do_something()
6. 在 UID 更改后保留权能
capng.capng_clear(capng.CAPNG_SELECT_BOTH)
capng.capng_update(capng.CAPNG_ADD, capng.CAPNG_EFFECTIVE|capng.CAPNG_PERMITTED, capng.CAP_CHOWN)
if capng.capng_change_id(99, 99, capng.CAPNG_DROP_SUPP_GRP | capng.CAPNG_CLEAR_BOUNDING) < 0:
error()
需要注意的一点是,从 Python 中打印权能的功能目前不可用。但您仍然可以操作权能。
## Ambient 权能
Ambient 权能在 Linux 内核 4.3 中引入。Ambient 权能允许一个特权进程将权能授予子进程。systemd 就是通过这种方式为服务账户中运行的守护进程授予权能的。
Ambient 权能的问题在于它们会被永久继承。从原始服务中 exec 出来的每个进程也会拥有这些权能。这是一个安全问题。
要查找并修复此问题,您可以运行 pscap 程序并 grep 查找 `@` 符号。`@` 符号表示具有 ambient 权能的进程。例如:
```
# 2. "Python" – Keep as "Python".
1 1655 systemd-oom systemd-oomd dac_override, kill @ +
1 1656 systemd-resolve systemd-resolve net_raw @ +
```
为了解决这个问题,libcap-ng 0.8.3 及更高版本提供了 libdrop_ambient.so.0。它旨在与 `LD_PRELOAD` 配合使用。它包含一个构造函数,用于强制丢弃 ambient 权能。当应用程序启动时,它同时具有有效权能和 ambient 权能——这意味着可以很早就安全地丢弃 ambient 权能。您可以通过链接将它用于作为 systemd 服务运行的应用程序(使用 ld),或者创建一个包装脚本来启动守护进程。
## 构建
注意:自 0.9 版本起,libcap-ng 不再通过 people.redhat.com/sgrubb/libcap-ng/ 分发,请调整任何脚本以关注此 GitHub 页面上的新版本发布。
克隆 libcap-ng 后,运行:
```
cd libcap-ng
./autogen.sh
./configure
make
make install
```
如果您需要 Python 绑定,请在配置命令中添加该选项。`netcap --advanced` 功能也依赖于较新的 Linux 内核头文件,包括 `linux/vm_sockets.h`。当这些头文件不可用时(例如在较旧的构建根目录上),`configure` 将自动退出高级模式并在其输出中报告,同时仍会构建 libcap-ng 的其余部分。cap-audit 程序需要特别启用,默认情况下不构建。如果您使用基于 rpm 的发行版,还有一个 spec 文件可用。为此,请在上述说明中运行 `make dist` 而不是 `make`。然后将生成的 tar 文件与 spec 文件一起使用。
当高级模式可用时,`netcap --advanced --list-interfaces` 会打印当前网络命名空间的接口名称。添加 `--json` 选项可获取机器可读的名称列表。
## 注意:致发行版
有一个 `make check` 目标。它仅在可用的内核头文件与构建根内核大致匹配时才有效。换句话说,如果您有一个使用更旧内核的 chroot 构建系统,内核头文件中的宏将描述构建根中不存在的功能。`capng_init` 函数将探测内核并决定我们只能使用 v1 而不是 v3 权能,而不是像内核头文件所描述的那样可能。如果这是您的情况,请不要在构建过程中执行 `make check`。随着构建根最终切换到 5.0 或更高版本的内核,此问题应该会消失。
## 3. "pscap | grep @" – This is a command. "pscap" is a tool name, "grep" is a command, so keep them in English. The "|" is a pipe symbol, and "@" might be a placeholder. I should translate the whole command as is, but since it's a heading, perhaps it's describing a command usage.
自 libcap-ng 的 0.9 版本起,有一个新的实用工具 **cap-audit**。该程序可用于确定一个程序实际需要的权能。为此,可以像使用 strace 那样使用它来运行应用程序。使用 `--` 将 cap-audit 的选项与被审计的程序分开。您需要以 root 身份使用 cap-audit,因为它会在内核中放置一个 eBPF 程序来挂钩权能检查,以确定请求了什么、是否被批准以及源于哪个系统调用。当测试一个守护进程时,传递命令行选项使其保持在前台运行。以下是检查 sshd 的示例:
```
cap-audit -- /usr/sbin/sshd -D
[*] Capability auditor started
[*] Tracing application: /usr/sbin/sshd (PID 30581)
[*] Press Ctrl-C to stop
^C[*] Analyzing results...
======================================================================
CAPABILITY ANALYSIS FOR: /usr/sbin/sshd (PID 30581)
======================================================================
SYSTEM CONTEXT:
----------------------------------------------------------------------
Kernel version: 6.18.3-100.fc42.x86_64
kernel.yama.ptrace_scope: 1
kernel.kptr_restrict: 1
kernel.dmesg_restrict: 1
kernel.modules_disabled: 0
kernel.perf_event_paranoid: 2
kernel.unprivileged_bpf_disabled: 2
net.core.bpf_jit_enable: 1
net.core.bpf_jit_harden: 1
net.core.bpf_jit_kallsyms: 1
vm.mmap_min_addr: 65536
fs.protected_hardlinks: 1
fs.protected_symlinks: 1
fs.suid_dumpable: 2
REQUIRED CAPABILITIES:
----------------------------------------------------------------------
chown (#0)
Checks: 1 granted, 0 denied
Reason: Used by chown (syscall 92)
dac_read_search (#2)
Checks: 2 granted, 1 denied
Reason: Used by openat (syscall 257)
setgid (#6)
Checks: 30 granted, 2 denied
Reason: Used by setgroups (syscall 116)
setuid (#7)
Checks: 13 granted, 4 denied
Reason: Used by setresuid (syscall 117)
net_bind_service (#10)
Checks: 2 granted, 0 denied
Reason: Used by bind (syscall 49)
net_admin (#12)
Checks: 2 granted, 2 denied
Reason: Used by setsockopt (syscall 54)
sys_chroot (#18)
Checks: 1 granted, 0 denied
Reason: Used by chroot (syscall 161)
sys_admin (#21)
Checks: 597 granted, 1656 denied
Reason: Used by brk (syscall 12)
sys_resource (#24)
Checks: 3 granted, 0 denied
Reason: Used by write (syscall 1)
audit_write (#29)
Checks: 27 granted, 2 denied
Reason: Used by sendto (syscall 44)
mac_admin (#33)
Checks: 1 granted, 0 denied
Reason: Used by getxattr (syscall 191)
CONDITIONAL CAPABILITIES:
----------------------------------------------------------------------
CAP_DAC_OVERRIDE
Needed when fs.protected_symlinks = 1 for symlinks in world-writable directories
Current value: 1 (capability needed)
ATTEMPTED BUT DENIED:
----------------------------------------------------------------------
dac_override (#1)
Attempts: 2 (all denied)
Syscalls: readlink, faccessat2
Impact: Application may have reduced functionality
bpf (#39)
Attempts: 2 (all denied)
Syscalls: prctl
Impact: Application may have reduced functionality
SUMMARY:
----------------------------------------------------------------------
Total capability checks: 2349
Required capabilities: 11
Conditional capabilities: 1
Denied operations: 2
RECOMMENDATIONS:
----------------------------------------------------------------------
Programmatic solution (C with libcap-ng):
#include
...
capng_clear(CAPNG_SELECT_BOTH);
capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CHOWN, DAC_READ_SEARCH, SETGID, SETUID, NET_BIND_SERVICE, NET_ADMIN, SYS_CHROOT, SYS_ADMIN, SYS_RESOURCE, AUDIT_WRITE, MAC_ADMIN, -1);
if (capng_change_id(uid, gid, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING))
perror("capng_change_id");
For systemd service:
[Service]
User=
Group=
AmbientCapabilities=chown dac_read_search setgid setuid net_bind_service net_admin sys_chroot sys_admin sys_resource audit_write mac_admin
CapabilityBoundingSet=chown dac_read_search setgid setuid net_bind_service net_admin sys_chroot sys_admin sys_resource audit_write mac_admin
For file capabilities (via filecap):
filecap /path/to/binary chown dac_read_search setgid setuid net_bind_service net_admin sys_chroot sys_admin sys_resource audit_write mac_admin
For Docker/Podman:
docker run --user $(id -u):$(id -g) \
--cap-drop=ALL \
--cap-add=chown \
--cap-add=dac_read_search \
--cap-add=setgid \
--cap-add=setuid \
--cap-add=net_bind_service \
--cap-add=net_admin \
--cap-add=sys_chroot \
--cap-add=sys_admin \
--cap-add=sys_resource \
--cap-add=audit_write \
--cap-add=mac_admin \
your-image:tag
For Kubernetes:
securityContext:
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop:
- ALL
add:
- chown
- dac_read_search
- setgid
- setuid
- net_bind_service
- net_admin
- sys_chroot
- sys_admin
- sys_resource
- audit_write
- mac_admin
```
## 报告
请向以下地址报告本软件包中的任何错误:
https://github.com/stevegrubb/libcap-ng/issues
标签:Docker镜像, libcap-ng, Linux开发, POSIX能力, 子域名枚举, 客户端加密, 工具集, 应用特权检查, 文件系统能力, 权限管理, 模型越狱, 特权分析, 系统安全, 编程库, 网络安全, 网络连接监控, 逆向工具, 隐私保护