Linux Security Module逆向分析实战

本文记录了对某发行版Linux中一个安全模块(LSM)的逆向过程,该LSM对系统中待运行的程序进行安全校验,数据流穿越内核态与用户态,涉及系统内核及系统服务。此LSM对系统安全性的增强效果明显,其设计思路值得防守方研究学习,可于个人终端或服务器安全防护中应用。特此对逆向内容记录,希望能为读者在终端防护方面拓宽思路,同时欢迎感兴趣的师傅们交流学习。

一. LSM框架简介

Linux安全模块(Linux Security Module,LSM)框架是Linux操作系统内核提供的一种安全机制,它通过内核扩展实现hook函数以完成多种安全检查,通常用于强制访问控制(Mandatory Access Control)。虽然被称作“模块”,但不同于LKM,这些扩展并不是可加载的内核模块,而是和内核代码一起编译在内核文件(vmlinuz)中。可以通过如下命令查看本机启用的LSM,cat /sys/kernel/security/lsm。常见的LSM包括SELinux、Yama等。

LSM框架的hook点设置于内核访问关键对象前,通过调用LSM中实现的hook函数,判断是否可以进行访问。如果有多个LSM,则会根据初始化的顺序依次判断,都允许才能进行访问。上述关键对象包括程序、进程、套接字、文件系统等,可在/usr/src/linux-headers-YOURSYSTEMVERSION/include/linux/lsm_hooks.h中查看详细的hook说明。

这里以程序启动过程为例,简单说明LSM工作的机制。当通过execve系统调用执行一个新程序时,内核最终会执行到__do_execve_file函数完成相关工作,在这里会调用prepare_binprm函数填充struct linux_binprm,填充前会调用security_bprm_set_creds进行安全检查。security_bprm_set_creds就是LSM框架提供的hook,它会依次调用注册在这个钩子上的回调函数,完成安全检查。此流程上相关代码以及此钩子的说明如下。

LSM开发时,通过如下函数定义安全模块的hook函数,逆向时通过此函数可快速定位具体的LSM以及相关回调函数。

二. 安全模块逆向分析

2.1 分析准备
本次分析的对象为某发行版Linux,此系统提供了可执行文件的签名校验功能,仅有签名的程序可以被执行,本次逆向的目标就是试图还原校验功能的框架和逻辑。由于此安全检查的存在,提权、后门等程序因为此机制的存在而无法直接运行,从某种程度提高了操作系统的安全性。编译一个hello world程序,运行,会提示无法通过系统安全校验目前不能运行。strace跟一下,看到在execve时就被干掉了(如下图),可以肯定是在内核中完成这个动作的,大概率是通过内核扩展实现。

下面尝试定位此内核扩展。lsmod看一眼,没有发现明显相关的。查看此系统的所有LSM,有一个名为elfverify的模块,通过此命名可以推断,就是此模块完成了程序的校验功能。

由于LSM是被编译在内核中的,因此接下来需要获取到此系统的内核文件。系统的内核文件通常可以在/boot目录中找到,其中vmlinuz的文件是压缩后的内核,可以通过extract-vmlinux工具提取未压缩的内核文件vmlinux进行分析。然而提取后的文件是没有符号的,符号信息存储在同目录下System.map文件中。这里推荐使用vmlinux-to-elf这个工具完成提取与符号修复工作,通过此工具可输出一个带符号的ELF文件,方便逆向分析。

2.2 LSM分析

反编译查看恢复后的内核,在elfverify的初始化函数elfverify_init()中,security_add_hooks()的第二个参数count为5,即此LSM一共注册了5个hook函数;跟踪一下第一个参数security_hook_list,可得到所有实现的回调函数,总结如下。


可以看出此LSM还对套接字、设备挂载进行了安全校验,这里专注于程序运行的校验,锁定hook_bprm_set_creds进行进一步分析。

跟进hook_bprm_set_creds,该函数首先对一些参数进行检查,接着判断是否开启了开发者模式(判断依据是某个文件的内容),如果符合条件则放行(返回0),否则调用access_verify进行进一步判断。此函数的参数类型是struct linux_binprm, 源码中此结构体被标记为__randomize_layout,这是Linux内核中的一项防御机制,有此标记的结构体其中的元素将作乱序排列,从而攻击者难以找到偏移具体对应的元素。因此通过静态分析,也暂时无法确定传递给access_verify的参数。

