LWM: Kernel运行时的系统安全工具

640
点击上方蓝色“ Linux News搬运工”关注我们~

Kernel runtime security instrumentation

By Jake Edge


LSS-NA

KRSI 项目全称kernel runtime security instrumentation,这个项目的主要目的是希望能减轻在Linux运行过程中的攻击带来的风险。项目的开发者KP Singh在圣地亚哥八月下旬举行的2019 Linux Security Summit North America (LSS-NA)上介绍了这个项目。KRSI的原型通过LSM (Linux security module)形式已经实现出来了,可以将eBPF program挂载到kernel的security hook(安全挂钩点)上。

Singh先介绍了他研发KRSI的动机。谈到系统安全性的时候,其实有两个方面:signals和mitigations。signals就是指一些可能意味着(并不是100%确定)系统有一些异常活动的迹象、事件。而mitigation则是指在检测到异常行为之后所采取的补救措施。这两者密不可分。

例如,audit子系统可以提供一些异常行为的signal。安全研究者可能会有一个程序来确定这个行为本身是不是真有问题,有问题的话则要升级LSM所配置的policy来限制、阻止这个异常行为。Audit也还需要把这个异常事件记录下来。他希望能用一个统一方案来指明signal和mitigation,这样两者能更好的配合。这就是KRSI所能提供的能力了。

他给了几个例子来说明各种类型的signal。如果有个程序执行之后删除了自己的可执行文件,那么就很可疑。如果某个kernel module在加载后把自己隐藏掉,那也很可疑。某个进程如果执行时特地指定了某些特殊环境变量(例如LD_PRELOAD)那也可能说明有什么猫腻。

关于mitigation也有一些例子,例如管理员可能不希望在server上启动到某个时间点之后挂载U盘。也可能有各种不断更新的黑名单白名单来管理哪些kernel module可以被加载;避免某些可疑代码执行;在某个程序要加载系统library的时候暂停它的执行,确保更新完成。每次要更新这些signal或者mitigation策略的时候都需要在kernel里很多地方进行配置,既费时间,又需要人工介入。他很希望能找到一个方法能统一配置好。

eBPF + LSM

他创建了一个新的eBPF program类型,专用于KRSI LSM。提供了一些eBPF helper函数作为“unified policy API”,可以用这套API来统一配置signal和mitigation。这些专用于安全方案的helper函数可以用来配置各种需要的行为。

经常有人问Singh为什么他要用LSM,而不是其他方案。他认为,安全行为跟LSM关联得更加紧密。而seccomp filter等方式不适用,是因为它们都是基于系统调用进行拦截的,很多安全相关的行为都是由多个系统调用组合起来完成了,光拦截系统调用的话很容易遗漏。而LSM hook是拦截我们关心的行为的。他也希望他的工作能够对LSM生态系统都带来帮助。

640

他同一些安全工程师讨论过它们有什么需求,其中一位提到需要在程序执行时记录LD_PRELOAD的值。这个可以通过KRSI来实现,只要在bprm_check_security() LSM hook这里(每次程序执行的时候都会执行这里的代码)增加一个BPF program。这样KRSI注册的函数执行的时候,就会调用到BPF program来跟user space的守护进程等通讯,从而决定是否要增加更多限制、保护。

他的目标是让这些helper函数能达到“precise and granular" (精确并且粒度合适)的标准。与BPF tracing API不同,这些helper函数不能访问kernel内部的数据结构。在他的ppt里面圈出了bpf_probe_read()并且划掉,说明他希望尽力避免执行它。这里的目的是希望能保持旧版本的兼容性,不要让helper依赖某个kernel版本。

然后他介绍了其他几种可能的实现方法,以及为什么他觉得那些方法不合适。首先是为什么不直接用audit?它的主要问题是mitigation的处理需要用其他方法来完成。此外,如果把更多的东西加入audit,也会引入不少性能损失。他会在ppt里面展示一些具体数据。此外,audit消息有严格的格式要求,解析过程可能会拖慢user space守护进程的响应速度。

接下来是Seccomp配合BPF。此前他也提到过,比起系统调用截获方式来说,安全行为跟LSM hook对应的更加好。他也比较担心系统调用参数处理过程中time-of-check-to-time-of-use (TOCTTOU,就是太早检查了,在使用的时候可能已经有变化)问题导致的race condition。不过他也承认他并不确定是不是真有这种问题。

还可以用kprobe加上eBPF来实现。这个方案也非常灵活,不过它的问题是会依赖kernel内部数据结构的分布位置。这样就比较难用,因为换一个kernel就需要重新编译一次。并且kprobe本身的API也不是稳定,kernel里经常有相关的函数增减,这些都会引入额外改动。

最后提到的一个方案是Landlock LSM。这个方案是用来提供非特权进程的安全沙盒的。KRSI则不同,更关注监测、处理安全相关的行为。所以,Landlock LSM主要是给非特权权限的进程用的,而KRSI则是需要CAP_SYS_ADMIN权限才能工作的。

Case study

此后他介绍了一个实用例子:监控在程序执行时设置了的环境变量。这个工作看起来简单,其实实现起来还是不容易的。比如说,运行起来的时候有可能会有占满32页的环境变量,他第一次看到的时候也非常惊讶。

他考虑了两种不同方式来实现eBPF helper,一种是把所有的环境变量都返回回来,另一种则是返回所关心的环境变量。后者的耗时会更少,更加合适一些,尤其是通常只需要监控少数几个环境变量的场景。不过这两种helper实现方式都有可能会进入page fault引起的睡眠,而eBPF program不允许出现这种情况。

Singh做了一些简单的性能测试,确保KRSI不会彻底无法工作。不过得到的数据还是需要做些处理才能看懂。他先跑了100遍一个什么都不做的程序,拿平均执行时间在几种系统上做对比,分别是:关闭了audit的Linux;打开audit的Linux,不过未打开任何audit策略;用audit仅来记录execve()调用;用KRSI来记录LD_PRELOAD的值。前两种配置下的平均耗时都是略超过500us(518和522),而用audit加上配置策略的方案则耗时663us(数值抖动比起其他测试方式更加大),KRSI测试则是543us,数据还不错,所以他决定继续往这个方向推进下去。

他也认为还有很多东西值得探讨。目前KRSI使用了perf ring buffer来跟user space通讯,这个方案很快,eBPF本身已经有了实现这个功能的helper。不过这个ring buffer是个per-CPU的buffer,因此占用的内存会更多,在多CPU的平台上就更加严重了。

还有eBPF program最好能够支持sleep,这样会大大简化KRSI的实现,也能使用更少的内存。目前来说,LSM hook需要把eBPF program会用到的memory都锁定住(不允许swap out)。他寄希望于Linux Plumbers Conference会议上的BPF microconference能在这方面有些进展。

在答疑环节,Landlock开发者Mickaël Salaün提出建议希望能合作。他也考虑过Singh会议上讲到的那些各种实现方式,他的结论是Landlock可以跟KRSI配合起来。Singh所他其实还没有完全跟上Landlock的进展,不过如果两者最终目标都是相同的话,他很愿意联合起来推进。

[I would like to thank LWN's travel sponsor, the Linux Foundation, for funding to travel to San Diego for LSS-NA.]

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

极度欢迎将文章分享到朋友圈 
热烈欢迎转载以及基于现有协议修改再创作~

长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值