20199317 2019-2020-2 《网络攻防实践》综合实践

PeX: A Permission Check Analysis Framework for Linux Kernel

一. 介绍

  • PeX: Linux内核的权限检查分析框架,这篇论文来自usenix security 2019

  • 权限检查通过为特权功能提供访问控制,从而在操作系统安全性中发挥重要作用。然而,对于内核开发人员来说,正确地应用新的权限检查并可伸缩地验证现有检查的可靠性是特别具有挑战性的,这是由于内核的代码基数大且复杂。

  • 这篇论文介绍了一个用于Linux内核的静态权限检查框架PeX
    ○ PeX可以很好地、可伸缩地检测出内核代码中任何丢失的不一致的冗余的权限检查。从高层次上讲, PeX静态地探索从用户入口点(例如,系统调用)到特权函数的所有可能的程序路径,并且检测出其中的错误。
    ○ 以一组已知的权限检查作为输入,自动识别出所有其他的权限检查(包括他们的包装器)。并且,PeX的控制分析也能够自动识别出每个权限检查和它们潜在的特权函数之间的映射

  • 本文的贡献总结如下:
    ○ 新技术:我们提出并实现了PeX,一个用于Linux内核的静态权限检查分析框架。我们还开发了新的技术,可以执行可伸缩的间接调用分析,并自动识别权限检查和特权函数的过程。
    ○ 实际影响:我们使用 PeX 分析了最新Linux内核v4.18.5中的DACCapabilitiesLSM权限检查,发现了36个新的权限检查错误,其中14个已经被内核开发人员确认
    ○ 社区贡献:我们将以开源项目的形式发布PeX,同时发布的还有已确定的权限检查和特权函数之间的映射。这将允许内核开发人员使用PeX验证他们的代码,并使用他们自己的领域改进映射,从而为PeX做出贡献。

二. 背景:Linux中的权限检查

2.1 自主访问控制(DAC)

  • DAC根据主体的身份或它们所属的组来限制对关键资源的访问。在Linux中, 为每个用户分配一一个用户标识符(uid)和一个组标识符(gid)。 相应地,每个文件都有其属性,包括所有者、组,以及所有者、组和所有其他用户的rwx(读、写和执行)权限位。当一个进程想要访问一个文件时,DAC根据进程的uid、gid以及文件的权限位授予访问权限。

  • 在某种意义上,DAC是一种粗粒度的访问控制模型。在这种Linux DAC的设计下,"root"绕过所有的权限检查。

2.2 Capabilities

  • 自Linux内核2.2(1999)以来,Capabilities 通过将根特权划分为小集合来支持细粒度的访问控制。例如,对于具有CAP NET ADMIN能力的用户,内核允许他们使用ping,而不需要授予完全的root特权。

  • CAP应该是细粒度的、不同的。然而,由于缺乏明确的范围定义,保护一个特权函数的特定Capabilities的选择是基于内核开发人员在实践中的理解而做出的。不幸的是,这就导致了CAP_SYS_ADMIN 的频繁使用(1167中有451个,超过38%),并且它只是作为另一个根处理; grsecurity指出, 有19个Capabilities确实相当于完整的根。

2.3 Linux 安全模块

  • LSM是在内核v2.6 (2003) 中引入的,它提供了一组细粒度的可插入钩子, 这些钩子被放置在内核的各个安全临界点上。系统管理员可以向LSM钩子注册自定义的权限检查回调,从而执行不同的安全策略。

  • LSM的一个常见用途是在Linux中实现强制访问控制 (MAC) (例如, SELinux ,AppArmor) : 例如,当一个进程试图读取一个符号链接的文件路径时,将调用security_inode_readlink来检查这个进程是否具有对符号链接文件的读权限。这个钩子的SELinux回调检查是否有策略规则可以授予这个权限(例如,允许domain_atype. b:lnk_file_read)。

  • 值得注意的是:LSM及其MAC机制的有效性在很大程度上取决于钩子是否在所有的安全临界点上正确地放置。如果一个钩子在任何临界点丢失,MAC就没有办法强制执行权限检查。