在access_verify中,会将当前进程通过add_wait_queue挂起等待,并将90-pid-UNKNOWN信息写入某个设备中,这里的90应该是LSM开发者自定义的一个“魔数”(socket校验中是91),而第三段的内容由于结构体的随机化也暂时无法确定(之后分析会知道其实是程序路径)。之后再从此设备中读取信息,根据内容选择是否继续执行,并从队列中移除进程。

LSM中关于elf校验的流程到这个函数基本就结束了,并不包含具体的校验逻辑,只是将待校验的进程信息写入某个设备并等待结果,可见校验应该是在另一处完成。经过跟踪分析,此LSM注册了一个杂项设备(在register_elf_verifier_dev()中),名为elf_verifier。下一步找到了谁从这个设备中读取信息,大概率就能定位到完成校验的具体代码。

然而,在内核中并没有找到相关的代码,下一步得去用户态的程序找找。

2.3 安全校验逻辑分析
查看一下系统进程,发现一条程序名为*-elf-verify,其ppid为1,看了下是系统服务,推断这就是处理杂项设备中数据的程序了。为验证推断,将此服务停止,运行一个自己编译的程序,待运行的进程“僵死”,推断应该是LSM将进程送入等待队列后,没有从杂项设备中读到校验结果,就造成了一直挂起的局面。这也确认了正是这个程序处理设备数据并给与返回结果,校验逻辑应当就在其中。

对此系统服务程序进行分析与调试,在进行ELF文件安全校验时,它会循环的从/dev/elf_verifier这个设备中读取内容,读取到的内容包括PID和完整的程序路径,并依据此信息进行校验,其主要检查如下两点:

判断此路径的程序是否在白名单或黑名单中

在ELF文件头的特殊节中提取签名(PKCS7),然后进行验证(证书在系统某路径中)
上述的黑白名单位于系统/usr目录下,仅root用户可编辑。而ELF文件头中的特殊节在其他普通的ELF文件中不会出现,应当是在对ELF文件进行签名时加上的,而将签名信息添加到文件头中又不会对程序的正常运行造成影响。如果能够顺利读取到签名信息,则调用openssl的相关函数进行校验。校验完成后,将检验结果写入/dev/elf_verifier,通知内核进行后续动作;同时如果校验不通过,会通过dbus通知GUI弹出提示告知用户。

至此,一次校验完成,整个签名校验功能的脉络基本摸清了。在其中还有一些细节检查,例如文件格式、ELF文件头等等,就不一一展开介绍了。

三. 总结

该系统的可执行程序签名校验功能,通过安全模块(LSM)elfverify、系统服务联合完成,二者通过杂项设备/dev/elf_verifier传递数据,完成了用户态和内核态的交互。在内核中,通过实现LSM的security_bprm_set_creds钩子在程序运行前获取到待运行程序的完整路径,将进程暂时挂起,同时将信息写入设备中;用户态程序从设备中读取到信息后,判断此路径程序是否在黑白名单、程序是否是经过签名的ELF程序,并将判断结果写入设备;内核LSM根据返回的结果确定是否允许执行。

整个过程涉及LSM、设备、ELF文件格式、签名校验等知识,有深有浅,本文记录的比较简单,欢迎感兴趣的师傅深入交流。同时,该方式利用LSM框架提供的钩子,对某些操作进行安全校验,同时将复杂的校验逻辑在用户态完成,通过设备完成数据传递,此类模式在终端安全防护上亦可借鉴。

最后

关注私我,获取【网络安全学习攻略

