搜公众号
推荐 原创 视频 Java开发 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库
Lambda在线 > Linux安全之进程篇

Linux安全之进程篇

2019-02-10
举报

 Linux安全系列是一套完整的检查linux系统是否被入侵,后门排查,木马清除,黑客溯源,以及恢复攻击路径的方法介绍。

由于是第一篇,在说主题前面先简单介绍一下目前linux木马的现状,目前主流的linux木马都不是内核级的,因为内核木马很难满足各个发行版的兼容性要求且需要root权限,所以几乎都是用户层的。从功能上看,基本都是实现一个挖矿功能和一个反弹rootshell功能。rootshell的触发机制,使用定时反弹固定iPPing触发,也有更底层的任意端口触发和无端口触发(netfilter prerouting)


  它们最显著的三个共同特点:

1、运行后删除自身,只驻扎在内存中

有时使用lsof|grep deleted会有惊喜哦,如图:

 2、运行后改名,且大多数木马改为内核形态的进程命名方式即[xxx],用以迷惑视线

3、修改/etc/ld.so.preload或环境变量进行动态链接库劫持,达到隐藏进程和端口的目的

cat /etc/ld.so.preload或使用ldd/bin/ps命令,可以看到异常,如图:

Linux安全之进程篇

我们进入正题说下进程:

  1. Linux下有3个特殊的进程,idle进程(PID = 0),     init进程(PID = 1)kthreadd(PID =     2)

  2. idle进程,linux的第一个进程

  3. /sbin/init进程由idle通过kernel_thread创建,是所有用户进程的父进程或祖先

  4. [kthreadd]进程由idle通过kernel_thread创建,是所有内核进程的父进程

Linux安全之进程篇

举个例子了解一下:

首先,内核进程的命名规则都是[xxx],用中括号括起来的,而用户层的进程正常情况下不会这样,那么,如果一个[xxx]形式的进程他的父进程是1(也就是/sbin/init),那是不是有问题?因为带中括号的进程的父进程正常情况下应该是2(也就是[kthreadd]),如图:

Linux安全之进程篇

这是一个针对改名的例子,改名代码很简单,所以利用广泛

strncpy(argv[0],FAKE_NAME, strlen(argv[0]));

就能实现,有兴趣的可以自行测试做实验

 

那么如果后门没有改成[xxx]形式又如何发现呢?

我们来观察几条能得到进程名字的命令,看看哪些得到的是真名,哪些是假名:

ps -ef

Linux安全之进程篇

cmdline

Linux安全之进程篇

pstree

Linux安全之进程篇

ls -l/proc/pid/exe

Linux安全之进程篇

可以看到前两个得到的名字是一样的为[locked],后两个得到的名字也是一样的为rootkit

前面两为假名,后面两为真名

那么未改名前的名字(即真实名字)就可以通过后面这两种方式查出来

我们也可以把它写成脚本来进行全部循环比较,知识星球里给出了脚本下载。

 

进程隐藏:

进程的隐藏可以在不同的层面实现

用户层---系统调用层---内核层---文件系统层

 

常用的隐藏方法如下:

  1. 替换ELF文件

  2. 劫持LD_LIBRARY_PATH

  3. 劫持syscall_table

  4. 篡改syscall_table劫持系统调用

  5. Inlinehook     系统调用

  6. VFS层劫持

  7. kprobe

  8. 感染系统关键内核模块

 

对于ELF文件被替换,我们可以使用

rpm -Vf/bin/ps    来校验

S 大小  5 MD5  T为时间 M为属性

如果执行命令后出现S等字样,就说明被改变了,如果S5同时改变,那么就是有问题的,ps命令将变得不可信

Linux安全之进程篇

上图,可以看到SM5T全部改变了

关于 LD_LIBRARY_PATH的劫持,劫持的方法有两种,环境变量和 /etc/ld.so.preload

如何发现?我们使用file /bin/ps观察如下:

