千家信息网

怎么增强Linux内核中的访问控制安全

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要为大家展示了"怎么增强Linux内核中的访问控制安全",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"怎么增强Linux内核中的访问控制安全"这篇
千家信息网最后更新 2026年11月02日怎么增强Linux内核中的访问控制安全

这篇文章主要为大家展示了"怎么增强Linux内核中的访问控制安全",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"怎么增强Linux内核中的访问控制安全"这篇文章吧。

Linux中常见的拦截过滤

  • 用户态动态库拦截。

  • 内核态系统调用拦截。

  • 堆栈式文件系统拦截。

  • inline hook拦截。

  • LSM(Linux Security Modules)

动态库劫持

Linux上的动态库劫持主要是基于LD_PRELOAD环境变量,这个环境变量的主要作用是改变动态库的加载顺序,让用户有选择的载入不同动态库中的相同函数。但是使用不当就会引起严重的安全问题,我们可以通过它在主程序和动态连接库中加载别的动态函数,这就给我们提供了一个机会,向别人的程序注入恶意的代码。

假设有以下用户名密码验证的函数:

#include  #include  #include  int main(int argc, char **argv) { char passwd[] = "password"; if (argc < 2) { printf("Invalid argc!\n"); return; } if (!strcmp(passwd, argv[1])) { printf("Correct Password!\n"); return; } printf("Invalid Password!\n"); }

我们再写一段hookStrcmp的程序,让这个比较永远正确。

#include  int strcmp(const char *s1, const char *s2) { /* 永远返回0,表示两个字符串相等 */ return 0; }

依次执行以下命令,就会使我们的hook程序先执行。

gcc -Wall -fPIC -shared -o hookStrcmp.so hookStrcmp.c export LD_PRELOAD="./hookStrcmp.so"

结果会发现,我们自己写的strcmp函数优先被调用了。这是一个最简单的劫持 ,但是如果劫持了类似于geteuid/getuid/getgid,让其返回0,就相当于暴露了root权限。所以为了安全起见,一般将LD_PRELOAD环境变量禁用掉。

Linux系统调用劫持

最近发现在4.4.0的内核中有513多个系统调用(很多都没用过),系统调用劫持的目的是改变系统中原有的系统调用,用我们自己的程序替换原有的系统调用。Linux内核中所有的系统调用都是放在一个叫做sys_call_table的内核数组中,数组的值就表示这个系统调用服务程序的入口地址。整个系统调用的流程如下:

当用户态发起一个系统调用时,会通过80软中断进入到syscall hander,进而进入全局的系统调用表sys_call_table去查找具体的系统调用,那么如果我们将这个数组中的地址改成我们自己的程序地址,就可以实现系统调用劫持。但是内核为了安全,对这种操作做了一些限制:

  • sys_call_table的符号没有导出,不能直接获取。

  • sys_call_table所在的内存页是只读属性的,无法直接进行修改。

对于以上两个问题,解决方案如下(方法不止一种):

  • 获取sys_call_table的地址 :

  • grep sys_call_table /boot/System.map-uname -r
  • 控制页表只读属性是由CR0寄存器的WP位控制的,只要将这个位清零就可以对只读页表进行修改。

