信息熵在ICMP隧道检测中的实践

VSole2021-11-02 14:02:41

ICMP协议通常用来测试网络通不通、主机可不可达、路由可不可用。宅男们打游戏时也常用来ping一下,看看延迟高不高,太高迅雷就得关一关了。

而网络攻击者通过ICMP协议,可以进行隧道传输,实现数据窃取,规避掉一些防火墙规则。

如何检测这种隧道?用传统的签名无法对抗负载加密,复杂的统计比对让检测引擎不堪重负,准确率也不高。

而基于ICMP常规的通讯数据和攻击时产生的畸形数据,利用信息熵来分析,可以为检测打开突破口。

1ICMP隧道

在ICMP报文中,最值得关注的是类型0x0和类型0x8。0x0类型的ICMP报文代表ICMPECHOREPLAY(响应),0x8类型的ICMP报文代表ICMPECHO(查询)。

以ping命令为例。在进行工作时,ping命令向远程主机发送一个或多个ICMPECHO数据包,其目的是判断远程主机是否可以到达。

ICMP数据包的选项部分可以填写数据,通常在ICMP报文到达远程主机的过程中,记录沿途经过的路由器地址以及沿途经过路由器时耗费的时间。一般的通讯数据形式如下:

PTunnel介绍

PTunnel是一种可以把TCP链接通过ICMP的显示请求(ping请求)和回复(ping回复)包进行传输的工具。

这种工具能够将数据信息隐秘地送入或送出网络,可以用于只有ICMP数据流允许出入的网络的情况。源码下载地址:

“http://www.cs.uit.no/~daniels/PingTunnel/。”

运行环境

PTunnel可以安装在Windows系统和Linux系统中。实验环境为:

客户端:Windows 7 + WireShark 【192.168.12.87】;

服务端:Kali 【192.168.12.234】;

在客户端和服务器端安装PTunnel,双方能直接通过IP地址实现点到点的数据通讯。

运行方式

客户端:

服务端:

模拟场景中,服务端安装MySQL仅允许本地登录,双方与防火墙串联在一起形成单一网络。

通过PTunnel工具建立ICMP隧道,绕过中间防火墙协议和服务器MySQL地址策略的限制,实现在客户端上成功访问服务器的本地MySQL数据库。

在服务器端开启PTunnel监听模式:

root@localhost:~#ptunnel[inf]:Starting ptunnel v 0.71.[inf]:(c) 2004-2009 Daniel Stoedle, <daniels@cs.uit.no>[inf]:Security features by Sebastien Raveau,<sebastien.raveau@epita.fr>[inf]:Forwarding incoming ping packets over TCP.[inf]:Ping proxy is listening in privileged mode.

在客户端以管理员权限启动cmd命令行,输入命令参数如下:

c:\Users\xxxx\Desktop>ptunnel.exe-p 192.168.12.234 -lp 808 -da 127.0.0.1 -dp 3306

将192.168.12.234上的3306端口和本地客户端808端口建立ICMP隧道,实现数据的通讯。在客户端连接808端口就相当于连接远程服务器上的数据库3306端口。

在客户端另起一个cmd命令行,连接本地的808端口,实现对远程服务器192.168.12.234数据库的访问。命令如下:

C:\xampp\mysql\bin>mysql.exe-h 127.0.0.1 -P 808 -uroot -p123456

在客户端上通过PTunnel成功连接上服务器的数据库:

数据报文分析

实际通信中,客户端将一直发送ICMP请求报文,而对应的服务端将针对请求报文发送ICMP应答报文,从而在服务端和客户端建立起一条ICMP隧道,通过将TCP报文封装在ICMP报文中,从而能够实现数据的传输。

如下图所示,所有的ICMP请求报文均是从客户端发送至服务端:

客户端与服务端通过ICMP协议中请求和应答包建立初始连接,数据包序号为3、4,类似于TCP连接中的三次握手:

在建立初始连接后,从序号为5的数据包为服务端向客户端发送握手初始化包,该包是为了提醒客户端下面需要进行身份认证:

客户端收到服务器提出的身份验证请求后,将身份帐号密码封装到ICMP请求包的data部分,返回给客户端:

操作数据库时,可以看到命令和返回信息:


2信息熵

如果通过签名规则的方式针对上述流量进行检测还是能起到一定的效果,但如果数据经过了加密,例如SSH的流量,那就无法使用签名的方式来检测。

我们也可以通过找规律的方式去检测,例如负载的长度不一致、请求和响应报数不一致、负载内容相似度等等,包括可以使用suricata的lua规则。但这类规则维护起来比较麻烦,且在公网流量中测试误报较多。

对于这些很难用签名规则检测的恶意流量,不可能直接用一种规则就能准确检测出来,首先需要从来海量流量中找到有异常的部分,也就是找线索。

针对ICMP隧道这类流量,相比正常流量,表现出来的规律就是数据的随机性特别大——没有规律,这就使得信息熵派上了用场。

信息熵

信息熵可以作为一个系统复杂程度的度量,如果系统越复杂,出现不同情况的种类越多,那么它的信息熵是比较大的。简单的说就是,信息随机性越强,熵值越大。

检测思路

检测思路其实就是观察到的异常现象,用代码语言描述然后落地,但如果没有点数学基础,实现起来就比较费时费力。

具体步骤如下:

首先,采集一定时间内的ICMP流量,计作一段流,作为计算输入。

然后,针对流中的每次ICMP通讯中的负载进行熵计算。

最后,对所有熵计算标准平方差。

如果标准方差为0,则说明这些负载都一样;如果标准方差越偏离0,则说明负载随机性很高,不是正常的ICMP通讯。

代码实现

根据信息熵计算的原理,即“对不重复数据的计算,且负载中的不重复数据的数量一定小于报文长度”,通过计算报文的熵,最后进行标准方差计算,部分代码如下。

获取报文熵:

//判断是否存在  intIsRepeat(int x,u_char y,u_char** z){   for(int n = 0; n < x; n++)                       {       if(z[0][n] == y)    {           z[1][n] += 1;      return1;    }  }   return 0;     }
//返回存在个数intRepeatCount(u_char* x,int y,u_char** z) {   z[0][0]=*x;       z[1][0]=1;   int maxC=1;   x++;   for(int n=0;n<y-1;n++)   {       if(!IsRepeat(maxC, *x, z))       {           z[0][maxC]=*x;           z[1][maxC]=1;           maxC++;               }         x++;                              }    return maxC;      }    //log换底公式floatMathLogFunc(float x){   return(x*(log(x)/log(2)));}
//计算报文的熵floatCalcEntropy(int x, int y, u_char** z)  {                                   float result = 0;
   for(int n = 0; n < x; n++)   {           result += -MathLogFunc((float)z[1][n]/y);     }  returnresult;  }  
floatgetEntropy(u_char* x, int y){  u_char**tmp = (u_char**)malloc(2 * sizeof(u_char*));  for(inti1 = 0; i1 < 2 ; i1++)  {    tmp[i1] = (u_char*)malloc(y * sizeof(u_char));    memset(tmp[i1], 0, y * sizeof(u_char));  }  floatresult = CalcEntropy(RepeatCount(x, y, tmp), y, tmp);  for(inti2 = 0; i2 < 2;i2++)  {    free(tmp[i2]);  }  free(tmp);  returnresult;}计算标准方差://计算平均值floatCalcAverage(float* x, int y){  floattmp = 0;  for(inti = 0; i < y; i++)  {    tmp+= x[i];  }  return((float)tmp/y);}
//计算标准方差floatCalcSD(float* x,int y){   float average = CalcAverage(x, y);   float tmp = 0;   for(int i = 0; i < y; i++)   {   tmp += (float)pow(x[i] - average, 2);   }   return((float)sqrt(tmp/y));}

测试效果

通过PTunnel、Nishang等工具制造出一些ICMP隧道的报文,用程序测试看一下效果。

