【Linux】Linux中的特权 | SUID | Linux Capabilities

1.获得特权的两种方式

Linux中,特权任务(privileged tasks)可以通过两种方式执行:

  • Using SUID

  • Using capabilities

2.关于SUID

通过SUID拿到root权限,参考
https://blog.csdn.net/qq_39441603/article/details/125010004
https://blog.csdn.net/qq_39441603/article/details/124996277

3.关于Capabilities(权能)

在检查进程的权限时,EUID标识为0的进程被Linux认为是 root用户进程(特权进程),EUID标识为0的进程被Linux认为非特权进程。

特权进程通过所有内核权限检查,
非特权进程依据进程的EUID、EGID 和Supplementary Group等标识进行权限检查

SUID标识位虽然可以解决普通用户执行特权任务的问题,却带来了安全隐患:

某个设置了SUID标识位的可执行文件对应的进程,通常只需要root用户权限的一部分,但 SUID 给了它 root 用户的全部权限。 因此一旦某个设置了SUID标识位的可执行文件被非法利用,则所有root权限都被攻击者获得,提高了攻击者的能力。

Linux 引入了 capabilities 机制对 root 权限进行细分,实现按需授权。

3.1 Linux capabilities概念

将与 root用户 关联的权限划分为不同的单元,称为 Capability 。
Capability 可以作为进程的属性存在。每个Capability 可以独立启用和禁用。

检查进程权限的过程变成了:

  • 如果进程的EUID是AID_ROOT,则进程拥有全部root权限
  • 如果进程的EUID不是AID_ROOT,则检查进程是否有该操作所对应的 Capability
    比如要向其他进程发送kill()信号,就得具有 Capability CAP_KILL; 比如要设置系统时间,就得具有 Capability CAP_SYS_TIME
    如果有,则允许;否则拒绝操作(报错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 计时器)

3.2 getcap 命令和 setcap 命令

举例:
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位的可执行文件。

3.3 进程的 capabilities与可执行文件的 capabilities

3.3.1 进程的 capabilities

对于进程来说,capabilities 是细分到线程的,即每个线程可以有自己的capabilities。

进程(线程)有5类 capabilities:

  • Permitted(cap_permitted)
    定义了进程能够拥有的 capabilities 的上限。
    • 不含CAP_SETPCAP的进程,只能往cap_inheritable中添加cap_permitted中有的capability。
    • 不含CAP_SETPCAP的进程,只能丢掉cap_permitted中的capability,但不能向其中添加capability。
    • 含CAP_SETPCAP的进程(UID为0),可以向cap_permitted中添加capability,但仍受规则约束。
      在这里插入图片描述
  • Effective(cap_effective)
    当前进程实际拥有的权能。内核检查进程是否可以进行特权操作时,检查的便是 cap_effective数组。
    在这里插入图片描述
  • Inheritable (cap_inheritable)
    父进程使用execve()执行可执行文件产生子进程时,子进程继承父进程的capability。
int execve(const char *pathname, char *const argv[],char*const envp[);
pathname :可执行文件的路径
argv :传递给程序的参数
envp∶传递给程序的新环境变量,无论是shell脚本,还是可执行文件都可以使用此环境变量

在这里插入图片描述

  • Bset(cap_bset)
    用于限定进程从可执行文件中获取的capability。
    在这里插入图片描述

  • Ambient
    Linux 4.3 内核新增了一个 capabilities 集合叫 Ambient ,用来弥补 Inheritable 的不足。

    • 非特权用户如果在 Permitted 集合中有一个 capability,那么可以添加到 Ambient 集合中,这样它的子进程便可以在 Ambient、Permitted 和 Effective 集合中获取这个 capability。
3.3.2 可执行文件的 capabilities

可执行文件有三类 capabilities:

  • Permitted:
    在进程执行时,文件的Permitted Capabilites 自动被加入到进程的 Permitted Capabilites 中。
  • Inheritable:
    Inheritable 集合中的 capabilites 会与进程的 Inheritable 集合执行与操作,以确定进程在执行 execve 函数后哪些 capabilites 被继承。
  • Effective:
    Effective 只是一个 bit。如果设置为开启,那么在执行 execve 函数后,Permitted 集合中新增的 capabilities 会自动出现在进程的 Effective 集合中。

3.4 execve() 权能变化规则

execve()执行二进制文件,产生新进程。新进程的capability如下:
在这里插入图片描述
在这里插入图片描述

3.5 capability的实现

  • 在进程的task_struct结构体中设置capability,capability取值需要计算。
  • 在进程进行特权操作时,检查进程是否具有相应的capability,而不是判断是否为root用户
    在这里插入图片描述

4. 安卓中 的 capabilities

(1)在 Android 4.3 之前,app进程 可以直接借助 有SUID标志位的su二进制文件 来获取root用户权限。
(2)Android 4.3之后,app进程基于SUID获取root权限的方案被禁用。主要措施是:

  • /system 和 /data 分区以 nosuid option被挂载,让文件的SUID标识失效。
  • app进程是由zygote 进程 fork产生的。zygote进程设置了NO_NEW_PRIVS标志,父进程的NO_NEW_PRIVS位会在父进程fork、clone和execve时,被子进程继承 ,并且不能被撤销。NO_NEW_PRIVS标志会让当前进程在执行可执行文件时,进程的EUID和EGID不受可执行文件的SUID和SGID位影响

关于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的其他限制:

  • 仅当进程的cap_bset数组中有 SETUID/SETGID capability时,进程才能切换 UID。而从Android 4.4开始,zygote fork app进程时,会对所有fork出来的子进程进行CAPBSET_DROP动作,让子进程不具有任何capability。
  • 从Android Oreo开始,OS通过SECCOMP过滤器阻止某些SYSCALL,app进程更改UID/GID的能力被进一步抑制。

(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

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值