Abstract
虽然Open Source思想让Linux拥有了坚不可摧的代码,但后门也许就存在于不小心的一次鼠标点击,不管你是否相信,但安全问题影响到你的每一天。
白帽和黑帽如同一对形影不离的智者,他们通过互相提出古怪的难题来刁难对方从而获得精神层次的乐趣,而旁观者虽然看得清,但却感受不到对决时那种刺激的快感,那么本文将尽全身之力以故事为载体为读者模拟出一场扣人心弦的黑客之战。
第一章 初 探
小黑是一名黑客高手并能够熟练使用各种黑客工具,最吸引他的是机房网管小白那台私人服务器里面那些珍贵的数据和最高ROOT权限。
小白是一名彻头彻尾的白帽,平时着迷于研究安全运维技术,最珍贵的就是自己那台私人服务器,誓死保卫不让其他人使用。
那台诱人的服务器每天在小黑的脑子中飘荡,最终忍不住了,走到了小白办公室以不能从服务器共享文件夹中复制文件为由让网管小白检查检查服务器,看看是不是出现了什么问题。
小白随即来到了小黑办公室,试了试下载共享文件确实不能用了,于是远程登陆服务器查看究竟,发现也不能登陆。。。最终发现是电脑网线没插。
其实小黑背地里将自己笔记本安装了键盘记录器,赶紧打开查看成果,如图:
虽然被数落了几句电脑白痴,但已经完全不往心里去了,但大喜过后是诅丧,竟然是一个低权限普通帐号,看来网管小白的安全专家称号也不是浪得虚名,管 理服务器竟然那么小心,日常也不用root登陆,唉,不过好在上学时间里通过机房的堡垒试验机学习过怎么在Linux下提权,因为过程稍微复杂并且不是文 章的重点所以省略,但已做视频教程,详见感谢页的。
经过前面的故事,终于终于要开始本文最核心的技术点——RootKits,接下来的一章我将继续会以故事为载体将理论和实战结合在一起论述并加以分析
既然小黑已经拿到了管理员的权限,下一步就是让自己能够长期的使用这台服务器,于是想到了Rootkits工具集。
Rootkits是linux/unix获取root权限之后使得攻击者可以隐藏自己的踪迹和保留root访问权限的神器,通常攻击者使用 rootkit的检查系统查看是否有其他的用户登录,如果只有自己,攻击者就开始着手清理日志中的有关信息,通过rootkit的嗅探器还可以获得其他系 统的用户和密码!
目前常用的有:t0rn /mafix/enyelkm 等等。
Rootkits通常分为:应用级别—内核级别—-硬件级别,早期的是rootkit主要为应用级rootkit通过替换login、ps、ls、 netstat等系统工具或修改.rhosts等系统配置文件等实现隐藏后门,硬件级RootKits主要是指Bios Rootkits,能够在系统加载前获得控制权,通过向磁盘中写入文件,再由引导程序加载该文件重新获得控制权也可以采用虚拟机技术,使整个操作系统运行 在rootkit掌握之中,目前常见的rootkit是内核级rootkit,通过直接修改内核来添加隐藏代码实现控制系统的功能。
最为简单实用的应用级别Rootkit是通过将添加过提权代码的命令替换系统中原始的命令来实现功能的,并且一般提供清理工具删除wtmp、 utmp、lastlog等日志文件中自己的行踪,并且复杂点的rootkit还可以向攻击者提供telnel、shell和finger等服务
Mafix是一款常用的轻量应用级别Rootkits,是通过伪造ssh协议漏洞实现让攻击者远程登陆的,特点是配置简单并可以自定义验证密码和端口号。
小黑此时已经压抑不住内心的激动心情,赶紧下载Mafix,解压如图:
查看帮助文件后开始安装,格式为:.root 密码 端口,如下图:
因为还考虑到以后都要远程访问,所以再加上一条给防火墙的命令,让小黑可以自由的穿行于服务器之间。
这时在小黑本机打开Putty,输入:ssh 192.168.10.30 12345,进行连接.(图)
并且现在的登陆帐号已经变成了root.
那么我来简单分析下Mafix是如何实现功能的,先看压缩包中的代码(如果全贴上。。估计就要8000字了,所以我就简单找一段吧):
1
2
3
4
5
6
7
8
9
|
# dir … //注释.此段为对dir命令的操作
If [ -f /usr/bin/dir ]; then //判断/usr/bin/dir命令是否存在,若存在则
chattr -isa /usr/bin/dir //将命令的附加权限去掉
cp/usr/bin/dir $BACKUP //将命里复制到$BACKUP目录中
mv -f dir /usr/bin/dir 2>/dev/null
//将压缩包中的”dir命令”,并不显示过程给用户
chattr +isa /usr/bin/dir
//添加附加权限.不允许再做修改
Fi //结束
|
那么此时已经很清楚了,其实Mafix就是很典型的应用级Rootkit,是批量替换系统命令来实现的,但因为要替换大量系统命令所以需要root用户才可以使用。
1
2
3
4
5
6
7
8
9
10
11
|
iftest -n “$1″ ; then //如果设置了密码
echo“${CYN}mafix!${DMAG} > ${CYN} Password:${DMAG} $1${RES}”//则按照此格式输出
cd$BASEDIR/bin
echo-n $1|md5sum > /etc/sh.conf //生成密码文件
else
echo“${CYN}mafix!${DMAG} > ${CYN} Password:${DMAG} $DEFPASS${RES}”
echo-n $DEFPASS|md5sum > /etc/sh.conf //使用md5加密并写入文件
fi
touch-acmr /bin/ls /etc/sh.conf
chown-f root:root /etc/sh.conf
chattr+isa /etc/sh.conf //写保护
|
上面的代码是按照用户的需求设置了监听密码,从中也可以得知密码是经过md5加密的,并保存在/etc/sh.conf且进行了写保护操作,如下图。
这几天网管小白总是接到投诉说服务器登陆不上去,上传下载文件速度也非常慢,因为外网流量突然飙升,大量数据流入机房,其实小白也有察觉,仔细检查 History记录发现出现了很多wget命令,点进去一看竟然是用公司的服务器下载黑客教程,肯定是小黑搞的!那找他算账之前,得先把后门给补上。
Rkhunter的中文名叫“Rootkit猎手”, 目前可以发现大多数已知的rootkits和一些嗅探器以及后门程序. 它通过执行一系列的测试脚本来确认服务器是否已经感染rootkits. 比如检查rootkits使用的基本文件, 可执行二进制文件的错误文件权限, 检测内核模块等等。
小白首先从网络上下载到Rkhunter,然后解压,如下图
进入解压后的目录,执行.installer.sh–install 自动化安装,如下图:
安装后就可以使用rkhunter命令了,下面列出有用的参数:
1
2
3
4
|
–checkall (-c) :全系统检测,rkhunter 的所有检测项目
–createlogfile :建立登录档,一般预设放在/var/log/rkhunter.log
–skip-keypress :忽略按键后继续的举动(程序会持续自动执行)
–versioncheck :检测试否有新的版本在服务器上
|
接下来运行rkhunter –checkall,连续敲击回车,数分钟后得到报表,如图:
从报表中可以看出,出现了很多可疑文件并且列出了rootkit的类型。
Rkhunter拥有并维护着一个包含rootkit特征的数据库,然后它根据此数据库来检测系统中的rootkits,所以可以对此数据库进行升级,rkhunter–update
Rkhunter在进行检查时同时把相应的信息写到了日志中,并提示了其位置是:/var/log/rkhunter/rkhunter.log
那么简单来讲,RKhunter就像我们的杀毒软件,有着自己的病毒数据库,对每一个重点命令进行比对,当发现了可疑代码则会提示用户。
当然如果只是用Rkhunter检查扫描还是不够权威,再来安装一款检查下吧,chkrootkit 是一款小巧易用的Unix平台上的可以检测多种rootkit入侵的工具。它的功能包括检测文件修改、utmp/wtmp/last日志修改、界面欺骗 (promiscuous interfaces)、恶意核心模块(maliciouskernel modules)。
小白先从网络上下载到chkrootkit资源包,在服务器中解压,如下图:
接下来使用命令make sense 来安装软件,如下图:
运行命令
1
|
./chkconfig | grep INFECTED
|
搜索被感染的文件,如下图:
1
2
3
4
5
6
|
### workaround for some Bourne shell implementations
unalias login > /dev/null 2>&1
unalias ls > /dev/null 2>&1
unalias netstat > /dev/null 2>&1
unalias ps > /dev/null 2>&1
unaliasdirname > /dev/null 2>&1
|
1
|
上面的代码是将系统中已存在的别名命令取消,防止已经被篡改使得检测结果不准确。
|
1
2
3
4
5
6
7
8
|
# Native commands
TROJAN=“amd basename biff chfn chsh cron date du dirname echo egrepenv find /
fingerd gpm grep hdparm su ifconfig inetd inetdconf identd init killall /
ldsopreload login ls lsof mail mingetty netstat named passwd pidof pop2pop3 /
ps pstree rpcinfo rlogind rshd slogin sendmail sshd syslogd tar tcpd /
tcpdump top telnetd timed traceroute vdir w write”
# Tools
TOOLS=“aliens asp bindshell lkm rexedcs sniffer w55808 wted scalperslapper z2 chkutmp”
|
上面的代码中则是定义了需要检查的命令和工具,用户则也可以自行添加。
通过上面两款工具的检查,网管小白已经确信了服务器被入侵的事实,但已经考虑到核心级rootkits是使用了LKM技术,而且系统中已经有大量的数据被修改且一般的木马后门隐蔽性毕竟高,为了保险起见还是要重新做系统。
1
|
将服务器的网络线及时拔除(必要时报告部门经理)。
|
1
|
备份重要资料数据,并多份保存防治丢失。
|
1
|
使用防火墙屏蔽不需要开放的一切端口。
|
文中使用的工具mafix是应用级别的rootkit,那么再来补充核心级rootkit的LKM隐藏技术吧,木马最大的特性就是隐蔽性,不能轻易 让人察觉,所以隐藏木马相关信息是关键的因素。对于Linux操作系统来说,主要有静态隐藏和动态隐藏两个标准。 静态隐藏是指木马文件的隐藏,用“ls”命令看不见我们的木马服务端程序。动态隐藏是指当木马运行时,进程和通讯端口的隐藏,如用“ps –A”命令不能找到木马进程,用“netstat -at”命令不会显示木马端口的通讯情况等。 由于Linux本身的安全性,想利用外壳程序隐藏木马文件和进程不可能实现,所以就借要通过修改Linux内核的系统调用来隐藏木马相关信息,这就是 LKM技术。 LKM就是可装载内核模块(Loadable Kernel Modules)。这些模块本来是Linux系统用于扩展其功能的。 当LKM被载入内核,就能修改内核变量,重载内核函数,轻易得实现扩充或裁减操作系统内核的某些功能。同时动态的载入模块还意味着能留给用户程序更多的内 存。由于这些优点,他们常常被特殊的设备或者文件系统(例如声卡、打印机等)使用。 对于众多的系统调用,不需要全部劫持,只需要劫持系统管理员用于查看文件、进程、网络连接等命令用到的关键系统调用即可。下面分析LKM后门在设计时主要 截获哪些关键的系统调用。 在用户空间执行每个命令都是调用内核的某些系统调用完成。比如用“ls”这个命令来查看当前目录信息,就会调用open()、 gendents64()、write()等系统调用。如果能截获write()这个调用,修改它的输出,那么现在的输出信息就不是真正的系统信息。 LKM技术最大的特点就是截获并修改多个系统调用,从而改变整个系统响应。看一个截获write()系统调用的例子。 netstat命令用于查看网络连接状况,显示命令结果会用到write()系统调用。在截获前,命令netstat –at的输出为:
从输出中看出本机IP为“192.168.0.253”,另一个IP为“192.168.0.42”的用户通过telnet连接到了本机。现在利用 一个LKM来截获write()系统调用,目的是把含有“192.168.0.42”这个字符串的信息屏蔽掉,从而实现隐藏网络连接的功能。关键代码如 下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int new_write( unsigned int fd, char *buf, unsigned int count )
{
char *k_buf;
char *hideinfo=”192.168.0.42”; //想隐藏的信息
k_buf=(char*)kmalloc(256,GFP_KERNEL);
memset(k_buf,0,256);
copy_from_user(k_buf,buf,255)
if(strstr(k_buf,hideinfo))
{
kfree(k_buf);
return count;
}
kfree(k_buf);
return real_write(fd,buf,count);
}
|
加载这个LKM后,write()系统调用就被换成了new_write():判断输出中是否含有“192.168.0.42”这个字符串,如果有,什么都不做,否则返回真正的write()调用。现在再来看命令netstat –at的输出(如下图):
加载LKM后netstat命令输出
成功隐藏!再查看/etc/log的登录记录,从“192.168.0.42”远程登录的记录也没了。
这就是LKM后门截获系统调用的威力。现在无论管理员用哪个命令,只要这个命令会用到write()系统调用,就不会显示含有“192.168.0.42”这个字符串的信息。这样既能隐藏当前的网络连接,又能擦除曾经登录而留在系统日志里的痕迹。
所以在Adore rootkit等后门中都实现了对write()系统调用的截获,隐藏hacker的足迹。当然也可以用别的方式来修改这个输出,比如说把“192.168.0.42”改成“255.255.255.0”等任何你想修改成的IP地址来蒙骗管理员。
安全加固方案
Linux在结构分为两层,即内核与核外程序。
rootkits要从核外程序发起对Linux内核的攻击和破坏,从机制上来说是不可能的。它唯一可利用的就是LKM方法。因此,Linux后门工具检测器必须严守这道防线,保护系统内核不被攻击和篡改。
那么下面的检测代码会提供两种保护内核方式。
第一种方式可称作“单模块内核”方式,即系统在启动之后不允许任何人加载程序模块到内核中。这种办法虽然保证了内核的绝对安全,但同时对系统功能的扩充和开发也带来了不便。这种“单模块内核”方式适用于不准备进行任何系统扩充和开发的应用场合。
第二种方式可称作“带安全检测的LKM”方式,这种方式适用于进行软件研发工作的应用环境。具体步骤是当系统启动完毕之后,首先为系统加载LKM检测器,由它来负责管理、监控随后所有的LKM活动。
要加载一个模块,必须使用命令insmod ,利用strace 命令会发现它用到了create_module( )这个系统调用,如果能截获create_module( )系统调用,那么任何LKM的加载都将受到控制。
对于“单模块内核”方式只要将create_module()修改成空函数就可以了。而对于“带安全检测的LKM”方式则要做一定的修改。
检测器的模块检测机制:记录每一个新加载的模块
利用LKM记录每一个新加载模块的名字。在调试LKM时有这样的经验:
文件/proc/kmsg记录了所有内核模块的printk( )输出。可以这样考虑:截获create_module( )系统调用,让它在加载每个LKM后将模块的名字记录在文件/root/log_lkm。那么内核模块的一举一动都在系统管理员的监视之下。
下面是截获这个系统调用的关键代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
int new_create_module( char *name, unsigned long size )
{
char *k_buf;
int ret =orig_create_module( name, size );
k_buf = (char*) kmalloc(256, GFP_KERNEL );
copy_from_user(k_buf, name, 255);
open = sys_call_table[ SYS_open ];
write = sys_call_table[ SYS_write ];
close = sys_call_table[ SYS_close ];
int fd;
char filename[ ] = “/root/log_lkm”;
mm_segment_told_fs_value = get_fs( );
set_fs( get_ds( ));
fd = open(filename, 0100 | 02 | 02000 , 0640);
write(fd, k_buf,sizeof(k_buf) );
close( fd );
set_fs( old_fs_value );
return ret;
}
|
现在往内核里加载任意一个LKM,在/root/log_lkm里都记录下这个模块的名字。
这样,系统管理员只需关注/root/log_lkm,就可以发现并删除任何非法的LKM。之所以不直接输出到/proc/kmsg中,是因为凭借 网络小白对小黑的了解,知道如果他使用了核心级的rootkit那么必然也能通过查看/proc/kmsg发现自己是否留下足迹,如果有记录则会通过别的 方法擦除这个记录,毕竟小黑现在也有系统的最高权限。
检测器的系统调用检测机制:记录系统调用地址改变
LKM后门工具的实现均是通过修改系统调用,这必然导致系统调用地址的改变,通过检测这些地址的改变情况,就能判断系统是否被加载了LKM后门。
检测前先将未修改时的地址保存起来(不妨就保存在log_lkm中),然后利用另一个LKM来记录现在所有系统调用的地址,为了对比方便,把现在的系统调用地址存在/root目录下的另一个文件log_syscall里,记录现在系统调用地址的LKM关键代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
int init_module( void )
{
open = sys_call_table[ SYS_open ];
write = sys_call_table[ SYS_write ];
close = sys_call_table[ SYS_close ];
int j, fd;
char filename[ ] = “/root/log_syscall”;
char addr[9];
mm_segment_t old_fs_value = get_fs( ) ;
set_fs( get_ds( ));
fd = open( filename, 0100 | 02 | 02000 , 0640);
for ( j = 0; j < 240; j ++ )
{
sprintf(addr,”%x/n”,sys_call_table[j]);
write(fd, addr, sizeof(addr)) ;
}
close( fd );
set_fs( old_fs_value );
return 0;
}
|
将这两个LKM加载到内核后,在log_lkm里记录了前240个系统调用最初的地址和后来加载的模块名字,在log_syscall里记录了现在的系统调用的地址。通过对比,如果某些系统调用的地址发生改变,那么毫无疑问,系统已经被攻击者(小黑)加载了LKM后门。
系统管理员现在应该分析文件log_lkm里新加载模块记录,找到是哪个LKM引起了系统调用地址的改变,从而确定出LKM后门模块。
需要指出的是,LKM后门工具往往只修改几个关键的系统调用。因此这个LKM可以简化为只检测几个重要系统调用的地址改变情况。
这些重要的系统调用是:getdents64( )、kill( )、read( )、write( )、fork()、clone( )、execve( )、getuid( )、query_module( )。
检测器的隐藏机制
为了让这个检测器更安全、有效的运行,还必须将它隐藏起来,即隐藏模块本身和文件log_lkm,log_syscall。
为了让检测器始终在内核中运行,不会因为系统重启而被“踢出”内核,管理员必须把载入这个检测器的行为放到系统的启动序列中。简单的方法就是在/etc/rc.local中加入一行:insmod LKM.o,来实现每次系统启动都会加载这个LKM检测器。
如果只是一篇枯燥的论文,那也就是从网络上复制点技术文章粘进来凑凑字数,所以本文以一个被入侵的故事为载体,入侵者小黑使用mafix工具入侵服务器,而网管小白则使用了两款工具:rkhunter以及chkrootkit
[via@freebuf]
Copyright © hongdaChiaki. All Rights Reserved. 鸿大千秋 版权所有
联系方式:
地址: 深圳市南山区招商街道沿山社区沿山路43号创业壹号大楼A栋107室
邮箱:service@hongdaqianqiu.com
备案号:粤ICP备15078875号