前面在《林老师之系统安全系列三》这篇文章中曾经介绍过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 | CAP_AUDIT_CONTROL 启用和禁用内核审计;改变审计过滤规则;检索审计状态和过滤规则 |
更多可参考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