Linux中,特权任务(privileged tasks)可以通过两种方式执行:
Using SUID
Using capabilities
通过SUID拿到root权限,参考
https://blog.csdn.net/qq_39441603/article/details/125010004
https://blog.csdn.net/qq_39441603/article/details/124996277
在检查进程的权限时,EUID标识为0的进程被Linux认为是 root用户进程(特权进程),EUID标识为0的进程被Linux认为非特权进程。
特权进程通过所有内核权限检查,
非特权进程依据进程的EUID、EGID 和Supplementary Group等标识进行权限检查
SUID标识位虽然可以解决普通用户执行特权任务的问题,却带来了安全隐患:
某个设置了SUID标识位的可执行文件对应的进程,通常只需要root用户权限的一部分,但 SUID 给了它 root 用户的全部权限。 因此一旦某个设置了SUID标识位的可执行文件被非法利用,则所有root权限都被攻击者获得,提高了攻击者的能力。
Linux 引入了 capabilities 机制对 root 权限进行细分,实现按需授权。
将与 root用户 关联的权限划分为不同的单元,称为 Capability 。
Capability 可以作为进程的属性存在。每个Capability 可以独立启用和禁用。
检查进程权限的过程变成了:
Operation not permitted
)capability列表参见:
https://man7.org/linux/man-pages/man7/capabilities.7.html
https://www.cnblogs.com/sparkdev/p/11417781.html
capability 名称 | 描述 |
---|---|
CAP_AUDIT_CONTROL | 启用和禁用内核审计;改变审计过滤规则;检索审计状态和过滤规则 |
CAP_AUDIT_READ | 允许通过 multicast netlink 套接字读取审计日志 |
CAP_AUDIT_WRITE | 将记录写入内核审计日志 |
CAP_BLOCK_SUSPEND | 使用可以阻止系统挂起的特性 |
CAP_CHOWN | 修改文件所有者的权限 |
CAP_DAC_OVERRIDE | 忽略文件的 DAC 访问限制 |
CAP_DAC_READ_SEARCH | 忽略文件读及目录搜索的 DAC 访问限制 |
CAP_FOWNER | 忽略文件属主 ID 必须和进程用户 ID 相匹配的限制 |
CAP_FSETID | 允许设置文件的 setuid 位 |
CAP_IPC_LOCK | 允许锁定共享内存片段 |
CAP_IPC_OWNER | 忽略 IPC 所有权检查 |
CAP_KILL | 允许对不属于自己的进程发送信号 |
CAP_LEASE | 允许修改文件锁的 FL_LEASE 标志 |
CAP_LINUX_IMMUTABLE | 允许修改文件的 IMMUTABLE 和 APPEND 属性标志 |
CAP_MAC_ADMIN | 允许 MAC 配置或状态更改 |
CAP_MAC_OVERRIDE | 覆盖 MAC(Mandatory Access Control) |
CAP_MKNOD | 允许使用 mknod() 系统调用 |
CAP_NET_ADMIN | 允许执行网络管理任务 |
CAP_NET_BIND_SERVICE | 允许绑定到小于 1024 的端口 |
CAP_NET_BROADCAST | 允许网络广播和多播访问 |
CAP_NET_RAW | 允许使用原始套接字 |
CAP_SETGID | 允许改变进程的 GID |
CAP_SETFCAP | 允许为文件设置任意的 capabilities |
CAP_SETPCAP | 参考 capabilities man page |
CAP_SETUID | 允许改变进程的 UID |
CAP_SYS_ADMIN | 允许执行系统管理任务,如加载或卸载文件系统、设置磁盘配额等 |
CAP_SYS_BOOT | 允许重新启动系统 |
CAP_SYS_CHROOT | 允许使用 chroot() 系统调用 |
CAP_SYS_MODULE | 允许插入和删除内核模块 |
CAP_SYS_NICE | 允许提升优先级及设置其他进程的优先级 |
CAP_SYS_PACCT | 允许执行进程的 BSD 式审计 |
CAP_SYS_PTRACE | 允许跟踪任何进程 |
CAP_SYS_RAWIO | 允许直接访问 /devport、/dev/mem、/dev/kmem 及原始块设备 |
CAP_SYS_RESOURCE | 忽略资源限制 |
CAP_SYS_TIME | 允许改变系统时钟 |
CAP_SYS_TTY_CONFIG | 允许配置 TTY 设备 |
CAP_SYSLOG | 允许使用 syslog() 系统调用 |
CAP_WAKE_ALARM | 允许触发一些能唤醒系统的东西(比如 CLOCK_BOOTTIME_ALARM 计时器) |
举例:
ping 命令在执行时需要访问网络,这就需要获得 root 权限。常规的做法是通过 SUID 实现,这里改用capability实现。
ping 文件所需的 capabilities 为 cap_net_admin 和 cap_net_raw,通过 setcap 命令可以添加它们:
sudo setcap cap_net_admin,cap_net_raw+ep /bin/ping
命令中的 ep 分别表示 Effective 和 Permitted 集合,+ 号表示把指定的 capabilities 添加到这些集合中(对于 Effective 来说是设置位)。
被赋予合适的 capabilities 后,ping 命令又可以正常工作了。
如果要移除刚才添加的 capabilities,可以使用:
sudo setcap cap_net_admin,cap_net_raw-ep /bin/ping
- 号表示从集合中移除(对于 Effective 来说是清除位)。
相比 SUID 方案,ping文件只具有必要的特权,在最大程度上减小了系统的安全攻击面。
使用sudo find / -perm /u=s
命令可以查找所有设置了setuid位的可执行文件。
对于进程来说,capabilities 是细分到线程的,即每个线程可以有自己的capabilities。
进程(线程)有5类 capabilities:
int execve(const char *pathname, char *const argv[],char*const envp[);
pathname :可执行文件的路径
argv :传递给程序的参数
envp∶传递给程序的新环境变量,无论是shell脚本,还是可执行文件都可以使用此环境变量
Ambient
Linux 4.3 内核新增了一个 capabilities 集合叫 Ambient ,用来弥补 Inheritable 的不足。
可执行文件有三类 capabilities:
execve()执行二进制文件,产生新进程。新进程的capability如下:
(1)在 Android 4.3 之前,app进程 可以直接借助 有SUID标志位的su二进制文件 来获取root用户权限。
(2)Android 4.3之后,app进程基于SUID获取root权限的方案被禁用。主要措施是:
关于zygote进程fork出app进程的过程
参考:https://www.toutiao.com/article/6777894692462789124/
Android 4.3之后,/system 分区也被以 nosuid option被挂载;
那么,系统进程如何获取root权限呢?
app进程是否可以使用同样的方式呢?
(3)系统进程改用 Capability来获取root权限,但app进程不行。
系统daemon可通过可执行文件的capability来获取进程的cap_effective,
但app进程不能这样做,因为app进程是由zygote 进程fork出来的;而zygote进程设置了NO_NEW_PRIVS标志,使得app进程无法通过可执行文件的capability来获取cap_effective。
P’(ambient) = (file is privileged) ? 0 : P(ambient)
P’(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & P(bounding))) | P’(ambient)
P’(effective) = F(effective) ? P’(permitted) : P’(ambient)
也就是:
P’(effective) = F(effective) ? ( (P(inheritable) & F(inheritable)) | (F(permitted) & P(bounding))) | ( (file is privileged) ? 0 : P(ambient) ) ) : ( (file is privileged) ? 0 : P(ambient) )
NO_NEW_PRIVS标志会使SUID和SGID位无法改变进程的 uid 或 gid,file capability也不会被添加到进程的capability中。也就是NO_NEW_PRIVS标志会使获取root权限的 SUID方案和file capability方案 失效。
参考:https://www.kernel.org/doc/html/latest/translations/zh_CN/userspace-api/no_new_privs.html
(4)对app进程切换EUID的其他限制:
(5)SELinux带来的约束
即使一个进程的euid变成了0,或者拥有了所有capability, 它也必须受到SELinux策略的约束。
也就是,SELinux机制进一步约束了root权限进程的行为。
参考:https://forum.xda-developers.com/t/info-is-it-possible-to-install-windows-ios-or-linux-on-android-device.3763961/post-77437874
(#6)
《Linux Capabilities 简介》
https://www.cnblogs.com/sparkdev/p/11417781.html
《Linux Capabilities 入门教程:概念篇》
https://icloudnative.io/posts/linux-capabilities-why-they-exist-and-how-they-work/
很好的介绍capability的课件:
《Linux中的SetUid和capability权能机制》
https://zhuanlan.zhihu.com/p/484164795