1.背景虽然经常更新内核版本通常被认为是一种安全最佳实践,但由于种种原因,尤其是生产环境中的服务器无法做到这一点。这意味着在机器运行的时候,会有已知的漏洞(当然也会有一些未知的漏洞)进行攻击,所以需要有一些方法来检测和防止这些漏洞被利用,也就是Linux内核运行时保护(LinuxKernelRuntimeProtectionLKRG)的诞生目的。LKRG来自Openwall项目,该项目以其增强安全性的Linux发行版而闻名。Openwall创始人亚历山大·佩斯利亚克(AlexanderPeslyak)在安全领域也非常有名。在那年1月底,他宣称LKRG是“我们有史以来最具争议的项目”。Peslyak在LKRG0.1发布公告中说,0.0版本“相当草率”;首席开发人员Adam“pi3”Zabrocki根据10天的反馈策划内容并添加了一些新功能。LKRG在运行时检查Linux内核的完整性,并检测内核安全漏洞。LKRG是一个内核模块(不是内核补丁),因此它可以在不打补丁的情况下针对各种主线和分发内核构建和加载。目前支持的内核版本已经更新到5.19,支持x86-64、32位x86、AArch64(ARM64)和32位ARMCPU架构。2、LKRG技术原理分析LKRG对正在运行的Linux内核进行检测,希望对运行进程用户id等凭据被非法修改(完整性检查)及时做出响应。对于进程凭据,LKRG会尝试检测漏洞并在内核基于未经授权的凭据授予访问权限(例如打开文件)之前采取措施。JuhoJunnila的题为“EffectivenessofLinuxRootkitDetectionTools”的论文表明,LKRG可以用作有效的内核Rootkit检测器。LKRG阻止了对许多预先存在的Linux内核漏洞的利用,并且可能会检测和防御许多未专门尝试绕过LKRG的未来漏洞利用(包括未知漏洞)。虽然LKRG在设计上是可绕过的,但这种绕过需要更复杂和/或不太可靠的漏洞利用。LKRG的核心是一个可加载的内核模块,它试图检测正在运行的内核是否已被更改以指示正在对其使用某种类型的漏洞利用。除其他外,它可以检查系统上运行的进程是否对各种凭据进行了未经授权的修改,以防止这些更改授予额外的访问权限,而这正是该漏洞利用程序试图做的事情。3.LKRG进程为了跟踪正在运行的内核,LKRG创建了一个数据库,其中包含有关系统和在其上运行的内核的各种信息的哈希值。它跟踪系统中可用和活动的CPU,以及它们的中断描述符表(idts)和特定于模型的寄存器(MSR)的位置和内容。由于插入(或从系统中拔出)的CPU数量发生变化,内核可能会自行修改,因此LKRG必须准备好根据这些事件重新计算一些哈希值。除了跟踪内核.text、.rodata和异常向量表外,LKRG还跟踪每个加载的内核模块,包括其结构模块指针、名称、.text大小和哈希值,以及模块特定信息。为了检测修改,需要定期验证存储的值。这是通过多种机制实现的:首先是周期性检查定时器,检测周期可以通过sysctl接口设置;它还运行检查;系统中的其他事件(如CPU闲置、网络活动、USB更改等)将触发验证,尽管只有一定比例的时间会减少对性能的影响。例如,CPU空闲将触发0.005%的时间验证,而USB更改将触发50%的时间验证;所有这些都是为了保护运行时内核本身的完整性,但漏洞利用通常会针对系统上运行的进程进行提升权限等。这些信息保存在内核的内存中。所以LKRG还跟踪每个进程的一堆不同属性,并维护它自己的任务列表,用于验证内核列表。如果两个进程出现分歧,受影响的进程将被终止,目的是防御利用差异的攻击。LKRG跟踪的目标包括任务属性,如task_struct的地址、进程名称和ID、cred和real_cred凭证结构的地址、与其关联的各种用户和组ID、SELinux设置和seccomp配置。所有这些信息都会在每次系统调用(例如setuid()、execve())或系统中的其他事件(例如打开文件前检查权限)时进行验证。此外,每次运行内核验证时都会执行进程列表验证。每次都会验证所有进程,而不仅仅是进行系统调用的进程,任何差异都将导致终止有差异的进程。LKRG测试了一些已知的内核漏洞(如CVE-2014-9322、CVE-2017-6074),性能影响约为6.5%。4.非法提权(IllegalElevationofPrivileges)Token/pointerswapping非法调用comit_creds()覆盖cred/read_cred结构SandboxescapeNamespaceescapecontainerescape异常修改CPUstatus异常修改kernel.text和.rodatasection5.BypassLKRG防御为了说明LKRG的漏洞检测能力,在分发内核的测试中,LKRG成功检测到CVE-2014-9322(badret)、CVE-2017-5123(waitid(2)missingaccess_ok)、CVE-2017-6074(在DCCP协议中使用后免费),一些预先存在的漏洞。但是,它无法检测到CVE-2016-5195(脏牛)漏洞,因为这些漏洞直接针对用户空间,甚至通过内核。DirtyCOW中LKRG的“绕过”是由于漏洞的性质和利用方式,这是未来直接针对用户空间利用类似LKRG绕过的一种方式。从检测端避开LKRG:覆盖LKRG不保护的关键元数据,将攻击转移到用户空间赢得比赛从正面攻击LKRG的角度:攻击LKRG内部的同步机制和锁机制找到所有LKRG的上下文并通过内核禁用它们直接攻击用户空间(如DirtyCOW)第六,增强LKRG防御计算密钥元数据的哈希值保护范围:发送到所有CPU中的核心数据IPI(Inter-Processor-Interrupt),并独占运行LKRG的保护功能(IDT/MSR/CRx/etc)动态加载的模块及其在内部结构中的顺序;如果有任何IOMMU也可以防止pCFI机制来检测ROP检测堆栈迁移使用非.text数据使用动态生成可执行页面使用sysctl动态配置LKRGroot@ubuntu:~/lkrg#sysctl-a|greplkrglkrg。block_modules=0lkrg.heartbeat=0lkrg.hide=0lkrg.interval=15lkrg.kint_enforce=2lkrg.kint_validate=3lkrg.log_level=3lkrg.msr_validate=1lkrg.pcfi_enforce=1lkrg.pcfi_validate=2lkrg.pint_enforce=pint_validate.profile1lkrg=2lkrg.profile_validate=9lkrg.smap_enforce=2lkrg.smap_validate=1lkrg.smep_enforce=2lkrg.smep_validate=1lkrg.trigger=0lkrg.umh_enforce=1lkrg.umh_validate=17.结论从上述LKRG原理来看,对于威胁模型,需要仔细考虑内核以及有特定需求的个人或公司,LKRG的功能是有价值的。因此,它可以作为系统级纵深防御策略中的另一道防线,而不是“一招胜天”的灵丹妙药。我们知道内核充满了各种类型的自修改代码,从跟踪点和其他调试功能到各种优化,因此在运行时保护内核的完整性并非易事。作者简介:许庆伟:龙蜥社区eBPF技术探索SIG组Maintainer&LinuxKernelSecurityResearcher