/* make the page writable */ int make_rw(unsigned long address) { unsigned int level; pte_t *pte = lookup_address(address, &level);//查找虚拟地址所在的页表地址 pte->pte |= _PAGE_RW;//设置页表读写属性 return 0; }
/* make the page write protected */ int make_ro(unsigned long address) { unsigned int level; pte_t *pte = lookup_address(address, &level); pte->pte &= ~_PAGE_RW;//设置只读属性 return 0; }

1. 开始替换系统调用

本文实现的是对 ls这个命令对应的系统调用,系统调用号是__NR_getdents。

static int syscall_init_module(void) { orig_getdents = sys_call_table[__NR_getdents]; make_rw((unsigned long)sys_call_table); //修改页属性 sys_call_table[__NR_getdents] = (unsigned long *)hacked_getdents; //设置新的系统调用地址 make_ro((unsigned long)sys_call_table); return 0; }

2. 恢复原状

static void syscall_cleanup_module(void) { printk(KERN_ALERT "Module syscall unloaded.\n"); make_rw((unsigned long)sys_call_table); sys_call_table[__NR_getdents] = (unsigned long *)orig_getdents; make_ro((unsigned long)sys_call_table); }

使用Makefile编译,insmod插入内核模块后,再执行ls时,就会进入到我们的系统调用,我们可以在hook代码中删掉某些文件,ls就不会显示这些文件,但是这些文件还是存在的。

堆栈式文件系统

Linux通过vfs虚拟文件系统来统一抽象具体的磁盘文件系统,从上到下的IO栈形成了一个堆栈式。通过对内核源码的分析,以一次读操作为例,从上到下所执行的流程如下:

内核中采用了很多c语言形式的面向对象,也就是函数指针的形式,例如read是vfs提供用户的接口,具体底下调用的是ext2的read操作。我们只要实现VFS提供的各种接口,就可以实现一个堆栈式文件系统。Linux内核中已经集成了一些堆栈式文件系统,例如Ubuntu在安装时会提醒你是否需要加密home目录,其实就是一个堆栈式的加密文件系统(eCryptfs),原理如下:

实现了一个堆栈式文件系统,相当于所有的读写操作都会进入到我们的文件系统,可以拿到所有的数据,就可以进行做一些拦截过滤。

以下是我实现的一个最简单的堆栈式文件系统,实现了最简单的打开、读写文件,麻雀虽小但五脏俱全。

https://github.com/wangzhangjun/wzjfs

inline hook

我们知道内核中的函数不可能把所有功能都在这个函数中全部实现,它必定要调用它的下层函数。如果这个下层函数可以得到我们想要的过滤信息内容,就可以把下层函数在上层函数中的offset替换成新的函数的offset,这样上层函数调用下层函数时,就会跳到新的函数中,在新的函数中做过滤和劫持内容的工作。所以从原理上来说,inline hook可以想hook哪里就hook哪里。

inline hook 有两个重要的问题:

  • 如何定位hook点。

  • 如何注入hook函数入口。

1. 对于***个问题:

需要有一点的内核源码经验,比如说对于read操作,源码如下:

在这里当发起read系统调用后,就会进入到sys_read,在sys_read中会调用vfs_read函数,在vfs_read的参数中正好有我们需要过滤的信息,那么就可以把vfs_read当做一个hook点。

2. 对于第二个问题:

如何Hook?这里介绍两种方式:

  • ***种方式:直接进行二进制替换,将call指令的操作数替换为hook函数的地址。

  • 第二种方式:Linux内核提供的kprobes机制。

其原理是在hook点注入int 3(x86)的机器码,让cpu运行到这里的时候会触发sig_trap信号,然后将用户自定义的hook函数注入到sig_trap的回调函数中,达到触发hook函数的目的。这个其实也是调试器的原理。

LSM

LSM是Linux Secrity Module的简称,即linux安全模块。是一种通用的Linux安全框架,具有效率高,简单易用等特点。原理如下:

LSM在内核中做了以下工作:

  • 在特定的内核数据结构中加入安全域。

  • 在内核源代码中不同的关键点插入对安全钩子函数的调用。

  • 加入一个通用的安全系统调用。

  • 提供了函数允许内核模块注册为安全模块或者注销。

  • 将capabilities逻辑的大部分移植为一个可选的安全模块,具有可扩展性。

适用场景

对于以上几种Hook方式,有其不同的应用场景。

  • 动态库劫持不太完全,劫持的信息有可能满足不了我们的需求,还有可能别人在你之前劫持了,一旦禁用LD_PRELOAD就失效了。

  • 系统调用劫持,劫持的信息有可能满足不了我们的需求,例如不能获取struct file结构体,不能获取文件的绝对路径等。

  • 堆栈式文件系统,依赖于Mount,可能需要重启系统。

  • inline hook,灵活性高,随意Hook,即时生效无需重启,但是在不同内核版本之间通用性差,一旦某些函数发生了变化,Hook失效。

  • LSM,在早期的内核中,只能允许一个LSM内核模块加载,例如加载了SELinux,就不能加载其他的LSM模块,在***的内核版本中不存在这个问题。

以上是"怎么增强Linux内核中的访问控制安全"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

系统 函数 内核 文件 安全 堆栈 动态 地址 模块 程序 问题 控制 内容 原理 属性 用户 不同 信息 方式 两个 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网黑科技 喔噻互联网科技有限公司 壹账通互联网科技 互联网高科技股票 四个字互联网科技公司取名 无锡溥仪互联网科技有限公司 恒生科技互联网指数分析 互联网科技公司的市场部门 互联网汽车科技小镇 济南华为互联网科技产业总部基地 青岛科技大学互联网大赛研究生 阿大互联网科技有限公司 河南住房之家互联网科技 长沙茂晟互联网科技有限公司 山东大美朱楼互联网科技有限公司 互联网金融运营模式中的金融科技 张家口科技产业互联网平台 求路客互联网科技电话 广西泛欧互联网科技有限公司 绵阳真晨互联网科技有限公司 互联网与科技金融数据 金融科技 互联网金融 互联网 卓越科技 华中科技大学互联网 多迪互联网科技有限公司 新华互联网科技校企合作 科技大学互联网专业好不好 搜狐科技互联网 浙南科技城互联网大厦建设工程 安徽零酒互联网科技有限公司
0