Linux安全之进程篇

证实ps命令它是动态编译的,使用了系统的共享库,如果此时动态链接被劫持,那么运行该程序的时候也会把后门程序劫持后的共享库加载进去(类似windows下的LPK劫持),通常实现一些隐藏的目的

 

使用 ldd /bin/ps 命令可发现异常

Linux安全之进程篇

正常应该全部为/lib 或者 /lib64下的系统动态链接库

如果最后一行(也有可能不是最后一行)是其他的so文件,那么就要考虑是否动态库被劫持了

进一步确认的话,可以跟干净的系统进行比较或者使用gdb调试,简单点也可以使用strings静态查看关键字符


对于上述两种应用层隐藏的方式,我们的反制方法:

当发现PS命令不可信的情况下,我们可以使用Linux静态命令工具箱busybox来执行操作系统命令,以求达到一个干净的环境

我们可以file busybox看到它是静态编译的,不受动态库环境变量的影响

Linux安全之进程篇

使用busybox 执行ps命令

Linux安全之进程篇

那么内核层的呢?

系统调用下的劫持,我们后面开篇单独讲。


关于VFS层的劫持,这个在rootkit中用得很多

大名鼎鼎的adore-ngenyelkm就是使用的这个方式

 

Linux下一切皆文件,说一下ps命令的本质,ps命令的本质还是读取文件,ps程序通过 open /proc 打开 fd,通过 getdents <fd> 遍历目录,如图执行命令strace/bin/ps

Linux安全之进程篇

可以看到它最终其实是实现了系统调用getdents


检查隐藏进程

不管是用户层的隐藏还是内核层的隐藏,我们想出一个办法,如果在内核态直接把所有进程遍历打印出来,然后再在用户态模拟ps执行命令,那么把两种结果进行循环比较,如果内核态的进程比ps模拟执行的进程多,那么隐藏进程就会被筛选出来

使用这个内核函数for_each_process()可以遍历内核态所有进程

 

根据这个原理,我写了一个隐藏进程检测工具,如下图检测工具运行结果:

隐藏进程检测工具感兴趣的可以加入知识星球进行下载。

执行 tar -xvf plist.tar

pythonplist.py

Linux安全之进程篇


是简单的一个脚本,测试在centos6.5环境下,其他发行版的大家可以自己延申

  

最后给大家一个一条命令隐藏进程的小技巧:

mount --bind

Linux安全之进程篇

可以看到两次执行ps -ef|greprootkit的返回结果是不一样的,第二次看不到rootkit

原因就是我们中间执行了这么一条命令

mount--bind /root/aaa /proc/12755

12755的进程目录绑定到一个空目录上,这样ps遍历该进程目录的时候就为空,达到了隐藏进程的目的(包括top命令都隐藏了)

如果需要卸载用umount/proc/12755

 

那么怎么检查呢,我们观察,除kcore外只有其在/proc下字节为非0

因此我们给出一条检查命令

ls -l/proc|awk '$9!="kcore"&&$5==4096 {print $9}'

Linux安全之进程篇

完整卸载命令如下:

umount/proc/`ls -l /proc|awk '$9!="kcore"&&$5==4096 {print $9}'`

 

近期会发布下一篇,Linux安全系列之二---启动篇,感兴趣的可以留意。


不得不等创建了一个“等级保护测评”知识星球,这是一个付费加入的知识分享群。建立这个星球的初衷:分享与整合各类资源,大家共同成长。

所有加入等级保护测评星球的伙伴们,请加我微信:djbhcp,不得不等将拉你加入“等级保护测评知识星球VIP群”,与各位大咖畅聊网络安全,永不掉队。


定价:198元/年

服务时间为一年,自加入日期顺延一年。


如何加入:扫描二维码,扫码付费即可加入。


其他文章:



版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《Linux安全之进程篇》的版权归原作者「等级保护测评」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

举报