2.4 Linux中常用的权限检查

三. 权限检查错误的例子

3.1 Capabilities权限检查错误

  • 分析:图a显示了内核函数scsi_ioctl, 其中sg_scsi_ioctl(第7行)由两个 Capabilities 检查保护,CAP_SYS_ADMINCAP_SYS_RAWIO(第5行);

  • 分析:图b中,scsi_cmd_ioctl调用了函数sg_scsi_ioctl(第8行),但是没有任何的Capabilities检查;

  • 分析:图c中,sg_scsi_ioctl调用blk_verify_command,后者反过来检查CAP_SYS_RAWIO;

  • 综上所述,scsi_ioctl检查了CAP_SYS_ADMIN一次,但是检查了CAP_SYS_RAWIO两次,导致了一次多余的权限检查。另一方面,scsi_cmd_ioctl 只检查CAP_SYS_RAWIO,造成缺少对CAP_SYS_ADMIN的权限检查。

  • 总结:PeX将上面的错误检测为不一致的权限检查,因为这两条路径不一致,进一步的研究表明,其中一条路径是冗余的,而另一条是缺失的。

3.2 LSM权限检查错误

  • 分析:图a显示了在readlinkat系统调用中LSM的使用。在它的调用路径上,vfs_readlink(第7行)受到LSM钩子security_inode_readlink (第4行)的保护。

  • 分析:图b给出了系统调用ioctl的两个子函数。loctl 调用ksys_ioctl, 它在do_vfs_ioctl(第6行)之前包含它自己的LSM钩子security_file_ioctl(第4行)。然后,从do_vfs_ioctlxfs_readlink_by_ handle (第10行)有一条路径,最终调用特权函数vfs_readlink (参见图a中的第7行和图b中的第13行)。虽然vfs_readlink受到readlinkat中的LSM钩子security_inode_readlink 的保护,但是通过xfs_readlink_by_handle的函数的路径却不是这样。

  • 问题是SELinux为readioctl保留了单独的“允许”规则。当缺少LSM security_inode_readlink检查,只具有"ioctl allow rule"的用户可以利用ioctl系统调用来触发vfs_readlink 操作,而这样的操作应该只会被不同的"read allow rule"所允许。

四. 挑战

4.1 内核中间接调用分析

  • 第一个关键挑战是linux内核中间接调用的频繁使用,以及以可伸缩的、精确的方式静态分析间接调用的困难
    为了实现模块化设计,内核提出了一组不同的抽象层,这些抽象层指定了不同具体模块的公共接口。例如虚拟文件系统(VFS),抽象了一个文件系统,从而提供了一种统一的、透明的方式来访问本地(例如ext4)和网络(例如nfs)存储设备。
    在这个内核编程范式下,一个抽象层将一个接口定义为一组间接函数指针,而一个具体模块则用自己的实现来初始化这些指针。

  • 内核庞大的代码基数使得对内核接口中大量函数指针的解析成为一个挑战性问题,这也使得现有的精确指针分析技术不可伸缩。而SVF,这种使用流和上下文敏感值流的高精度先进分析技术,也不能运用到庞大的Linux内核中去。
    基于类型这种简单的函数指针分析技术虽然能够运用到Linux内核中,但是由于在内核中的函数指针通常共享相同的类型,从而导致很多的错误定位,基于类型的间接分析的精确度也就不高。

4.2 缺乏完整的权限检查、特权函数及其映射

  • 第二个挑战是在Linux中健全地列举出一组权限检查,并推断出权限检查和特权函数之间的映射
    虽然已知一些常用的DACCapabilitiesLSM权限检查,但是内核开发人员经常设计一些在内部使用基本权限检查的自定义权限检查(包装程序)。然而,此类权限检查的完整列表从没被记录下来。而且,Linux内核没有明确指定哪个权限检查应该保护哪个特权函数的文档。现有的静态权限错误检查技术并不适用于解决这些问题。

五. PeX的设计

