Linux-capability

前面在《林老师之系统安全系列三》这篇文章中曾经介绍过SUID这种机制,但是这种方式也存在着安全隐患,例如vim如果不小心被suid修饰,那么它就可以去修改/etc/shadow这个文件,另外如果一个被suid修饰的二进制程序存在漏洞,就可能会被利用,root权限外流。所以今天讨论一种能力(capability)机制。

为什么SUID机制不安全呢?主要原因是因为SUID对于权限控制太过粗放,一旦被修饰了s位,便拥有了root的权限,如果程序没有漏洞,那么就以root身份安分地执行该做的事;如果该程序存在漏洞,那么可能就会突破程序本身所涉及的范围,以root权限去干一些其他的事情;所以权限需要细分,目前二进制程序只在需要特权的时候才将自己的euid设为0,这里应该就是对应我们曾说过的Saved UID(暂存用户ID),还有一种实现按需授权的能力(capability)机制。

capability

该机制将root的权限进行功能组细分,可以分别启用或禁用,在执行特权操作时,如果euid不是0,便去检查该进程是否具有该特权操作所具有的capability,capability细分到线程。

常见的capability

1
2
3
4
5
6
7
8
9
10
11
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 允许锁定共享内存片段
……

更多可参考capabilities

capability可以在进程执行时赋予,也可以从父进程中继承。

线程的capabilities

每一个线程,对应着5个capabilities集合,每一个集合包含0个或多个capability,分别是:

  • Permitted
  • Effective
  • Inheritable
  • Bounding
  • Ambient

Permitted

该集合定义了线程所能拥有的特权上限,不在该集合中的capability,该线程就不能使用这个capability所对应的特权操作。

Effective

检查线程是否拥有执行某种特权的capability时,检查的是该集合,那Permitted这个集合是干啥的呢?Effective集合是Permitted集合的子集,可以删除Effective集合中的某个capability,在需要时,再从Permitted集合中移入,可以达到临时禁用的目的。

Inheritable

通过execve启动的新程序可以继承的集合。

Bounding

如果某个capability不在Bounding集合中,即使它在Permitted集合中,该线程也不能将该capability添加到它的Inheritable集合中(也就是说Bounding里的才是可以往下继承的,而Permitted里的不一定能往下继承)。Bounding集合在执行fork系统调用时会传递给子进程的Bounding集合,并且在执行execve系统调用后保持不变。
当线程运行时,不能向Bounding集合中添加capabilities;一旦某个capability被从Bounding集合中删除,便不能再添加回来。
将某个capability从Bounding集合中删除后,如果之前Inherited集合包含该 capability,将继续保留;但如果后续从Inheritable集合中删除了该 capability,便不能再添加回来。

Ambient

不是很懂

另外文件也有这种机制

文件的capabilities

文件与线程的capabilities共同决定了通过exec运行该文件后的capabilities。
文件的capabilities对应着三个集合,分别是permitted、inheritable和effective