ICMP隐蔽隧道通信与检测
技术背景
在一些网络环境中,如果攻击者使用各类上层隧道(例如HTTP隧道,DNS隧道,正反向端口转发等)进行操作均失败。那么可以尝试使用ICMP建立隧道,ICMP协议不需要端口的开放,因为其基于IP工作的,所以我们将其归结到网络层,ICMP消息最为常见的就是ping命令的回复,将TCP/UDP数据包封装到ICMP的ping数据包中,从而穿过防火墙**(通常防火墙是不会屏蔽ping数据包的)**
技术原理
由于ICMP报文自身可以携带数据,而且ICMP报文是由系统内核处理的,不占用任何端口,因此具有很高的隐蔽性。
通常ICMP隧道技术采用ICMP的ICMP_ECHO和ICMP_ECHOREPLY两种报文,把数据隐藏在ICMP数据包包头的选项域中,利用ping命令建立隐蔽通道。
进行隐蔽传输的时候,防火墙内部主机运行并接受外部攻击端的ICMP_ECHO数据包,攻击端把需要执行的命令隐藏在ICMP_ECHO数据包中,被攻击者接收到该数据包,解出其中隐藏的命令,并在防火墙内部主机上执行,再把执行结果隐藏在ICMP_ECHOREPLY数据包中,发送给外部攻击端。
优缺点
- 优点:防火墙对ICMP_ECHO数据包是放行的,并且内部主机不会检查ICMP数据包所携带的数据内容,隐蔽性高。
- 缺点:ICMP隐蔽传输是无连接的,传输不是很稳定,而且隐蔽通道的带宽很低。利用隧道传输时,需要接触更低层次的协议 ,这就需要高级用户权限。
icmptunnel
服务器暴露在外网上,可以访问外部网络,但是服务上有防火墙,拒绝了敏感端口的连接(比如22端口,3389端口等)。使用icmpsh的目的就是为了能够绕过对敏感端口的限制,此时ICMP作为获取反向shell的通道,进行反向shell。
#获取icmptunnel
git clone https://github.com/jamesbarlow/icmptunnel
实验设置
(1)两台虚拟机:攻击者A 服务器B
(2)两台虚拟机安装icmptunnel,建立虚拟网卡tun0。设置ip分别为10.0.0.1和10.0.0.2。(参考readme中的quickstart操作建立连接)
可以从攻击机ssh连接目标机。在不同网卡(eth0和tun)抓包,可以看到所有TCP流量都被装进了ICMP流量中。
但利用iptables等防火墙配置端口规则仍会导致失效,如何理解绕过防火墙仍有待验证。
检测思路
1、检测同一源的ICMP数据包的流量。一个ping命令每秒发送2个数包,而使用ICMP隧道的机器会发送很多ICMP数据包。
2、检查ICMP数据包的协议与标签。例如,icmptunnel会在所有的ICMP payload前添加”TUNL”标记来识别隧道。tunl包请求包和响应包内容不一致,正常icmp包应一致。
Quickstart
First, disable ICMP echo responses on both the client and server. This prevents the kernel from responding to ping packets itself.
# echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
On the server-side, start icmptunnel in server mode, and assign an IP address to the new tunnel interface.
# ./icmptunnel –s
opened tunnel device: tun0
(ctrl-z)
bg
/sbin/ifconfig tun0 10.0.0.1 netmask 255.255.255.0
On the client-side, point icmptunnel at the server, and assign an IP address.
# ./icmptunnel <server>
(./icmptunnel 192.168.0.103)
opened tunnel device: tun0
connection established.
(ctrl-z)
bg
/sbin/ifconfig tun0 10.0.0.2 netmask 255.255.255.0
At this point, you should have a functioning point-to-point tunnel via ICMP packets. The server side is 10.0.0.1, and the client-side is 10.0.0.2. On the client, try connecting to the server via SSH:
# ssh root@10.0.0.1
Password:
To use the remote server as an encrypted SOCKS proxy:
# ssh -D 8080 -N root@10.0.0.1
Password:
Now point your web browser at the local SOCKS server.