5.1 PeX的静态分析结构

  • PeX以内核源代码权限检查作为输入,报告并输出权限检查错误。PeX还在已识别的权限检查和特权函数之间生成映射,作为输出。

  • 下面根据这个结构进行具体分析。

5.2 KIRIN 间接调用分析

5.2.1 间接调用目标收集

  • 在Linux内核中,一个内核接口通常是在由函数指针组成的C结构中定义的。很多内核接口(C结构)静态地被分配和初始化。一些接口可以在运行时动态地分配和初始化以进行重新配置。

  • 对于前者,KIRIN线性地扫描所有Linux内核代码,找到所有被静态分配和初始化的带有函数指针字段的struct对象。然后,对于每个struct对象,KIRIN 使用偏移量作为字段的键值来跟踪哪个函数地址被分配给哪个函数指针字段。

  • 对于其余动态初始化的内核接口,KIRIN 在内核接口中执行一个数据流分析,以收集一个函数地址到函数指针的任何分配。KIRIN的字段敏感分析允许收集目标与内核接口的单个字段相关联。

5.2.2 间接调用站点解析

  • KIRIN 将前边第一次传递的结果存储在key——value映射数据结构中,其中key 是一对内核接口类型和一个偏移量(字段),value 是一组调用目标。在每个间接调用站点中,KIRIN 从LLVM IR中检索出内核接口的类型和偏移量,使用它们作为key以查找映射,并计算出匹配的调用目标。

  • 当把KIRIN应用于Linux内核时,我们发现在某些调用站点中,内核接口类型并没有出现在LLVM IR中,这就使得对它们的解析变得不可能。例如,宏container_of通常用于通过使用指向自身成员字段的指针来获取结构对象的起始地址。

5.3 调用图的产生和分区

  • 用户空间可访问函数:从带有公共前缀SyS_ (表明系统调用入口点)的函数开始,PeX遍历调用图,标记所有访问过的函数,并将这些函数视为用户空间可访问函数。研究此分区中用户可访问的函数是否存在权限检查错误。

  • 内核初始化函数:收集仅在启动期间使用的函数,以探测冗余检查。Linux 内核从start_kernel函数启动,调用一个使用通用前缀_init的函数列表。PeX 从start_kernel和每一个_init 函数开始,执行多个调用图遍历,去收集这些函数。

  • 其他函数,如IRQ处理程序和内核线程函数,由于不能直接从用户空间调用,在以后的分析中不会用到。

5.4 权限检查包装器检测

  • PeX将用户提供的不完整的权限检查列表作为输入。从这些权限检查开始,PeX通过在扩张的调用图上执行正向调用图切片来检测基本的权限检查。对于一个给定的权限检查函数,PeX搜索函数内的所有调用指令,查找将函数的参数传递给被调用函数的指令。换句话说,PeX标识出了权限检查函数的各个被调用函数,这些被调用函数将其实际参数作为它们自己的形式参数。类似地,PeX 然后从这些基本权限检查中执行向后调用图切片,以检测出其包装器的列表。PeX 仅将那些传递权限参数的调用函数看作包装器,不包括其他仅使用权限检查的调用函数。

  • 如下为每次检测时权限检查包装器的示例:给定一个已知的权限检查ns_capable(第10-13行),PeX首先找到security_capable(第4行)作为一个基本的权限检查,然后基于它,PeX检测出另一个权限检查包装器has_ns_capability(第14-20行)。注意,参数cap从父节点ns_capable_commonhas_ns_capability传递给子节点security_capable;返回security_capable的结果。

5.5 特权函数检测

  • PeX利用了一个过程间控制分析,该分析可以自动识别被一个给定权限检查保护的特权函数。PeX 适当地将那些调用指令的所有目标(被调用函数),即在ICFG的基础上的每个权限检查所控制的目标(被调用函数),当作其潜在的特权函数。

  • 控制分析的基本原理是基于以下观察结果:由于没有一条路径允许不访问控制者就可以访问控制调用指令(即权限检查),所以被调用函数的情况很有可能是它在所有路径上应该被检查保护着。

  • 特权函数检测算法

