在企业内网环境中,ICMP协议是必不可少的网络通信协议之一,被用于检测网络连通状态,通常情况下,防火墙会默认放此协议。由于防火墙对ICMP协议开放,恶意攻击者常会利用ICMP协议进行非法通信。例如,在黑客攻击中经常出现一种情况是,黑客通过某一种方式取得了一台主机的权限,得到了一些文件,比如域hash,密码文件之类的东西,需要回传至本地进行破解,但是防火墙阻断了由内网发起的请求,只有icmp协议没有被阻断,而黑客又需要回传文件,这个时候如果黑客可以ping通远程计算机,就可以尝试建立ICMP隧道,ICMP隧道是将流量封装进 ping 数据包中,旨在利用 ping数据穿透防火墙的检测。现在市面上已经有了很多类似的工具了,比如 icmptunnel、ptunnel、icmpsh等。
本文将为大家介绍一种简单而有效的icmp隧道检测技术。我们将利用Spark Streaming,来帮助我们检测ICMP隧道。
ICMP(Internet ControlMessages Protocol,网间控制报文协议)是TCP/IP协议族的子协议,是一种面向无连接的协议。ICMP协议的结构,如图1所示:
图1
经常使用的ping命令就是基于ICMP协议,windows系统下ping默认传输的是: abcdefghijklmnopqrstuvwabcdefghi,共32bytes,如图2所示:
图2
linux系统下,ping默认传输的是48bytes,前8bytes随时间变化,后面的固定不变,内容为!”#$%&’()+,-./01234567,如图3所示:
图3
此外,ping的包大小,也就是data大小是可以修改的,以windows为例,使用ping baidu.com -l 223,修改为223bytes,从包体内容来看,规律还是一样,就是重复罢了,如图4所示:
图4
那能否改变这些data填充我们自己的数据呢? 答案是当然可以! 这就是ICMP隐蔽隧道的原理,改变操作系统默认填充的Data,替换成我们自己的数据。 比如使用icmp隧道可以构造一个包含有www.facebook.com字符串的自定义data的包,如图5所示:
图5
windows系统下ping默认传输的是:abcdefghijklmnopqrstuvwabcdefghi,16进制内容为:
6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869
linux系统下ping默认传输的内容,去掉开头可变的8bytes后是:!”#$%&’()+,-./01234567,16进制内容为:
101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
对自定义长度的ping,在linux下使用ping -s 500 baidu.com产生了492位大小的data,去掉开头可变的8bytes,16进制内容为:
101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3
windows下自定义长度的ping类似,16进制内容为:
6162636465666768696a6b6c6d6e6f70717273747576776162636465666768696a6b6c6d6e6f70717273747576776162636465666768696a6b6c6d6e6f707172737475
因此,正常操作系统下通过ping产生的data,转换为16进制后为从00开始不断递增然后一直到ff的重复序列中的一段或几段。
000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
对于icmp隧道产生的自定义data数据包,转换为16进制后内容是乱序没有规律的,比如构造一个内容为R5*êÍwwwfacebookcom字符串的自定义data的包,其16进制内容为:
4500003e377d400040119c2f0a0001020a0052019d800035002a1a14eacd01000001000000000000037777770866616365626f6f6b03636f6d0000010001
因此,可以根据ping产生的data数据包,转换为16进制后的内容是否有规律来做区分。
在这里使用AC自动机 字符串匹配方法进行特征匹配,具体做法为:
(1) 将正常操作系统产生的不断重复序列,如下:
000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
每4位切分成特征数组,生成的特征数组如下:
"0001", "0203","0405", ...... "feff"
对ping产生的data数据,如以下linux产生的data:
e7cd0a0000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3
每4位切分成特征数组,生成的特征数组如下:
"e7cd", "0a00", ......, "1011","1213","1415",......, "feff"
(2) 使用ac自动机算法,将生成的特征数组和正常操作系统生成的特征数组进行匹配,将匹配到的特征的个数*4/payload长度作为匹配度,进行计算得到匹配度0.987。
匹配度算法:
匹配度 = 匹配到的特征的个数*4 / payload的长度
对于正常的ping数据产生的data,计算得到的匹配度结果都在0.9以上,Icmp隧道产生的自定义data的数据包通常匹配度很低,可以根据匹配度来区分是否是正常操作系统产生的数据包。
对于正常的ping命令产生的数据,有以下特点:
每秒发送的数据包个数比较少,通常每秒最多只会发送两个数据包;
请求数据包与对应的响应数据包内容一样;
数据包中payload的大小固定,windows下为32bytes,linux下为48bytes;
数据包中payload的内容固定,windows下为abcdefghijklmnopqrstuvwabcdefghi,linux下为!”#$%&’()+,-./01234567,如果指定ping发送的长度,则为不断重复的固定字符串;
type类型只有2种,0和8。0为请求数据,8为响应数据。
对于ICMP隧道产生的数据,有以下特点:
每秒发送的数据包个数比较多,在同一时间会产生成百上千个 ICMP 数据包;
请求数据包与对应的响应数据包内容不一样;
数据包中 payload的大小可以是任意大小;
存在一些type为13/15/17的带payload的畸形数据包;
个别ICMP隧道工具产生的数据包内容前面会增加 ‘TUNL’ 标记以用于识别隧道。
因此,根据正常ping和ICMP隧道产生的数据包的特点,可以通过以下几点特征检测ICMP隧道:
检测同一来源数据包的数量。正常ping每秒只会发送2个数据包,而ICMP隧道可以每秒发送很多个;
检测数据包中 payload 的大小。正常ping产生的数据包payload的大小为固定,而ICMP隧道数据包大小可以任意;
检测响应数据包中 payload 跟请求数据包是否不一致。正常ping产生的数据包请求响应内容一致,而ICMP隧道请求响应数据包可以一致,也可以不一致;
检测数据包中 payload 的内容。正常ping产生的payload为固定字符串,ICMP隧道的payload可以为任意;
检测 ICMP 数据包的type是否为0和8。正常ping产生的带payload的数据包,type只有0和8,ICMP隧道的type可以为13/15/17。
将基于统计的ICMP隧道检测部署到生产环境中,需要考虑大数据规模对模型的时效性、吞吐量等性能指标的影响。经多方考量,最终选用Spark Streaming进行在线检测。
Spark Streaming 是Spark核心API的一个扩展,可以实现高吞吐量、具备容错机制的实时流数据处理。支持从多种数据源获取数据,包括Kafka、Flume、Twitter、ZeroMQ、Kinesis 以及TCP sockets,从数据源获取数据之后,可以使用诸如map、reduce、join和window等高级函数进行复杂算法的处理。最后还可以将处理结果存储到文件系统,数据库和现场仪表盘。在“One Stack rule them all”的基础上,还可以使用Spark的其他子框架,如集群学习、图计算等,对流数据进行处理。
整个过程主要分3个阶段:
数据收集 => 汇总统计 => 检出过滤,具体检测逻辑,见图6所示:
图6
Spark Streaming中读入实时流量数据,设置15秒处理一次数据,根据数据包的源ip、目的ip大小排序拼接后进行分组,将同一个ip向目的ip发送的请求/响应数据包分到一个组中,分组字段timesortsip_dip 加上时间戳timestamp,为了过滤掉上一次15秒内该源ip、目的ip之间的数据包,保证每个15秒内只处理当前15秒内的同一ip、目的ip的数据。
根据分组后的数据,分别统计以下特征指标,作为最终是否检出的依据:
1. 在一个时间窗内,ICMP请求响应的数据包数量;
2. 捕获到的ICMP请求响应中,其payload部分是否是操作系统的正常长度;
3. 序号相同的ICMP数据包应当属于一对ICMP请求响应消息,他们的payload是否一致;
4. ICMP请求响应的payload内容是否正常(多模匹配);
5. ICMP请求是否是畸形Ping报文(Type是否异常);
对1/2/5直接使用统计组内的payload个数、payload_len长度值、是否有type不为0/8的数据包,直接得出。
对与3的判断,需要根据正常ping和异常数据的不同点,依据组内统计得到的id_seq集合和payload集合去重后,做大小比较得出:
对于正常ping,源ip向目的ip发送的一系列数据包中idseq全部不一样,其中identify为当次请求随机生成的序号不重复,同一批次identify一样,seq是根据数据包个数,从1开始一次递增1的数字,同一个请求和响应数据包的idseq一样,payload内容也一样。例:ping baidu.com产生了10个数据包,包括5次请求、5次响应,则id_seq去重后为5,payload去重后win下为1,linux下为5。
对于Icmp隧道,源ip向目的ip发送的一系列数据包中idseq,可以一样,也可以不一样。同一个请求和响应数据包的idseq可以一样,也可以不一样,payload内容不一样。例:隧道产生了10个数据包,则idseq去重后为5(seq依次递增)或1(seq固定不递增),payload去重后为10,极端情况下只有发送包,没有响应包,则idseq去重后为10。
可见不考虑一些极端情况,可以简单通过 payloadsnum > idseq_num 即可认为请求响应内容不同,对与极端情况,可以根据别的条件进行检出。
对于4的判断,使用2.2中介绍的方法进行判断payload是否异常。
为了减少误报,过滤掉一些正常的路由器发送的数据包,使用3种条件结合进行是否检出判断:
存在有非法type的payload且去重后的payload的个数大于阈值(经内网测试,个别路由器会发送有畸形type的payload内容一样的包,通过增加去重后的payload的个数大于阈值来过滤);
请求响应数据包不一致;
15秒内的数据包个数、非正常长度数据包个数、异常内容数据包个数、去重后的payload的个数 大于自定义的阈值检出(经内网测试,个别路由器隔几个小时会发送有异常内容的但是内容只有几个字符不一样的payload心跳包,通过增加去重(使用汉明距离去重,差别不超过3个字符的认为一样)后的payload的个数大于阈值来过滤)。
鉴于Icmp隧道特点的多样性,只要满足3者之一,就会检出,对于一些极端异常的ICMP隧道产生的包,比如隧道只有请求包没有响应包即一直往外发数据,则id_seq去重后为10(10次全是请求包,且seq递增),payload去重后为10,无法单独通过2检出,但是可以满足3,一样会检出,不会漏报。
目前测试过程中使用的已知负样本有以下几种:
icmpTunnel样本,使用icmpTunnel隧道工具造的样本;
icmptransmitter样本,使用icmptransmitter隧道工具造的样本;
icmpsh样本,使用icmpsh隧道工具造的样本;
badping样本,使用python脚本手动造的icmp的异常数据包。
异常样本检测准确率如下:
目前测试过程中使用的已知正样本有以下几种:
正常Ping数据包,Ping命令产生的数据包,平台包括linux/win/mac/solaris/android/ios,payload内容如下:abcdefg12345等。
网络设备心跳包,路由器等网络设备会定时发送的一些心跳包,payload内容如下:DataBuffer 0000001、DataBuffer 0000002等。
正常样本误报率如下,其中Ios平台偶尔有误报:
本文介绍了基于统计的检测ICMP隧道方法和落地实施中的一些技术细节。首先,基于统计的ICMP检测重点是需要了解ICMP隧道的工作原理和一些特征指标,只有较好的指标才能保证在真实环境中的检出效果。其次,为了达到在线实时检测,我们在文中介绍了结合Spark Streaming进行实时统计各种指标,检出超出阈值的数据。最后,通过分别对正样本和负样本进行测试,调整检出阈值,提高了检测准确度。
作者:斗象能力中心TCC-Chris
TCC团队长期招聘,包含各细分领域安全研究、机器学习、数据分析、大数据研发、安全研发等职位。感兴趣不妨联系我们。
Email: alex.xu@tophant.com。
推荐阅读