对 Capabilities (libcap, getcap, setcap) 的基本了解

安装 Wireshark 的时候,有一步是给 dumpcap 读网卡的权限,使得普通用户也可以使用 Wireshark 进行抓包。

# setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip' /usr/sbin/dumpcap

那么 setcap 是个啥玩意呢?


参考文献

https://wiki.archlinux.org/index.php/Capabilities
https://wiki.archlinux.org/index.php/DeveloperWiki:Security#Replacing_setuid_with_capabilities
https://wiki.archlinux.org/index.php/File_permissions_and_attributes#Extended_attributes
http://man7.org/linux/man-pages/man7/capabilities.7.html CAPABILITIES(7)

Capabilities

CAPABILITIES(7) 文档有一段:

       For the purpose of performing permission checks, traditional UNIX
       implementations distinguish two categories of processes: privileged
       processes (whose effective user ID is 0, referred to as superuser or
       root), and unprivileged processes (whose effective UID is nonzero).
       Privileged processes bypass all kernel permission checks, while
       unprivileged processes are subject to full permission checking based
       on the process's credentials (usually: effective UID, effective GID,
       and supplementary group list).

       Starting with kernel 2.2, Linux divides the privileges traditionally
       associated with superuser into distinct units, known as capabilities,
       which can be independently enabled and disabled.  Capabilities are a
       per-thread attribute.

从前,要使被普通用户执行的某个程序有特殊权限,一般我们会给这个程序设置suid,于是普通用户执行该程序时就会以root的身份来执行。
比如,/usr/bin/passwd 这个可执行文件就带有suid,普通用户执行它时会以root身份执行,所以 passwd 才能读取并修改 /etc/shadow 文件。

[root@rhel671 ~]# ls -l /usr/bin/passwd 
-rwsr-xr-x. 1 root root 30768 Feb 17  2012 /usr/bin/passwd

[root@rhel671 ~]# ls -l /etc/shadow
----------. 1 root root 945 Sep 11 16:22 /etc/shadow

可以看到,使用 suid 有一个弊端,那就是以 root 身份执行的程序有了所有特权,这会带来安全风险。
Kernel 从 2.2 版本开始,提供了 Capabilities 功能,它把特权划分成不同单元,可以只授权程序所需的权限,而非所有特权。

用 /bin/ping 测试

在 RHEL6 中,普通用户能执行 ping 命令是因为 /bin/ping 设置了 suid 。

[root@rhel671 ~]# ls -l /bin/ping
-rwsr-xr-x. 1 root root 38200 Dec 11  2014 /bin/ping

将 /bin/ping 的 suid 去除,普通用户则无法执行 ping.

[root@rhel671 ~]# chmod 755 /bin/ping
[root@rhel671 ~]# ls -l /bin/ping
-rwxr-xr-x. 1 root root 38200 Dec 11  2014 /bin/ping
[testuser@rhel671 ~]$ ping www.baidu.com
ping: icmp open socket: Operation not permitted

在 root 用户下,用 setcap 命令给 /bin/ping 这个可执行文件加上 “cap_net_admin,cap_net_raw+ep” 权限,普通用户即可使用 ping.

[root@rhel671 ~]# setcap 'cap_net_admin,cap_net_raw+ep' /bin/ping
[root@rhel671 ~]# getcap  /bin/ping
/bin/ping = cap_net_admin,cap_net_raw+ep
[testuser@rhel671 ~]$ ping www.baidu.com
PING www.a.shifen.com (119.75.217.109) 56(84) bytes of data.
64 bytes from 119.75.217.109: icmp_seq=1 ttl=47 time=4.08 ms
64 bytes from 119.75.217.109: icmp_seq=2 ttl=47 time=4.13 ms

Extended attributes

在 Linux 中的 Capabilities 是通过 extended attributes 中的 security 命名空间实现的。主流的 Linux 文件系统都支持 Extended attributes,包括 Ext2, Ext3, Ext4, Btrfs, JFS, XFS 和 Reiserfs.

[root@rhel671 ~]# getfattr -d -m "security\\." /bin/ping
# file: bin/ping
security.capability=0sAQAAAgAwAAAAAAAAAAAAAAAAAAA=

备注

1. setcap 一般用于二进制可执行文件。setcap 用于脚本文件时无效(比如以 #!/bin/python 开头的脚本文件)
2. CAPABILITIES(7) 文档有较为详尽的说明,推荐阅读。