来源:https://activecm.github.io/threat-hunting-labs/long_connections/
一、目标
识别长期存在的网络连接。
二、工具使用
Wireshark
Zeek
RITA
三、背景
要确定连接保持打开状态的时间,我们首先需要定义连接的开始或结束部分是什么。
对于TCP,典型的连接以3路握手开始(SYN, SYN/ACK, ACK),以4路握手结束(FIN, ACK, FIN, ACK)
TCP 3路握手连接启动
客户端->>服务器:SYN 服务器->>客户端:SYN/ACK 客户端->>服务器:ACK
TCP 4路握手连接结束
客户端->>服务器:FIN 服务器->>客户端:ACK 服务器->>客户端:FIN 客户端->>服务器:ACK
这意味着很容易判断TCP连接何时开始和结束。但是,无状态协议(即UDP)没有相同的属性。UDP连接没有正式打开,术语“连接”在应用到UDP上是很棘手的。防火墙和大多数数据包分析工具所做的是定义一个时间窗口(通常为30-60秒),在此期间,使用相同ip和端口号的UDP数据包被认为是同一“会话”的一部分。每当看到一个新的数据包时,会话窗口TCPtimer就会重置。这意味着会话在看到第一个UDP包时被认为启动,在时间窗口期间没有看到任何UDP包时被认为结束。术语“会话”和“连接”通常可以互换使用。
以下信息必须在数据包之间保持相同,才能被视为同一会话的一部分。尽管IP和端口将在源和目的地之间交换,这取决于数据包的方向。*源和目的IP地址*源和目的端口*协议,这些信息通常被称为一个5元组,用于区分各个会话。
四、狩猎
我们将找到那些活动时间最长的连接。这可能表明攻击者的C2会话存在较长时间。
五、Wireshark
打开你的pcap在Wireshark。这将加载主窗口中的每个数据包。
在统计菜单下选择对话。对话窗口将所有数据包汇总为“对话”。
选择TCP选项卡并通过单击Duration列进行排序。再次单击以按降序排序。
从这里可以看到哪些TCP连接打开的时间最长。在上图中,我们有一个从10.55.100.100到65.52.108.255的连接,连接端口为443 (HTTPS),打开时间为86,222秒,即23.95小时。
接下来,选择UDP选项卡,并通过两次单击Duration列应用相同的排序。
这里我们有一个UDP数据包,在123端口(NTP)上从192.168.88.2到216.299.4.69,持续时间为86,217秒,或23.95小时。
然而,回想一下上面关于UDP如何没有真正的“开始”和“结束”时间的讨论。一些工具将使用时间窗口来确定UDP连接何时结束。通过查看第二项,我们可以看出Wireshark很可能不会这样做。如果将总时间(86,209)除以发送的数据包总数(6),就会看到数据包之间的平均延迟为14,368秒(或大约4小时)。这么宽的时间窗口是没有用的,我们可以安全地假设Wireshark向我们显示的是数据包捕获整个时间段内的数据“对话”。
六、Zeek
在开始之前,一定要使用Zeek分析pcap。
您的Zeek日志应该包括一个名为connl .log的文件。您可以使用head命令检查该文件中的内容。
head conn.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path conn
#open 2019-10-16-15-13-09
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto serviceduration orig_bytes resp_bytes conn_state local_orig local_resp missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents
#types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string]
1517336042.090842 CW32gzposD5TUDUB 10.55.182.100 14291 10.233.233.5 80 tcp -3.000158 0 0 S0 - - 0 S 2 104 0 0 -
1517336042.279652 ComPBK1vso3uDC8KS2 192.168.88.2 55638 165.227.88.15 53 udp dns 0.069982 61 81 SF - - 0 Dd 1 89 1 109 -
这本身不是很好读。在一行中显示太多的列。让我们用zeek-cut把列简化成我们想看的。
head conn.log | zeek-cut -c id.orig_h id.orig_p id.resp_h id.resp_p proto service duration
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path conn
#open 2019-10-16-15-13-09
#fields id.orig_h id.orig_p id.resp_h id.resp_p proto service duration
#types addr port addr port enum string interval
10.55.182.100 14291 10.233.233.5 80 tcp - 3.000158
192.168.88.2 55638 165.227.88.15 53 udp dns 0.069982
这样更好了,但是到目前为止我们只处理文件的前几行。使用cat而不是头将显示整个文件滚动。
cat conn.log | zeek-cut -c id.orig_h id.orig_p id.resp_h id.resp_p proto service duration
...
10.55.100.111 57481 172.217.6.2 443 tcp ssl 105.310590
10.55.100.111 57475 198.160.127.57 443 tcp ssl 105.614383
10.55.100.107 51651 52.203.62.126 443 tcp ssl 14.495950
10.55.100.111 57447 54.215.180.145 443 tcp ssl 109.111123
10.55.100.100 61848 205.204.101.182 80 tcp - 106.362057
10.55.100.111 57461 172.217.8.198 443 tcp ssl 107.272461
10.55.100.111 57459 172.217.8.198 443 tcp ssl 107.268048
10.55.100.111 57448 23.201.85.182 443 tcp ssl 108.628962
10.55.100.106 60207 65.52.108.188 443 tcp ssl 2340.397545
10.55.100.111 57477 63.140.32.190 443 tcp ssl 105.333464
192.168.88.2 123 216.229.4.69 123 udp ntp 0.048235
接下来,让我们介绍一下sort命令。* -n将根据数字顺序进行排序,* -r将反向排序,以便最大的数字位于顶部* - k7告诉sort使用第7列,即我们的duration列
cat conn.log | zeek-cut id.orig_h id.orig_p id.resp_h id.resp_p proto service duration | sort -nrk 7 | head
10.55.100.100 49778 65.52.108.225 443 tcp - 86222.365445
10.55.100.107 56099 111.221.29.113 443 tcp - 86220.126151
10.55.100.110 60168 40.77.229.82 443 tcp - 86160.119664
10.55.100.109 53932 65.52.108.233 443 tcp ssl 72176.131072
10.55.100.105 60214 65.52.108.195 443 tcp ssl 66599.002312
10.55.100.103 49918 131.253.34.243 443 tcp - 64698.370547
10.55.100.104 63530 131.253.34.246 443 tcp ssl 57413.278323
10.55.100.111 63029 111.221.29.114 443 tcp - 46638.510373
10.55.100.108 52989 65.52.108.220 443 tcp - 44615.165823
10.55.100.106 52918 40.77.229.91 443 tcp ssl 41206.913035
我们将connl .log的内容通过管道传输到zeek-cut,这样就减少了字段的数量,从而只显示我们关心的字段。接下来,我们使用sort按持续时间对行进行排序。最后,我们使用head只显示前10个条目。
从这里可以看到哪些TCP连接打开的时间最长。在上面的输出中,我们在端口443上有一个从10.55.100.100到65.52.108.255的连接,该连接打开了86,222秒,即23.95小时。
请注意,log将TCP、UDP和ICMP的连接显示在同一个文件中。因此,上面的命令为我们提供了跨所有这些协议的最长连接。如果我们想过滤掉并且只看到最长的UDP连接,我们在排序之前使用grep。
cat conn.log | zeek-cut id.orig_h id.orig_p id.resp_h id.resp_p proto service duration | grep udp | sort -nrk 7 | head
10.55.182.100 63546 96.45.33.73 8888 udp - 99.087045
10.55.182.100 59685 172.217.8.196 443 udp - 59.539003
10.55.182.100 63546 96.45.33.73 8888 udp - 59.322097
10.55.182.100 63546 96.45.33.73 8888 udp - 56.383127
10.55.182.100 63546 96.45.33.73 8888 udp - 55.771569
10.55.182.100 63546 96.45.33.73 8888 udp - 54.537906
10.55.182.100 59690 172.217.4.34 443 udp - 53.620681
10.55.182.100 63546 96.45.33.73 8888 udp - 51.529226
10.55.182.100 63546 96.45.33.73 8888 udp - 51.355111
10.55.182.100 63546 96.45.33.73 8888 udp - 48.440549
这里我们可以看到,UDP长连接的结果从Zeek不同于我们得到的如果我们使用Wireshark。这是因为Zeek在分析UDP连接时使用了1分钟的无活动超时,而Wireshark没有使用超时。
七、累计性长连接
在某些情况下,恶意软件可能会表现出介于单个长连接或短且频繁的信标间隔之间的行为。相反,它可以打开一个连接,保持它打开一段时间(例如30分钟),然后立即打开另一个连接,然后重复。
下面的图片展示了一个连接保持24小时开放与6个连接分散在24小时内的区别。
这样,攻击者仍然能够在很长一段时间内保持持久通信,但可能不会出现在我们目前所做的长连接分析中。下面的命令将打印从一个IP地址到同一目标IP和端口的累计连接时间。
cat conn.log | zeek-cut id.orig_h id.resp_h id.resp_p proto duration | awk 'BEGIN{ FS="\t" } { arr[$1 FS $2 FS $3 FS $4] += $5 } END{ for (key in arr) printf "%s%s%s\n", key, FS, arr[key] }' | sort -nrk 5 | head
10.55.100.100 65.52.108.225 443 tcp 86222.4
10.55.100.107 111.221.29.113 443 tcp 86220.1
10.55.100.110 40.77.229.82 443 tcp 86160.1
10.55.100.109 65.52.108.233 443 tcp 72176.1
10.55.100.105 65.52.108.195 443 tcp 66599
10.55.100.103 131.253.34.243 443 tcp 64698.4
10.55.100.104 131.253.34.246 443 tcp 57413.3
10.55.100.111 172.217.8.198 443 tcp 55728.1
10.55.100.111 111.221.29.114 443 tcp 46658.4
10.55.100.108 65.52.108.220 443 tcp 44615.2
awk是一个强大的脚本编制工具。然而,语法开始变得非常混乱,都在一行上,就像这样。
开始{FS="\t"} -将FS(字段分隔符)变量设置为制表符。这是用来分隔Zeek日志中的列以及我们希望在输出中使用的内容。BEGIN意味着在处理任何数据之前,该指令只执行一次。
{arr[$1 FS $2 FS $3 FS $4] += $5} -创建一个数组(名为arr)并将持续时间相加($5是第五个字段,它是我们的持续时间)。这里的重要部分是,我们使用前四个字段($1到$4)的连接作为数组键。这意味着,只要源ip和目标ip、目标端口和协议保持不变,就会将持续时间加到总数中。awk对每一行数据重复执行此指令。
这里我们循环遍历数组中的所有元素并打印出结果。END表示awk在处理完所有数据后只执行这条指令一次。
我们在这个数据集中得到的结果与上一节中所有长连接的结果非常相似。但是,请注意,在前面的长连接中没有从10.55.100.111到172.217.8.198的长连接。但在这里我们可以看到,它有足够多的个人联系,可以进入前10名。
让我们修改我们的命令:
忽略目标端口和协议。如果两个ip直接通信,无论如何,我们都想知道。这将捕捉恶意软件在同一IP上的多个端口或协议之间切换的情况。
打印出占总持续时间的连接数。这将帮助我们区分有单个长连接的条目和有多个连接的条目。
cat conn.log | zeek-cut id.orig_h id.resp_h duration | awk 'BEGIN{ FS="\t" } { arr[$1 FS $2] += $3; count[$1 FS $2] += 1 } END{ for (key in arr) printf "%s%s%s%s%s\n", key, FS, count[key], FS, arr[key] }' | sort -nrk 4 | head
10.55.100.100 65.52.108.225 1 86222.4
10.55.100.107 111.221.29.113 1 86220.1
10.55.100.110 40.77.229.82 1 86160.1
10.55.100.109 65.52.108.233 1 72176.1
10.55.100.105 65.52.108.195 1 66599
10.55.100.103 131.253.34.243 1 64698.4
10.55.100.104 131.253.34.246 1 57413.3
10.55.100.111 172.217.8.198 543 56057.3
10.55.100.111 111.221.29.114 2 46658.4
10.55.100.108 65.52.108.220 1 44615.2
我们可以看到,即使不考虑协议和端口,结果也没有变化。然而,现在我们可以看到,从10.55.100.111到172.217.8.198的这一对有543个单独的连接,而列表中的其余部分有1或2个连接。通过用56057秒除以543个连接,我们可以看到每个连接打开的平均时间为103秒。如果我们想进一步研究,我们可以查看这些单独连接的时间和持续时间,甚至执行一些简单的统计分析,就像我们在信标中所做的那样,以查看这些连接中是否有任何规律性或模式。
八、RITA
RITA使用Zeek日志,应该会得到与我们前面直接查看日志文件相同的结果。如果还没有,请按照基本工具使用文档中的描述导入日志文件。
本例中的数据集名称为“sample”。
rita show-long-connections -H --limit 10 sample
+---------------+----------------+--------------------------+----------+
| SOURCE IP | DESTINATION IP | DSTPORT:PROTOCOL:SERVICE | DURATION |
+---------------+----------------+--------------------------+----------+
| 10.55.100.100 | 65.52.108.225 | 443:tcp:- | 86222.4s |
| 10.55.100.107 | 111.221.29.113 | 443:tcp:- | 86220.1s |
| 10.55.100.110 | 40.77.229.82 | 443:tcp:- | 86160.1s |
| 10.55.100.109 | 65.52.108.233 | 443:tcp:ssl | 72176.1s |
| 10.55.100.105 | 65.52.108.195 | 443:tcp:ssl | 66599s |
| 10.55.100.103 | 131.253.34.243 | 443:tcp:- | 64698.4s |
| 10.55.100.104 | 131.253.34.246 | 443:tcp:ssl | 57413.3s |
| 10.55.100.111 | 111.221.29.114 | 443:tcp:- | 46638.5s |
| 10.55.100.108 | 65.52.108.220 | 443:tcp:- | 44615.2s |
| 10.55.100.106 | 40.77.229.91 | 443:tcp:ssl | 41206.9s |
+---------------+----------------+--------------------------+----------+
请注意,RITA将TCP、UDP和ICMP连接混在一起,因为它们在Zeek的conn.log中,而且没有办法使用RITA按协议分离结果。
网友评论