Linux安全从内核做起
杨伟帅
随着网络技术的发展,计算机安全日益成为一个网络应用乃至全社会关注的一大问题。目前,Linux操作系统的安全级别较低,相应的安全增强软件也不丰富。通常,提到安全问题人们很容易想到防止黑客入侵,而很少考虑若系统已被入侵怎样使系统损失降低到最小,并使黑客无法安装后门,防止下一次入侵。系统入侵的手段是丰富多样的,而当前的Linux系统在安全方面的工作有许多不足之处,这种现状很有必要改进和完善。
一、不安全因素
现在,在GNU/Linux系统中不完善之处主要表现在以下几个方面。
1. 超级用户可能滥用权限。作为一个超级用户,它可以做任何事情,包括删除不该删除的系统文档、杀死系统进程以及改变权限等等。
2. 系统文档可以被任意地修改。在Linux系统中,有许多的重要文件,比如/bin/login,如果入侵者修改该文件,就可以轻易地再次登录。
3. 系统内核可以轻易插入模块。系统内核允许插入模块,使用户扩展Linux操作系统的功能,使Linux系统更加模块化,但这样做是十分危险的。模块插入内核后,就成为内核的一部分,可以做原来内核所能做的任何事情。
4. 进程不受保护。
二、开后门的14种办法
在一般的Unix计算机中做后门的方法,归纳起来可以分为以下14类。
1. 破解计算机账号密码。
2. .rhosts文件使特定用户从特定主机登录不需要密码。
3. 以具有跟源文件一样时戳的特洛伊木马程序版本来代替二进制程序。
4. 替换login程序,提供特殊口令隐身登录。
5. 替换Telnetd。
6. 替换网络服务。
7. Cronjob定时运行后门,入侵者每天在该时刻可以访问。
8. 替换共享函数库。
9. 替换内核。
10. 在文件系统中隐藏后门。
11. 在启动区内隐藏后门。
12. 隐藏进程。
13. IP数据包后门。
14. 在.forward文件中放置命令。
事实上,目前已知的后门基本上都不超出上述分类,分析以上各类后门可知,后门可以分为永久性后门和一次性后门。永久性后门是指系统重启后还能继续起作用的后门,一次性后门是指仅在本次运行时有效、重启后就无效的后门。要设置永久性后门,一定要对重要的文件进行改动,而一次性后门很可能是对重要进程进行改动。
三、阻截黑客入侵的良方
针对该论文提出的几大类设置黑客后门的方法,笔者又参考了LIDS系统的思想方法,提出了一种简单的增强系统安全、防止黑客入侵计算机的方法。主要思想是根据各种可能的设置后门的方法,堵截黑客后门,在最大程度上防止黑客入侵,以及在已经被入侵后最大程度上减少恶意破害的损失。
我们可以通过以下途径来提高系统的安全性。
1.保护重要的文件。保护某些重要的文件,使这些文件具有相应的功能。如使文件在某些情况下不能被删除,或者使某些文件不能被修改,即使是超级用户也不行。
2.保护重要的进程。保护某些进程,使之不能被删除,即使用户使用命令kill -9也是不行的。
3.对内核进行封装。保护内核,使用户不能对内核进行模块插入。
实现的关键就是限制系统管理员的权限,使其权限的使用处于保护之下,即使误操作或蓄意破环,也不至于对系统造成致命打击。
四、增强内核级安全
Linux内核级安全增强的具体做法是用加载模块的方法修改和安全有关的几个系统调用。对于文件保护,在被修改的系统调用或被调用时,先检查文件的保护类型,若没有保护或属于非保护类型,则返回原来的系统调用。反之,根据文件的保护类型和用户打开文件的模式来选择打开模式,或返回错误类型。例如,对于被列为只读保护的文件,如果用户以只读模式打开文件,则返回原来的系统调用;若对只读保护的文件试图以写的模式打开,则返回错误。对于进程保护,为了保护重要的进程,使之不能被删除,可以在进程的标记位上设置一个未被操作系统使用的标志位来保护重要的进程,并替换Kill调用,在真正执行Kill调用前先检查标志位,系统将拒绝用户删除设置保护位的进程。对内核进行加固后,应禁止插入或删除模块,从而保护系统的安全,否则入侵者将有可能再次对系统调用进行替换。我们可以通过替换create_module()和delete_module()来达到上述目的。另外,对这个内核进行加固模块时应尽早进行,以防系统调用已经被入侵者替换。
修改系统调用可以通过2种方法来实现。第1种是直接修改系统的核心代码,然后重新编译生成新的核心。该方法的缺点是:每做一次修改都需要对系统进行重新编译,这给新核心代码的调试带来了相当大的困难。若系统管理员需要针对不同用户进行相应的配置,重新编译的工作量是巨大的,而且编译过内核的人都知道,编译过程中有非常多的选项,要编译出一个性能优良的内核非常困难。第2种方法是将对系统的修改内容做成一个模块,通过静态或动态地加载和卸载,该模块会修改系统调用入口。应用模块技术,可以减小系统核心代码的规模,而且在需要时才装入模块可以减小系统所占用的硬件资源,从而提高系统的性能。模块的代码在装入核心后与核心中其他代码的地位是相同的,代码的调试就方便得多了。若管理员针对不同用户进行相应的配置,只需修改模块配置文件或在装载它时传递的参数。
Linux中的可加载模块是Linux内核支持的动态可加载模块,它们是核心的一部分,但是并没有编译到核心里面去。模块可以单独编译成为目标代码,它可以根据需要在系统启动后动态地加载到系统核心之中。超级用户可以通过insmod和rmmod命令将模块载入核心,或从核心中将模块卸载。若在调试新核心代码时,采用模块技术,用户不必每次修改后都需重新编译核心和启动系统。
下面是替换系统调用的例子。
int lksp_kill(pid_t pid, int sig) //替换的kill系统调用
{
struct task_struct *task;
if(!lksp_active) return (*original_kill)(pid, sig); /* 保护模块处于非激活状态,调用原有系统*/
if(sig == SIGKILL){
if((task = lksp_find_task(pid)) == NULL)
return -ESRCH;
if(task->flags & PF_PROTECTED)// 受保护,返回权限错误
return -EPERM;
}
return (*original_kill)(pid, sig);
}
如上所述,对于有一定经验的系统管理员来说,用模块替换系统调用的方法保护Linux系统简单易用,而且性能不错。大家不妨一试。
发布人:netbull 来自:计算机世界网