前言
以前就知道如果Linux
服务以非root的方式运行会增强系统的安全性,但如何去实践呢?
Linux安全基础
安全设计原则
- 最小安全原则
一般应尽可能缩小权限的授予范围
技术手段
- 用户隔离
rwx
读写执行权限capability
特权权限- PAM体系
pam_cap
模块 - ACL等
简单非root用户运行方案
一般的应用,用非root用户做隔离,对于文件仅所有者拥有读写、执行、权限,同组内和其它组的用户可以根据场景,设定合理的权限就可以完成,原则就是最小安全原则,不过多授予权限!
涉及特权的的方案
粗浅介绍
对于某些需要添加和修改系统的IP
,和创建RAW
套接字的应用,那么在rwx
和用户隔离的基础上,需要通过setcap
操作进行特权授权,但整体上玄机并不多。
可以看到rwx
为整个安全控制的基础,与capability
特权权限形成权限检查链条,某一环节的卡壳,就会可以造成服务不可用。
简单场景,我们依然将这些需要特权的服务部署在以用户隔离的目录下,并设定合理的rwx
权限,然后以root
用户身份,通过setcap
操作授予特权用户目录下某(些)启动程序获得特权。
即使这些用户具有一些特权,但是,由于是非root用户,对于其它用户的文件资源,并不能偷窃,这也实现了一定程度的安全性。
特权集介绍
这个概念纠缠的原因就在于实际上区分进程特权集和文件特权集,特别在可继承特权集的设定上,完全是南辕北辙。
进程可继承特权集是南向的,面向下游进程树传播;文件可继承特权集是北向,会与上游进程的南向特权集进行相与判断。
进程/线程特权集
- CapInh = Inheritable capabilities
决定在进程树下如何进行特权继承,注意,此处需要区分是否
capabilities aware
,后续进程启动二进制文件是否主动进行了setcap
授权
- CapPrm = Permitted capabilities
允许的特权集
- CapEff = Effective capabilities
当前特权集
- CapBnd = Bounding set
系统可用特权集
- CapAmb = Ambient capabilities set
环境特权集,并没有通过
setcap
授权的连带程序如何自动获得特权的机制
文件特权集
- e
可以生效的特权集
- p
允许的特权集
- i
决定是否从上游继承某些权限
对于文件通过setcap
能够借助root用户授予特权属性,又可以看作Linux
一切都可以看做文件的深入设计
优先级最高
相对于Ambient capabilities set
的自动传播,如果某文件特殊设定了特权集,则以明确设定的为准,见特权生效算法介绍
最佳实践
在服务中存在某个根启动程序,从此启动程序可以创建出一颗进程树出来,但仅需对此根启动程序在非root用户运行时,通过setcap
文件特权集进行授予权限,其它涉及的程序并不进行主动设定,通过Inheritable capabilities
和Ambient capabilities set
,进行进程树的特权权限的传递、传播。
与docker容器特权传递类似
弱点
相比较于对每个设计文件进行setcap
授权,通过Inheritable capabilities
和Ambient capabilities set
进行传播特权的方式,相当于粗放管理,但是,部署会比较简便。
在恶意攻击的i情况下,攻破这个进程树的某一个进程,就可以获取到比较多的特权。
PAM的孱弱
通过pam_cap
模块,PAM aware
程序,例如,su
、sudo
程序,见/etc/pam.d/下对应的配置,启动后的进程自动获得在/etc/security/capability.conf
中根据用户配置/可继承权限Inheritable capabilities
。
但是,因为pam_cap
模块版本的限制,并不能设置Ambient capabilities set
,对于未经setcap
授权二进制文件所启动的进程,并不能形成很好的权限传递和传播!
在libcap-2.58+版本支持了
Ambient capabilities set
的设置
pam_cap失效的一种原因
按照man中的介绍,在/etc/security/capability.conf
中配置auth optional pam_cap.so
并不能生效的原因是因为,配置在PAM
鉴权栈中如果遭遇requisite
、sufficient
很早就提前返回了,并不能将配置生效!
systemd.service机制
- AmbientCapabilities
配置字段可以考虑