Linux Security Module逆向分析实战相关推荐

  1. 学习LSM(Linux security module)之二:编写并运行一个简单的demo

    转自:cnblog 各种折腾,经过了一个蛋疼的周末,终于在Ubuntu14.04上运行了一个基于LSM的简单demo程序. 一:程序编写 先简单的看一下这个demo: //demo_lsm.c #in ...

  2. Windows逆向分析实战:使用CE+OD获取用户信息

    序: 很多想学软件逆向分析的朋友们,初学者往往看到一大堆的技术资料,直接就懵了.本文以一个简单的例子,演示一下使用CE+OD进行内存的获取,然后使用Qt进行界面显示,让初学者简单了解逆向分析的流程,并 ...

  3. js逆向分析实战之七麦数据

    1.介绍:   要分析的网站是:https://www.qimai.cn/rank   ①当你打开网站,打开控制台的时候,网站有debugger检测,会陷入一个死循环,让你无法调试,如下图:   ②在 ...

  4. 学习LSM(Linux security module)之四:一个基于LSM的简单沙箱的设计与实现

    转自:cnblog 嗯!如题,一个简单的基于LSM的沙箱设计.环境是Linux v4.4.28.一个比较新的版本,所以在实现过程中很难找到资料,而且还有各种坑逼,所以大部分的时间都是在看源码,虽然写的 ...

  5. 最新战火互娱JS逆向分析实战教程

    目标网址:https://passport.kongzhong.com/ 重要说明:文章教程仅供参考学习,请勿用于非法用途,否则后果自负. 目录 一.接口参数分析

  6. 最新中烟新商盟JS逆向分析实战教程

    目标网址:https://xinshangmeng.com/ 重要说明:文章教程仅供参考学习,请勿用于非法用途,否则后果自负. 目录 一.接口参数分析 二.全局搜索j_mcmm关键词</

  7. 学习LSM(Linux security module)之一:解读yama

    最近打算写一个基于LSM的安全模块,发现国内现有的资料极少.因此打算自己琢磨一下.大致的学习路线如下: 由易至难使用并阅读两到三个安全模块->参照阅读模块自己实现一个安全模块->在自己实现 ...

  8. 拿走不谢!固件逆向分析过程中的工具和技巧(上)

    将固件逆向分析,然后再将逆向分析后的内容转换为有用的东西,这个过程对于所有人来说都是一个耗时又耗力的过程.有时即使文件出现在你面前,你也无能为力,比如你可能会面临专有(几乎没有文档记录)的文件格式.奇 ...

  9. 专访丰生强:Android软件安全与逆向分析

    [专家简介]   丰生强(@非虫)   Android软件安全专家:看雪论坛Android安全版版主,安卓巴士开发进阶板块版主.对Android软件与系统安全有狂热的爱好和独到的见解,对Android ...

最新文章

  1. python朴素贝叶斯回归预测的结果全是1_python – 朴素贝叶斯概率总是1
  2. 018_html文件路径
  3. ClickHouse最详细的入门教程(一):部署运行
  4. 【学术相关】博士新生应该懂得哪些道理?
  5. AgileConfig - RESTful API 介绍
  6. 计数方法应用于PTB数据集
  7. 什么是序列化和反序列化
  8. 模板与泛型编程(二)
  9. [争什么! 掺在一起做撒尿牛丸啊! 笨蛋]ASP.NET Core 2.0 + EF6 + Linux +MySql混搭
  10. (9)Spring框架----AOP的HelloWorld
  11. linux 下tftp服务器搭建,CentOS 6下搭建TFTP服务器
  12. 2022-渗透测试-口令破解-几款暴力破解和字典生成的工具
  13. 电脑计算机配置应用程序兼容性,电脑怎么打开兼容模式怎么办
  14. SVN创建分支/合并分支/切换分支
  15. 【目标检测】YOLOv2 ,对YOLOv1的多种改进
  16. Bookmarks 各种技术 参考
  17. mysql 1436,Mysql Error Code : 1436 Thread stack overrun
  18. 什么是CSR以及CSR的作用和生成方法
  19. kill linux 苹果_Linux 下的KILL函数的用法
  20. english words

热门文章

  1. ML之kNNC:基于iris莺尾花数据集(PCA处理+三维散点图可视化)利用kNN算法实现分类预测daiding
  2. ML之分类预测之ElasticNet:利用ElasticNet回归对二分类数据集构建二分类器(DIY交叉验证+分类的两种度量PK)
  3. 第三次作业-介绍一款原型设计工具
  4. 《JAVA程序设计》_第四周学习总结
  5. Slim Span UVA - 1395
  6. 网络传输 中文乱码问题
  7. iOS-UIImageView的总结
  8. C# 线程知识--使用Task执行异步操作(转)
  9. Linux 环境下的抓包工具 - tcpdump
  10. I2C_ADDRS(addr, addrs...)理解