
0x00 介绍
网络图是一种将复杂的网络数据结构化、可分析化和可视化的方法,一个典型的用途便是威胁狩猎、建模分析时对TCP/IP网络通信进行建模和分析。Brim的Python库beta版发布使得将Zeek和网络图融在一起变得前所未有的简单。
0x01 预备知识
Brim
注:Windows、Linux和macOS版Brim的详细安装说明https://github.com/brimsec/brim/wiki/InstallationBrim的安装需要后端ZQD和ZQD守护进程提供一个restapi来管理和查询日志存档。Brim的Python库连接到ZQD以发送查询和获取数据。
Anacondaand Jupyter
Jupyter Notebook(https://jupyter.org/)是一个开源的web应用程序,允许创建和共享包含实时代码、公式、可视化和叙述性文本的文档。这里建议安装Anaconda(https://www.anaconda.com/),一个开源的包括Jupyter Notebook以及其他一些有用的应用程序和工具的数据科学平台。
Python模块
Brim Python库目前处于开放测试阶段,可以通过“pip”安装:pip3 install 'git+https://github.com/brimsec/zq#subdirectory=python/zqd'Pandas是一个开源的BSD许可的库,为Python编程语言提供高性能、易用的数据结构和数据分析工具。可以通过pip安装:通过以下链接获取更多信息:https://pandas.pydata.org/pandas-docs/stable/getting_started/install.htmlMatplotlib库(https://matplotlib.org/)用于可视化数据,NetworkX使用它绘制和绘制图形。可以通过“pip”安装:使用NetworkX作为网络图库。NetworkX(https://networkx.org/)是一个Python包,用于创建、操作和研究复杂网络的结构、动态和功能。可以从命令行通过“pip”安装它:有关安装的详细信息,请参阅:https://networkx.org/documentation/stable/install.html其中TZG文件来自https://github.com/brimsec/zq-sample-data/tree/master/tzng。另外是我们在“Hunting Emotet with Brim and Zeek”文章使用的来自恶意软件流量分析网络的Emotet恶意软件示例:https://www.malware-traffic-analysis.net/2020/09/02/2020-09-01-Emotet-epoch-3-infection-with-Trickbot-gtag-mor119.pcap.zip(password: infected)0x02 通过Brim将Zeek数据输入Pandas!
注:下一节使用随附的JupyterNotebook:https://gisthub.com/orochford/4489198fd4d94b772fb8a0da8be3c315首先确保Brim和ZQD已经启动。如果Brim没有运行,需启动它,ZQD将在后台自动启动。然后将示例数据导入Brim,把示例文件拖放到UX中,一个新空间就会被创建。
0x03 连接Jupyter和ZQD
注:可以按照随附的JupyterNotebook中教程中代码进行操作。 继续使用一个新的JupyterNotebook连接到ZQD,发送一个ZQL查询后将返回的数据放入Pandas的DataFrame:
1、为要查询的边空间定义一个变量“space”,在本例中为“2020–09–01-Emotet-epoch-3-infliction-with-Trickbot-gtag-mor119.pcap”。空间将共享导入的示例文件的名称2、定义要发送到ZQD的ZQL查询(变量'ZQL')zql = '_path=conn | cut id.orig_h,id.resp_h, proto | sort id.orig_h, id.resp_h'
4、最后,从返回的数据创建一个pandas DataFrame“df”,将任何json或dictionary的值平化。0x04 验证数据
既然已经将数据导入到PandasDataFrame中,应该进行一些验证以确保一切都按预期进行。
如果一切都按照计划进行,那么现在应该看到许多不同的度量和特征,包括DataFrame包含多少条记录、列和数据类型。然后,我们还需检查是否存在缺少数据的字段,如果有就删除它们。
注:有更好的方法来管理丢失的数据,但目前我们并不需要,就我们的目的而言,目前已经足够了。0x05 绘制我第一个网络图
你可能已经注意到, ZQL查询没有返回定量值,例如每个连接发送的字节数。在以后的文章中,我们还将讨论如何使用Pandas来分析这些指标。但今天,重点是使用连接数据创建网络模型。为此,使用NetworkX创建一个网络图。NetworkX是一个网络图库,支持网络图的生成、创建、操作和可视化。网络图对于建模和分析表示流、关系或连接的数据非常有用,在分析社交网络、电子邮件通信或前述示例中的网络数据时特别有用。现在,数据的格式可以用来生成IP连接的网络图了。网络图通过节点和边来展示全部,一个节点就是一个主机,一个边就是两个主机之间的连接,也可以用描述它们的数据来修饰边。在示例中,我们将区分TCP、UDP和ICMP流量。因为ZQL查询已经用可以直接使用的格式返回数据,所以这里可以使用networkX“from_pandas_edgelist()”函数。
networkx.from_pandas_edgelist()要求输入源节点和目标节点及任何其他属性。在示例中,设置“edge_att=True”意味着Pandas DataFrame中任何附加值都将作为边属性添加。
注:NetworkX支持4种不同类型复杂网络的基本图形类型(参见https://networkstable/documentation/https/documentation/documentation/)。为了达到我们的目的,需要使用一种叫做有向图的方法来绘制出连接的方向。刚刚创建的图表:

可以看到许多节点(主机)有所谓的“度”的倍数。度是两台主机之间的IP连接的网络图等价物,G.degree()会打印出每个节点的列表以及它有多少条边,给出唯一IP连接的总数。请注意这些值是如何正确键入的-这是由于Brim的ZNG数据格式的嵌入数据类型造成的。
0x06 将网络图可视化
现在已经创建了网络图,可以使用NetworkX的默认设置将其可视化。这个很好的小数据集,虽然不漂亮,但可以清楚地看到从两个中心节点发出的连接。
虽然代码现在可以很好地处理较小的数据集,但是结果却非常难看。一切似乎都过于拥挤,很难分辨出标签和关系。更糟糕的是,如果使用更大的数据集,例如“tzng”样本数据有更多的节点和边,我们会得到数据科学家亲切地称之为“模糊毛球”。
设置一个值作为NetworkX在用例中可以合理地可视化的上限,并根据这个值检查DataFrame中的记录数。设置一个值作为样本大小,以防超出限制。然后,使用样本大小随机抽取Pandas样本。如果重新运行Notebook,每次都会看到不同的星座图,但是如果样本具有代表性,那么高离群值应该会频繁出现。
注:我们还可以使用ZQL的“head”处理器来限制从ZQD获取的记录的数量。这将限制我们必须在内存中使用的数据量,但以随机抽样为代价。使用Panda的sample()函数,可以提供一个真正的随机样本进行分析。由于NetworkX主要不是一个可视化库,它更适合于较小或不太复杂的可视化。如果需要对绘图进行更多处理,NetworkX支持GrapViz输出,以实现更大的提升。通过figure的“figsize”参数来调整networkx图的输出大小。参数需要宽度和高度的值(以英寸为单位)。plt.figure(figsize=(Width x Height))绘制一个更大的图形将在可视化中加入更多的节点和边,但目前不知道数据包含多少节点和边,所以需要一个更动态的方法。
因为已经在检查样本有多少条记录,所以添加一些逻辑来返回一个大小用来设置图形大小,还可以根据图形的记录数应用特定的样式。
3、应用样式
最后,为使可视化更易于阅读,也为了帮助可视化流和协议组成,在图中添加一些样式。
首先,添加一些代码来创建基于IP协议的不同边列表(tcp_列表、udp_列表和icmp_列表)。用特定的样式来清楚地可视化不同的IP协议。
根据前面确定的图形大小设置绘图图形大小,并应用调整后的样式选项来调整这些选项以获得更好的易读性。使用多个布局同时绘制图形,而不仅仅使用Spring布局。
使用FOR循环遍历布局,为每个布局绘制一个子图。而且,和上次一样不用标准networkx.draw_networkx()函数,一点一点地绘制网络图以便更好地控制所绘制的内容。
可以看到,不硬编码样式属性,而使用前面设置的样式变量,不仅可以更好地控制图形的可视化方式,还可以使代码更易于阅读和维护。注:有关图形绘制参数及其含义的详细信息,参见:https://networkx.org/documentation/stable//reference/drawing.html一组一组地绘制边能够对每种边类型应用非常精细的样式,使用前面基于“proto”列创建的列表来确定样式应该应用于哪些边。最后,为了绘制节点,使用网络图函数(G.degree).values(),来动态更改绘制节点的大小。G.degree()提供与所有节点相邻的边数,或者用另一种方式表示与特定节点的连接量。用它作为一个乘数(本质上作为一个权重),根据到它的连接数绘制一个更大的节点。当绘制可视化图时,我们看到的是一幅完全不同的画面。连接是用颜色编码和IP协议标记的,如果节点拥有很多连接,它们看起来会更大,还可以看到连接的方向,用箭头表示。由于美学是主观的,你可以多试试直到找到一个你觉得有吸引力的造型。
0x07 结论
希望这给您一个很好的起点,让您可以使用Brim、Pandas和NetworkX来探索Zeek数据,并对下一步的发展方向有一些想法。本文由金睛安全研究团队整理并翻译,不代表金睛安全研究团队任何观点和立场来源:https://medium.com/brim-securitys-knowledge-funnel/visualizing-ip-traffic-with-brim-zeek-and-networkx-3844a4c25a2f