正常ping百度、163等网站的ICMP报文,计算出来的为0:

而计算工具产生的隧道报文时,就看到以下标准方差很大:


3总结

在现网测试时,往往会遇到一些来历不明的ICMP流量,大多数都是相似的负载,偶尔会夹杂时间戳信息,也会有一些IoT设备发出的流量,调整标准方差来判断即可。

利用信息熵来检测ICMP隧道的方式,能有效的解决规则不好描述、难以维护的问题,但对于一些加密、未知的流量,这种方式只是一个线索发现功能,要确认是否是真正的攻击流量,还需要借助其他数据信息进行综合判断。

icmp信息熵
本作品采用《CC 协议》,转载必须注明作者和本文链接
ICMP协议通常用来测试网络通不通、主机可不可达、路由可不可用。宅男们打游戏时也常用来ping一下,看看延迟高不高,太高迅雷就得关一关了。 而网络攻击者通过ICMP协议,可以进行隧道传输,实现数据窃取,规避掉一些防火墙规则。 如何检测这种隧道?用传统的签名无法对抗负载加密,复杂的统计比对让检测引擎不堪重负,准确率也不高。 而基于ICMP常规的通讯数据和攻击时产生的畸形数据,利用信息熵来分析,
隐蔽隧道怎么防?
2022-08-02 22:08:31
攻击队完成初始打点后,通常会建立外联隐蔽隧道维持权限,并进一步通过横向移动最终获得靶标。HTTP隐蔽隧道检测难度比较大,需要结合单流、多流层面,利用规则、行为、人工智能等多个方法综合进行判断。
在对抗日益激烈、加密手段逐渐成为主流的今天,攻防演练场景中的加密流量也已逐渐成为主流,对加密流量检测的技术变得愈发重要。目前针对攻防演练场景的加密流量检测主要分为解密后检测和不解密检测两大类,传统的解密检测拥有可以直接将加密流量转化为明文后采用完善的传统手段继续检测的优势,但也有诸如性能耗损、隐私泄露以及可以解密的流量有限等缺点,基于上述问题,不解密检测的方法逐渐受到业界重视,本文将从不解密的前提
攻防演练场景下的加密流量分为入联、横向、出联三个类别,本文将从不解密的前提下对三类流量检测展开介绍。
icmp 隧道代理搭建
2022-08-07 20:17:09
简介 在内网渗透中,内网隧道的搭建是必不可少的。有条件的情况下,优先使用tcp隧道,比较稳定可靠。但是遇到只有icmp协议出网的时候,就需要利用别的思路了。ICMP代理 两台机器之间,只允许icmp 协议通讯,其他的协议tcp/udp 不允许,那么可以考虑利用icmp 隧道进行穿透。
ICMP隧道攻击
2022-04-27 21:50:29
ICMP一般用于检测网络的可通性
它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用ICMP协议主要提供两种功能,一种是差错报文,一种是信息类报文。标识符和序号字段分别是16 位的字段。对于标识符,应用程序执行期间送出的所有报文里填入相同的值。例如,icmptunnel会在所有的ICMP payload前添加”TUNL”标记来识别隧道。
使用 ICMP 传递 shellcode
2021-02-17 21:59:14
在研究不同的渗透方法时,我遇到了一种利用DNS的技术。在编写概念证明代码时,我注意到实现的ping函数很有趣。我们可以提供一个可容纳65,500字节的缓冲区。由于大小限制很大,我们可以将shellcode加载到我们的ICMP请求中,然后将其注入到目标的进程中。
ICMPWatch是一款功能强大的ICMP数据包嗅探工具,该工具基于Python 3开发,可以帮助广大研究人员捕捉和分析ICMP(Internet控制报文协议)数据包。该工具能提供有关捕捉数据包的详细信息,包括数据包源IP地址、目标IP地址、MAC地址、ICMP类型以及Payload数据等。除此之外,该工具还支持将捕捉到的数据包存储到SQLite数据库中,并以pcap格式保存。
VSole
网络安全专家