当前位置: 首页 > 科技观察

如何在Linux内核中增强访问控制安全_0

时间:2023-03-15 00:52:43 科技观察

背景前段时间,我们项目组在帮助客户解决一些操作系统安全问题,涉及到windows、Linux、macOS三大操作系统平台。不管是什么操作系统,本质上都是一个软件。任何软件在设计之初,都不能完全满足人们的需求,操作系统也是如此。为了尽可能满足人们的需求,它不得不提供一些机制供人们定制操作系统。当然,除了政府提供的一些机制外,还有一些黑魔法,不建议使用,但有时可以作为具体业务场景的参考。Linux中常见的拦截与过滤本文重点介绍Linux平台上的常见拦截:用户态动态库拦截。内核模式系统调用拦截。堆叠式文件系统拦截。内联钩子拦截。LSM(LinuxSecurityModules)动态库劫持Linux上的动态库劫持主要是基于LD_PRELOAD环境变量。这个环境变量的主要作用是改变动态库的加载顺序,让用户有选择地加载不同动态库中的相同功能。.但使用不当会造成严重的安全问题。我们可以利用它来加载主程序和动态链接库中的其他动态函数,这就为我们提供了向他人程序中注入恶意代码的可乘之机。假设用户名密码认证有如下函数:#include#include#includeintmain(intargc,char**argv){charpasswd[]="password";if(argc<2){printf("Invalidargc!\n");return;}if(!strcmp(passwd,argv[1])){printf("CorrectPassword!\n");return;}printf("InvalidPassword!\n");}让我们编写另一个hookStrcmp程序来使这种比较始终正确。#includeintstrcmp(constchar*s1,constchar*s2){/*永远返回0,表示两个字符串相等*/return0;}一条一条执行下面的命令,我们的hook程序就会先执行。gcc-Wall-fPIC-shared-ohookStrcmp.sohookStrcmp.cexportLD_PRELOAD="./hookStrcmp.so"结果我们会发现先调用了自己写的strcmp函数。这是最简单的劫持,但是如果你劫持类似geteuid/getuid/getgid之类的东西,让它返回0,就相当于暴露了root权限。所以为了安全起见,LD_PRELOAD环境变量一般是禁用的。Linux系统调用劫持最近发现在4.4.0内核中有超过513个系统调用(其中很多从未被使用过)。系统调用劫持的目的是改变系统中原有的系统调用,将原有的系统调用替换为我们自己的程序。系统调用。Linux内核中所有的系统调用都放在一个名为sys_call_table的内核数组中,数组的值代表系统调用服务程序的入口地址。整个系统调用流程如下:当在用户态发起系统调用时,会通过80软中断进入syscallhander,然后进入全局系统调用表sys_call_table查找具体的系统调用,那么如果我们把这个数组中的地址改成我们自己的程序地址就可以实现系统调用劫持。但是为了安全起见,内核对这个操作做了一些限制:sys_call_table的符号是不导出的,不能直接获取。sys_call_table所在的内存页是只读的,不能直接修改。针对以上两个问题,解决方法如下(方法不止一种):获取sys_call_table的地址:grepsys_call_table/boot/System.map-uname-r控制页表的只读属性由WP控制CR0寄存器的位,只要将该位清零即可修改只读页表。/*makethepagewritable*/intmake_rw(unsignedlongaddress){unsignedintlevel;pte_t*pte=lookup_address(address,&level);//查找虚拟地址所在的页表地址pte->pte|=_PAGE_RW;//设置页表读写属性return0;}/*makethepagewriteprotected*/intmake_ro(unsignedlongaddress){unsignedintlevel;pte_t*pte=lookup_address(address,&level);pte->pte&=~_PAGE_RW;//设置只读属性return0;}1.开始替换本文实现的系统调用是ls命令对应的系统调用,系统调用号为__NR_getdents。staticintsyscall_init_module(void){orig_getdents=sys_call_table[__NR_getdents];make_rw((unsignedlong)sys_call_table);//修改页面属性sys_call_table[__NR_getdents]=(unsignedlong*)hacked_getdents;//设置新的系统调用表地址make_ro((unsignedlong)sys_call_);返回0;}2。恢复staticvoidsyscall_cleanup_module(void){printk(KERN_ALERT"Modulesyscallunloaded.\n");make_rw((unsignedlong)sys_call_table);sys_call_table[__NR_getdents]=(unsignedlong*)orig_getdents;make_ro((unsigned_long));}使用Makefile编译,在内核模块中插入insmod,然后执行ls,就会进入我们的系统调用,我们可以在hook代码中删除一些文件,ls不会显示这些文件,但是这些文件还是存在的。堆栈文件系统Linux使用vfs虚拟文件系统对具体的磁盘文件系统进行统一抽象,IO堆栈自上而下形成一个堆栈。通过对内核源码的分析,以一个读操作为例,自上而下执行的过程如下:内核采用了很多C语言面向对象的形式,即函数指针的形式。比如read是vfs提供给用户的。下面调用接口,具体是ext2的读操作。我们只要实现VFS提供的各种接口,就可以实现一个堆叠式文件系统。一些堆栈文件系统已经集成在Linux内核中。例如,Ubuntu会在安装过程中提醒你是否需要对主目录进行加密。实际上,它是一个堆栈式加密文件系统(eCryptfs)。原理如下:实现了一个堆叠式文件系统。相当于所有的读写操作都会进入到我们的文件系统中,所有的数据都可以拿到,可以做一些拦截和过滤。下面是我实现的最简单的堆栈文件系统,实现了最简单的文件打开、读写。麻雀虽小,五脏俱全。https://github.com/wangzhangjun/wzjfsinlinehook我们知道,内核中的一个函数不可能实现这个函数中的所有功能,它必须调用它的下层函数。如果这个下层函数能够得到我们想要的过滤后的信息内容,我们就可以用新函数的偏移量替换下层函数在上层函数中的偏移量,这样当上层函数调用下层函数,它会跳转到新函数。在一个新的函数中做过滤和劫持内容的工作。所以原则上,inlinehook想钩哪里就钩哪里。inlinehook有两个重要的问题:如何定位hook点。如何注入钩子函数入口。1、对于第一个问题:需要有一定的内核源码经验。例如对于read操作,源码如下:这里发起read系统调用时,会进入sys_read,在sys_read中会调用vfs_read函数。vfs_read的参数恰好有我们需要过滤的信息,所以vfs_read可以看作是一个hook点。2.对于第二个问题:如何挂钩?这里有两种方法:第一种方法:直接进行二进制替换,将调用指令的操作数替换为钩子函数的地址。第二种方式:Linux内核提供的kprobes机制。原理是在hook点注入int3(x86)机器码,这样CPU运行到这里就会触发sig_trap信号,然后在sig_trap的回调函数中注入用户自定义的hook函数,达到目的触发钩子函数。这其实就是调试器的原理。LSMLSM是LinuxSecurityModule的缩写,即linux安全模块。它是一个通用的Linux安全框架,具有高效、易用等特点。其原理如下:LSM在内核中做了以下工作:为特定的内核数据结构添加安全域。在内核源代码的不同关键点插入对安全挂钩函数的调用。添加了通用安全系统调用。提供的功能允许将内核模块注册为安全模块或取消注册。大多数功能逻辑被移植到具有可扩展性的可选安全模块中。适用场景以上hook方法有不同的应用场景。动态库的劫持还没有完成。被劫持的信息可能不符合我们的需求,也可能在您之前被其他人劫持。一旦禁用LD_PRELOAD,它将失效。系统调用劫持,劫持的信息可能不符合我们的需求,比如获取不到structfile结构,获取不到文件的绝对路径等。堆栈文件系统依赖Mount,可能需要重启系统。inlinehook,灵活性高,随机hook,无需重启立即生效,但不同内核版本之间的通用性差,一旦部分函数发生变化,hook就失效了。LSM,在早期的内核中,只能允许加载一个LSM内核模块。比如加载了SELinux,就无法加载其他LSM模块。最新内核版本不存在该问题。摘要篇幅有限。本文只介绍Linux上的拦截技术。以后有机会再讨论windows和macOS上的拦截技术。其实类似的审计HOOK在任何系统都是刚需的,不仅仅是内核,我们可以看到越来越多的vm和runtime,甚至很多web组件和前端应用都提供了更灵活的hook方法。是透明和实时两种安全趋势下最常见的解决方案。【本文为专栏作者“ThoughtWorks”原创稿件,微信公众号:Thinkworker,转载请联系原作者】点此查看该作者更多好文