5.6 非特权函数过滤器

  • PeX应用基于启发式的过滤器来删减错误的特权函数。在当前的原型中,过滤器包含了一组不是特权函数的内核库函数,例如,kmallocstrcmpkstrtoint.

  • PeX目前的设计是为了避免假阴性(因此只利用了一小组库过滤器),但是可以添加更具攻击性的过滤器来清除更多错误的特权函数。

5.6 特权函数错误检测

  

六. 实现与评估

6.1 KIRIN 的评估

  

  • 解析率: K-Miner 只能解析间接调用站点的1%;只能用于defconfig, 不用于allyesconfig.
  • 解析的平均目标:对于KIRIN来说,每个已解析的间接调用站点的平均间接调用目标数比基于类型的方法要少得多。
  • 分析时间:基于类型的方法是最快的,可以在1分钟内完成对两种配置的分析。KIRIN的运行速度比基于类型的方法慢。但是,对于defconfig, KIRIN的分析时间 (≈1分钟)与基于类型方法的分析时间相当,而KIRIN对allyesconfig 的分析时间为6.6分钟。基于SVF的K-Miner完成对defconfig的所有系统调用的分析大约需要9869分钟,比KIRIN慢得多。

6.2 PeX的结果

  

  • 使用不同的间接调用分析时PeX警告的比较

    ○ 对于allyesconfig, PeX+TYPEPeX+KM在12小时的实验限制内无法完成分析。PeX+TYPE在ICFG中产生了太多的(假)边,在PeX分析的最后阶段还发生了路径爆炸;在超时之前,只报告了19个bug。同时,PeX+KM在较早的指针分析阶段就已经出现超时,因此无法报告任何错误。
    ○ 对于defconfigPeX+TYPEPeX+KM都能够完成分析。在这个配置下,PeX+KIRIN (original)PeX+TYPE都报告了21个bug (是allyesconfig检测到的36个bug中的一个子集)。PeX+ KM产生有限数量的警告,导致只检测到6个bug,其余的都没有发现。

6.3 PeX报告的Bug

  

七. 论文复现

八. 总结与心得

  • 通过这门课的学习,我由衷地开始敬佩那些黑客们,以前对黑客的印象只是停留在电影里,很是虚幻,而我现在对黑客的感觉就是——大神大神大神!!!能够被称为黑客,本身就说明其具有极高的专业技能。还有就是以前总以为黑客就是破坏网络世界、损害国家社会及他人利益的代名词,而这门课的课本从一开始就澄清了“黑客”这个词的概念,它是有黑帽子白帽子灰帽子之分的,“黑帽子”才是对社会带来负面作用的骇客,“白帽子”则是对社会积极作用的黑客,并且白帽子的存在对于网络世界的安全具有极大的价值和意义,正是有了这些白帽子,才得以抵御黑帽子的入侵与破坏,保证国家社会网络生活的正常进行。

  • 从搭建网络攻防的实验环境到网络踩点收集有效信息,再到后边每次实践都会用到多种工具,一步步深入到最后能够远程控制受害者主机以及植入后门方便下次攻击,最后的综合实践也是给了我们认真看论文学习怎么看论文的机会,还是收获很多的。

  • 学习必须与实践相结合,知识如果不加以实践,终究是纸上谈兵,一到应用阶段就溃不成军,实践能够加深我们对于知识的理解,加强我们的动手能力,培养我们的动手能力以及独立思考的能力,这些对于我来说还是很有价值的。另外,通过这门课的学习,我也深深感到网络世界的危险性,个人隐私保护的重要性,以及安全意识的培养对于每一个公民的重大意义。

  • 从寒假开始的寒假作业,一直到最后的综合实践,难度是越来越大,我也从一开始的能够跟得上课程到后边一次一次跟不上,每次作业完成都只能参考同学的博客才可以完成,而且对于每次的实践作业也是似懂非懂,最后的综合实践也是好难好难好难。

posted on 2020-07-02 22:17  20199317-程峥华  阅读(310)  评论(0编辑  收藏  举报

导航