聊一聊chkrookit的误信和误用

chkrookit以及rkhunter基本上已经成为类unix系统的应急响应中的标配了。大多数处理安全事件基本上上机器的第一步都是来个两连发。但很多是以失望结束,或者出了结论又不知道如何是好。这篇文章或许能够解决你们的部分困惑。这篇文章主要是讲chkrootkit,rkhunter回头有空再吐槽。

首先对工具我们应该有一个明确的认识。工具是死的,人是活的,攻防本身就是人与人的对抗。挑战的对象是活生生的人而不是预定义好的程序时,机械的依靠某个工具,真正上战场了注定要悲剧。对于用于实际对抗中使用的工具,什么时间用,能够解决什么问题,对它的期望如何。我们心里应该很清楚,甚至我们有多大程度可以相信它的结论,欺骗或者bypass它的成本是什么样子也都需要了解。

言归正传,这篇文章我们先聊聊chkrootkit: http://www.chkrootkit.org。从README中我们了解到最近一次更新是:04/30/2014,而前一次更新是09年…看看CHANGELOG,大概也能够明白它都有哪些功能,代码目录的命名很好的反应出了这一点:

1

chkrootkit本身是一个shell脚本。运行 chkrootkit –l 可以看到所有的检测集。注意chkrootkit脚本这几个字的重点飘红。一般来说,这种开源脚本调用外部命令方式工作的安全检查程序,按照经验注定是悲剧的节奏(注意定语)。而且上机器后看都不看运行环境就执行这类检测程序极易被反补一刀[1][2]

打开chkrootkit我们一开始就看到这样两句SHELL

啧啧,检查范围让64位操作系统情何以堪啊

大体来说检测流程是什么样子吧:
1. 历史遗留rootkit/backdoor/蠕虫的默认检测;方式为根据位置、特殊的文件名、字符之类的来找文件,根据绑定的端口号来看是否有某个特定的后门(拜托…)。但这些查找特征赤裸裸的写在chkrootkit这个脚本里面的,绕过这类的检查的成本有多大,指望在实际对抗中,能查出什么样的东西,大家预期不要太高。
2. 后面进入checking阶段,有几个check点还比较有意思,但基本上都是靠外部的bin来实现的。但我们不要忘记了,这些bin运行的环境很有可能是恶意的哦。

这里不讨论从ring0上怎么躲避检查了,简单的一些open文件的redirect就能够bypass一堆,有兴趣的可以去phrack 97年的文章中看看思路[3]。靠ring3的开源程序去查ring0级别的未知后门本身出发点就有问题,这里注意是开源啊,再用ring0去bypass纯粹是欺负人啊:)。(当然对于实现不好的,只能被称作beta版的rootkit还是有可能,文件引用计数差异啊、没有相互配合好的cd和readdir调用啊之类的。但谁让你开源啊~啧啧。)
吐槽我还是限制后门在ring3下的实现吧。
Ldd看一下

2

这里以Linux为例,不传参数的情况下的make,产出的是一堆使用动态连接的bin,一个ld.so.preload就可以直接KO了。判定打开文件的读写对象,塞一个正常的给他即可。再看看有没其他更有意思的绕过方式。一个一个的来分析检测原理:
1. chkproc程序
a) chkproc函数完成了ps命令隐藏以及readdir函数隐藏的检测。
b) 检测逻辑:比对ps和readdir的输出以及通过遍历到MAX_PROCESSES(99999)的进程尝试chdir到每个目录/proc的结果来找出差异并报告(只有99999啊,啧啧),完全可以把pid拉起来啊 , 不过这样检查会导致报告一个OooPS错误

3

c) 实际使用经验来看,高并发的机器上,ps输出完毕后,再去读取/proc目录中的内容,时间窗口也会带来很大的误差
d) 对于利用ptrace等方法注入shellcode或者SO到其他进程的后门检查无效
e) 不隐藏的进程无效

2. chkdirs程序:
a) 接受要检查的目录,递归检查,通过比对父文件夹的link计数和子文件夹计数的差异来发现异常。正常情况下父目录的link计数应该是所有子项的数目+2
b) 在调用chkdirs这个命令的时主程序传递的参数为“/tmp /usr/share /usr/bin /usr/sbin /lib”大家记得别把隐藏文件放这些目录即可,这是在逗我么…
c) 不隐藏的文件无效

3. chklastlog、chkutmp chkwtmp
a) 本质上这几个程序都是在对utmp wtmp之类的文件做交叉比对,有些工具会检查某些特殊的字段,比如time是否为0。此类的检查工具的检查思路更多的是来自对外界广泛流传的日志擦除工具的了解。
b) 程序实现时有硬编码的略过账户在里面,可以直接将产生的log主体改成它可以绕过检查
c) 不要轻易的将日志的字段完全清0,甚至在某些程度上,你可以从其他的entry copy一个过来

4. ifpromisc程序
a) 枚举系统上处于混杂模式的接口以及PF_PACKET链路层套接字的程序来查找嗅探器
b) 建议采用so hijack的方式进行隐藏

看到现在,应该大概对chkrootkit 的定位和功能有效性有所感觉了:

● 首先,基本的、初级的入侵行为,比如uid=0,权限异常,文件系统的文件替换和新增、删除,这还得你自己查。甚至当前可列的进程端口,你还是要自己去看的。Chkrootkit充其量是辅助,或者辅助的辅助。
● 没有自作(第一声)的程序是查不出来的,你堂而皇之的拿crontab起一个回连后门,它根本吱都不会吱一声。稍微复杂一些的它也查不出来,比如so注入等后门。Chkrootkit只能帮你做很有限的一些入侵特征检查,而且这种检查是经验性的,是建立在对攻击者尿性的揣摩基础上。
● 由于是开源,检测逻辑很好绕,而且存在很多方式方法。攻击者换个姿势,就瞎了,几乎可以肯定定制化的 rootkit根本查不出来。
● chkrootkit的后门/rootkit检测对抗工作思路还很朴素。别指望能有啥重大发现了。

清楚了一个安全检测工具的工作原理和局限性、公开了check 点,在一个“通用”的操作系统上对抗,攻击者以有心算无意总能有收获。通用系统的坑或者特性太多了,拿启动位置来说,随随便便能列一堆之前听都没听过的地方,恶意程序利用这些点,都能带起来。

假使应急响应中需要使用这类通过研究攻击者尿性开发的有针对性的工具,还是老老实实的private吧,这类东西属于出奇制胜、见光死。

多关注关注CVE,呵呵,你的检查运行程序,别成了人家本地提权的途径了。说不定人家造成大的动静就等着你来chkrootkit呢!

最后,以一个吐槽结束,应急响应最重要的目标在实际操作中太容易被忽视。弄清怎么进来的,进来后做了啥,造成了哪些损害。咱不是要和攻击者玩躲猫猫,你来藏我来找。事情结了后,能重装就重装吧,别折腾清理什么后门了。保不齐就被就被你没留意的一个小细节或者不知道的一个特性给坑了。Focus目标, 勿忘初心。

[via@Xiao士奇]