导语:在本系列文章的第一篇博文中,我将介绍 Jupyter Notebook 的基本工作原理,如何创建你的第一个notebook ,以及如何在 Python 中运行一些初始的基本命令。
当涉及到威胁检测,有多少次你听到有人说: “答案就在我的头脑中,如果你有任何问题,只问我就够了! ” 或者“只有 TA 或者他们知道怎么做! ” ,像这样的情况有很多次,不是吗? 没有对如何分析数据以检测网络中潜在的入侵的过程作记录、标准化或与人分享的问题要比你想象的更常见,特别是从技术和专业知识的角度来看当团队变得非常多样化的时候。 它不仅会影响你的检测策略,还会影响你的团队的动态。
现在,有多少次你想过用一种更有效、更直观或更有创造性的方法来分析你的组织收集的安全事件,但是你会因为只能使用一个语言相关的搜索栏而感到有局限性?
这篇文章是本系列文章的一部分,这个系列文章将介绍如何利用 Jupyter Notebook 以一种更加动态、灵活和不涉及语言的方式来分析安全事件,同时帮助你的团队记录、标准化和分享用于检测威胁的Jupyter Notebook 文件。 你可以将其与 ThreatHunter-Playbook 之类的项目集成在一起,然后免费进行部署,并且可以不限时间的使用 HELK 之类的开源项目。
在本系列文章的第一篇博文中,我将介绍 Jupyter Notebook 的基本工作原理,如何创建你的第一个notebook ,以及如何在 Python 中运行一些初始的基本命令。
其余四部分可在以下连结找到:
· 用Jupyter Notebook 进行威胁狩猎——第二部分: Pandas 数据分析基础
· 用Jupyter Notebook 进行威胁狩猎——第三部分: 利用 Apache Spark 查询 Elasticsearch
· 用Jupyter Notebook 进行威胁狩猎——第四部分: 通过 Apache SparkSQL 实现 SQL JOIN
· 用Jupyter Notebook 进行威胁狩猎——第五部分: 记录、分享和运行威胁狩猎
什么是 Notebook?
你可以把 notebook 想象成一个文档,你可以通过 Web 界面访问这个文档,这个 Web 界面允许你保存交互式会话的输入(即实时代码)和输出(即代码执行结果 / 评估代码输出) ,以及解释执行特定任务(即数据分析)的方法和步骤所需的重要说明。
什么是 Jupyter Notebook?
Jupyter Notebook 是一个开源的 Web 应用程序,允许你创建和分享包含实时代码、方程式、可视化和叙述文本的文档。 用途包括: 数据清理和转换,数值模拟,统计建模,数据可视化,机器学习,等等。
Jupyter Notebook 项目是 IPython Notebook 库的演变,开发这个库的主要目的是为了通过可共享的 Web 文档实现科学操作和高级数据分析功能,从而增强默认的 python 交互控制台。
如今,Jupyter Notebook 项目不仅支持 Python,还支持40多种编程语言,如 R、 Julia、 Scala 和 PySpark。 事实上,它的名字最初来源于三种编程语言: Julia、 Python 和 R,这使它成为第一个与语言无关的 notebook 应用程序,现在被认为是社区中数据科学家和工程师探索和分析数据最喜欢的环境之一。
“Jupyter Notebook”是如何工作的?
Jupyter Notebook 使用基于内核–客户端基础结构的所谓双进程模型。这个模型将一个类似的概念应用于 Read-Evaluate-Print Loop (REPL) 编程环境,该环境接受单个用户的输入,然后计算输入,并将结果返回给用户。
基于双进程模式的概念,我们可以从以下方面解释 Jupyter 的主要组成部分:
Jupyter 客户端
· 它允许用户将代码以Qt 控制台 或者通过浏览器的 notebook文件的形式将代码发送到内核。
· 从 REPL 的角度来看,客户端执行read 和 print 操作。
· 由一个 Jupyter Web 服务器托管,该服务器使用Tornado 处理 HTTP 请求。
Jupyter 内核
· 内核接收客户端发送的代码并执行代码以及将结果返回给客户端显示。 一个内核进程可以有多个客户端与其通信,这就是为什么该模型也被称为解耦的双进程模型。
· 从 REPL 的角度来看,内核执行evaluate 操作。
· 内核和客户端通过基于 ZeroMQ (底层传输层)和 WebSocket(基于 TCP)的异步消息处理库的交互式计算协议进行通信。
Jupyter Notebook 文件
· Notebook 可以自动保存和存储在磁盘上,采用开放源码的 JavaScript Object Notation文件(JSON)格式保存,文件的后缀名称是 .ipynb。
Jupyter Lab
· 这是下一代基于 Web 用户界面的 Jupyter 项目。
· JupyterLab 最终将取代经典的 Jupyter Notebook。
· 我们将在整个系列文章中使用 Jupyter Lab 扩展。
安装 Jupyter
我敢肯定此刻你一定想急于安装 Jupyter 并开始探索它的功能,但首先你必须决定你是想直接在你的系统上安装 Jupyter Notebook 服务器,还是在虚拟机或 docker 容器上托管它。
我相信给你这些选项是很重要的,这样你就可以随心所欲地运行这个工具。 如果你希望直接在系统上进行经典式的安装,请参阅官方的 Jupyter 安装文档。
通过 Docker 运行 Jupyter
对于本系列文章,我们将使用 HELK 项目。 我更喜欢通过 docker 镜像共享一个标准化的工作环境,以便更多地关注应用程序的功能,而不是花时间对服务器安装进行故障排除。
安装要求
初始化步骤
· 克隆最新版本的 HELK 代码仓库,将你的工作目录改为 HELK/docker 然后运行通过sudo 执行 helk_install.sh 脚本
git clone https://github.com/Cyb3rWard0g/HELK.git cd HELK/docker sudo ./helk_install.sh
· 对于本系列文章,我们将使用带有基础许可证的选项3 进行安装。
· 一旦脚本运行完成(大约5-10分钟) ,你将看到类似的输出:
· 打开上面的 HELK JUPYTER SERVER URL
· 你可能会得到一个Privacy Error 页面。忽略掉它,点击 Advanced 然后点击 Proceed。
· 复制显示在你的控制台中的JUPYTER CURRENT TOKEN 的值然后将这个 token 粘贴到页面的密码框中然后点击Log in。
你可以进入 Jupyter Lab 的主菜单。
· 正如你可以在上面的图片中看到的,有一个名为datasets的目录。里面默认包含了一个Mordor 数据集 ,这个数据集我们将会在下一篇文章中用到。我们将在下一篇文章中使用的数据集。 此外,还有一些 notebook 可供你使用。 我制作所有这些 notebook 的目的是为了让你们熟悉我将要分享的概念。
探索 Jupyter 的主界面
文件浏览器部分
· 这一部分显示的是可用的对象,例如可供你使用的文件夹或文件。 你可以通过右键单击对象 重命名 , 移动 , 下载, 或删除 任何文件夹或文件。
· 你还可以上传本地系统中存在的文件,方法是单击Upload 图标,如下图所示。
· 此外,还可以创建新对象,如Notebooks,文本文件,甚至运行 bash 终端。
· 你也可以从启动器部分(Launcher)完成,如下图所示:
· 如上图所示,我们的Jupyter 服务器有四个内核可用: Python 3, PySpark, R, and Syplon。
· 默认情况下,Jupyter 使用的是Python 3 (IPython) 内核。Jupyter 团队维护了IPython 内核 ,因为 Jupyter notebook 服务器依赖于 IPython 内核功能。 除了 Python 之外,notebook 中还可以使用许多其他语言。 这就是我所说的与语言无关的方法。 如果你想了解更多关于其他内核的信息,你可以点击这里阅读。
运行终端和内核部分
· 这一部分提供有关当前运行的 Jupyter 进程的信息。 当你创建一个notebook 或启动一个终端会话时,你将能够在这里跟踪这些进程。
命令部分
· 这一部分提供有关可用于与文件、新控制台交互的几个命令的信息。如: 内核等。
你的第一个 Notebook
现在,让我们创建我们的第一个notebook ,并熟悉其他选项。
· 返回到 启动器(Launcher) 部分,单击要用来初始化新notebook 的特定内核。这里我们选择 Python 3。
· 你会看到一个基本的 notebook Web 界面和命名为Untitled 的最初的 notebook以及 一个input(In) 单元格,你可以添加代码到 Python 3 内核中,然后执行代码。
· 你还将看到一个后缀为ipynb名称为untitled 的文件。notebook 会自动进行保存。
· 你可以通过点击文件浏览器的图标来最小化文件浏览器部分。
· 你可以通过右键点击 notebook 的标题然后点击 Rename Notebook重命名你的notebook。
· 如果你检查 Jupyter 内核会话,你将看到你的 notebook 正在运行,并带有关闭内核的选项。
探索 Notebook 界面
在notebook 界面中有几个可用的选项,其中大多数选项的含义都非常简单明了,工作方式类似于你在常规文档工具栏中获得的工具,你可以保存、打开或关闭文件。 然而,有一些选择和概念非常有必要重点理解:
Cell 环境
· Cell 环境的一个主要部分是input cell container ,你可以在其中输入代码(即 Python)或文本(即 Markdown) ,以供内核计算和执行。
· 在input cell 左边有一个input label。这个是通过一系列数字来跟踪代码的执行,默认从[1]开始计数。如果还没有运行任何程序,它将显示空括号[ ]。如果内核正在运行代码,这里的空括号[]里面会显示一个星号*也就是[*]。
· 你可以通过页面中的工具栏保存 notebook 的内容,添加新单元格(➕) ,剪切 / 删除单元格(✂) ,复制单元格和粘贴单元格。
· 你可以通过选择input cell container 然后点击run cell button 运行代码。你也可以选中一个单元格通过SHIFT +回车键运行代码。
· 你可以通过code 下拉按钮选择你要是有的输入类型。目前有三种单元格输入类型,code 输入类型允许用户在内核中定义的特定编程语言中运行代码。 在这种情况下,编程语言是 Python 3。
你也可以通过 Run 选项卡访问更多选项,如下图所示:
内核环境
· 你可以通过Kernel 标签访问内核选项。
我想运行一些代码
现在我们了解了如何与 Jupyter notebook 接口交互,接下来让我们在input cell container 中运行一些基本的 python 代码。
输入一个基本的 python PRINT 语句,然后按下SHIFT + 回车键运行单元格代码。
print("Hola World!!")
· 现在尝试运行一个FOR 循环 ,这个循环通过RANGE生成 5 个数字的序列。
for x in range(5): print(x)
· 将 cell type 切换为一个新的输入类型 ——Markdown ,输入一些 Markdown 文本。
· 复制,粘贴,并运行下面的Markdown 文本:
# Threat Detection ## Data Analysis ### Data Sources #### Process Monitoring PowerShell Execution
· 使用 SHIFT + UP 键选择所有当前单元格然后删除它们。
· 通过在某个单元格上创建一个变量,在从另一个单元格调用变量之前需要先运行该变量,使变量在多个输入单元格之间可用。
dog_name = 'Pedro' print(dog_name + " is my best friend!")
标准 python shell 中的一个有用特性是 tab 补全。
· 你可以键入变量的第一个字母dog_name 然后在你的键盘上按下tab 键。这将在命名空间中搜索与你输入的字母相匹配的任何变量。
dog_<tab>
· 你还可以将对象中可用的方法或属性进行tab补全。
· 让我们定义一个包含关于我的狗的元素列表,并将它保存在一个变量中。
dog_list = ['pedro, 4, 2015]
· 然后你可以在输入dog_list 后,再输入一个句点符号然后按下 tab 键看看你可以使用哪些方法来处理这个列表。例如,你可以选择 append 在列表中附加新的元素。
· 你也可以对模块执行相同的操作。现在我们导入 random 模块然后通过 tab 补全查看模块内部可用的方法或函数。
· tab 补全功能也适用于补全文件路径。我们可以在datasets文件夹中测试这个功能。
另一个很酷的特性是 Introspection,可以用于获取关于对象的信息(例如列表、函数等)。 你可以在对象之前或之后简单地输入一个问号(?)即可。
· 让我们用它来处理变量 dog_list。
· 那么函数呢? 让我们用print 函数做个测试。输入一个问号(?)来打印这个函数的docstring 。
这很简单,不是吗? 如果这是你第一次使用“Jupyter notebook ” ,我希望这能帮助你熟悉一些基本的概念,加快你的第一个“Jupyter notebook ”环境的部署!
如果你想再次获得 Jupyter 令牌,你可以使用以下方法:
sudo docker exec -ti helk-jupyter jupyter notebook list | grep "token" | sed 's/.*token=\([^ ]*\).*/\1/'
在下一篇文章中,我们将使用 HELK jupyter 容器中的一些可用的 notebook ,通过一个名为 Pandas 的 python 库学习更多关于安全事件日志的数据分析。
Pandas 基础数据分析
在上文中,我介绍了 Jupyter Notebook 的基本概念,并向你展示了如何部署一个基本的notebook环境。 现在,我们准备开始运行更多的 Python 代码,并开始向你展示如何灵活和动态地使用notebook来分析安全事件。
在下文中,我将向你展示如何在一个名为 Pandas 的 python 库的帮助下,以 JSON 格式读取和分析安全日志文件。
要求
· 本文假设你已经阅读了前一篇文章,并按照特定的指示部署了 HELK 项目。
· 基本的 Python 编程技能和对 Python Numpy 数组的基本理解。 如果你是 python 数据结构、控制流、循环、函数、模块和 NumPy 数组方面的新手,或者是你想刷新一下你对这些知识的记忆,我为你准备了两个简短的 notebook,作为对这些知识的介绍。 打开01-intro-to-python.ipynb 和 02-intro-to-numpy-arrays.ipynb就可以开始学习了。
尽管如此,我还是想直接跳到事件日志的分析部分,我相信理解 Pandas 背后的基本概念是很重要的。
什么是 Pandas?
Pandas 是一个 Python 包,提供了快速、灵活和富于表达能力的数据结构,旨在使处理“关系型”或“标记型”数据变得既简单又直观。 它旨在成为用 Python 进行实际的、现实世界的数据分析的基本高级构建块。
Pandas 数据对象严重依赖高性能 NumPy 数组,并提供典型的电子表格和关系型数据库(如 SQL)的灵活的数据操作能力。
什么是 Numpy?
· Numpy 是“Numerical Python”的缩写,它是用于科学计算的基本 Python 包
· 它使用一种高性能的数据结构,称为 n维数组或 ndarray,这是一种多维数组对象,用于高效地计算数组和矩阵。
什么是数组?
· Python 数组是类似于列表存储数据的数据结构,只是其中存储的对象类型受到了限制。 数组的元素都具有相同的类型,并由一组正整数进行索引。
· Python 的 array 模块 允许你在创建对象时通过使用类型代码(单个字符)指定数组的类型。
NumPy N维数组(ndarray)
· Numpy 数组是一个高效的多维数组,提供快速的面向数组的算术运算。
· 与任何其他 Python 数组一样,它是相同类型元素的容器。
· 与 Python 中的其他容器对象一样,你可以通过索引或切片操作访问和修改 ndarray 的内容。
· Numpy 数组处理向量化操作,存储效率比其他 Python 内置的数据结构更高。
· 如果我们尝试向列表中的每个元素添加一个数字,你必须执行一个循环,以便对每个元素应用基本的加法。
· 如果对 NumPy 数组执行相同的操作,则只需要向数组对象添加一个数字,并将其应用于数组的每个元素。
Pandas 和 NumPy 数组
Pandas 利用并扩展了 NumPy 中的几个基于数组的功能,并提供了一种更具表现力的表示数据和操作数据的方法。 Pandas 中的两个主要数据结构是:
· Series(序列)
· DataFrames
Pandas 的 Series
· Pandas 的 Series 是一个一维的带标签的索引数组,可以存储任何数据类型,如整数、浮点数和字符串。
· 可以通过传递 NumPy 的 ndarray 来创建和初始化 Series。
· 正如你在上面看到的,索引在左边,值在右边。 我们没有为数据指定索引; 因此, Pandas默认从0开始创建索引。
Pandas 的 DataFrames
· Datatrame 是一个二维表,用于以表格格式表示数据。
· 可以将 DataFrame 看作是一个包含列标题和行的表格。
· Dataframe 同时具有行索引和列索引。
· Pandas 依赖 NumPy 数据类型来输入 DataFrames 中的数值。 例如,我们可以使用以下命令打印单个条目的数据类型,例如,我们可以使用 iloc 查看 age 列上的第一个值的数据类型,我们可以看到它是 NumPy 类型。
现在我们已经了解了 Pandas 的基础知识及其数据结构,我们可以开始使用 DataFrames 以表格格式处理安全事件日志。
基本的事件日志分析
让我们创建一个新的notebook,探索魔多数据集,不断丰富、可视化这个数据集并筛选出有趣的事件。 这个notebook的解决方案被命名为basic_event_log_analysis_pandas ,对你是可用的。 我建议你重新创建它,并按照下面的步骤进行操作,这样你就可以得到一些亲自的实践体验。
创建一个新的notebook
导入库
import pandas as pd from pandas.io.json import json_normalize import json import matplotlib.pyplot as plt
读取魔多数据集
· 我们接下来要读取的是魔多的小数据集——empire_invoke_wmi
· 我们可以用 read_json 这个方法read_json 将 Mordor JSON 文件转换为 DataFrame。lines 参数设置为了 True ,目的是将文件作为 json 对象进行每行读取。
invoke_wmi_df = pd.read_json('datasets/empire_invoke_wmi_2019-05-18214442.json', lines=True)
探索数据
· 接下来,我们可以使用shape 以返回表示 DataFrame 维度的元组。 数据包含 5271 行和23 列。
· 此外,我们可以使用iloc 选择 DataFrame 中的第一条记录。 在这一步中,我们了解了 DataFrame 中的模式。 请记住,我们的数据集包含不同的数据源。 因此,我希望模式对每个记录或审计类别进行大量更改。
嵌套列处理
· 在前面的图片中,我们可以看到数据集中的一些嵌套字段。 因此,我们可以使用json_normalize 帮我们压平那些列。
· 首先,我使用to_json方法将DataFrame转换为 JSON。
· 接下来,将结果作为 json 结构加载,然后通过json_normalize 函数获得一个 DataFrame 。
json_struct = json.loads(invoke_wmi_df.to_json(orient="records")) invoke_wmi_flat = json_normalize(json_struct)
识别可用的数据源
· 你可以用pandas的groupby 方法使用source_name 字段对 DataFrame 进行分组。 我这样做是为了了解更多关于可用数据源的信息。
invoke_wmi_flat.groupby(['source_name']).size()
筛选 Sysmon 事件
· 现在,我们可以开始通过特定的数据源筛选我们的 DataFrame。
· 我决定只筛选 Microsoft-Windows-Sysmon 事件。
· 正如你在下面看到的,还有一些字段的值是NaN 。这是因为 Sysmon 的每个事件的数据模式并不是相同的。
sysmon_filter = invoke_wmi_flat['source_name'] == "Microsoft-Windows-Sysmon" sysmon_df = invoke_wmi_flat[sysmon_filter]
筛选 Sysmon 进程创建事件(EID 1)
· 现在我们有了一个 Sysmon DataFrame,我们可以根据特定的事件 id 筛选这些事件。 让我们通过传递event_id == 1 筛选一下。
sysmon_filter2 = sysmon_df['event_id'] == 1 sysmon_proc_create = sysmon_df[sysmon_filter2]
在 ProcessCreate Dataframe 上删除空字段
· 在对一个特定事件筛选 Sysmon DataFrame 之后,我们需要删除值为 NaN 的空字段。属于相同事件类型(事件 id)的所有记录都应该具有相同的模式,这样就可以很容易地筛选出不属于ProcessCreate 模式的数据。
· 你可以通过以下方法了解关于模式的更多信息OSSEM Sysmon Event Id 1
sysmon_proc_create = sysmon_proc_create.dropna(axis = 1, how = 'all')
按特定字段分组事件
· 让我们一起探索我们的ProcessCreate 事件,并将这个事件的数据按照ParentImage分组。
· 根据数据集的含义,该文件包含的是攻击者利用 WMI 进行横向移动,以便在目标机器上产生一个新代理的行为数据。 因此,我决定分析ParentImage 列的数据值,目的是为了了解在端点上执行的父进程的更多信息。
sysmon_proc_create.groupby(['event_data.ParentImage']).size()
丰富数据
· 我们可以采取的一个基本步骤是丰富当前的事件
· 我们可以向我们的 DataFrame 添加一个新字段,并将该字段的值设置为每条记录的字符总数的结果,然后我们可以使用这个新字段来寻找潜在的异常值
sysmon_proc_create['command_count'] = sysmon_proc_create['event_data.CommandLine'].str.len()
可视化数据
· 我们可以从每条记录中提取新字段的值,并用一个基本的柱状图将数据可视化。
· 我们可以看到与网络流量中的其他进程相比 C:\Windows\System32\Wbem\WmiPrvSE.exe 的CommandLine 参数执行了大量字符的操作。
sysmon_proc_create.plot(kind='bar',x='event_data.ParentImage',y='command_count')
筛选有趣的事件
· 我们可以更深入地了解在 CommandLine 参数中执行的子进程的信息。
· 接下来,我们可以选取子进程的 ProcessGuid 进行分析。
sysmon_filter3 = sysmon_proc_create['event_data.ParentImage'] == "C:\Windows\System32\wbem\WmiPrvSE.exe" sysmon_proc_create[sysmon_filter3]['event_data.ProcessGuid']
显示结果
· 我们可以用 Pandas 的 option_context 管理器来增加我们的结果列的宽度,以便看到较长的CommandLine 参数。
· 通过分析,我们可能已经找到了我们的对手。
with pd.option_context('display.max_colwidth', 2000): print(sysmon_proc_create[sysmon_filter4]['event_data.CommandLine'])
我希望这篇文章对那些刚刚开始使用 Jupyter notebook的人有所帮助。 另外,我希望这能激发你使用 DataFrames 来表示和分析安全事件日志的兴趣。
如果你想深入研究 Pandas 提供的一些附加功能,可以运行可用的03-intro-to-Pandas notebook。 如果你想运行在这篇文章中提出的每一个步骤,并比较你的结果,你也可以运行basic_event_log_analysis_pandas notebook。
在下一篇文章中,我们将继续以表格格式分析安全事件日志,但是我们会直接从数据库中读取,而不是从离线的 JSON 文件中读取。 我们仍然会使用相同的魔多数据集,但我会对数据进行实时分析,然后进行规范化处理并存储在一个 Elasticsearch 数据库。 然后,我将向你展示如何通过 Apache Spark 连接到 Elasticsearch 数据库,进行可扩展的并行数据处理。
参考资料
https://jupyter4edu.github.io/jupyter-edu-book/
https://jupyter.readthedocs.io/en/latest/architecture/how_jupyter_ipython_work.html
https://ipython-books.github.io/chapter-3-mastering-the-jupyter-notebook/
https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop
https://en.wikipedia.org/wiki/read%e2%80%93eval%e2
https://jupyterlab.readthedocs.io/en/stable/getting_started/overview.html#overview
https://github.com/pandas-dev/pandas
https://medium.com/@ericvanrees/pandas-series-objects-and-numpy-arrays-15dfe05919d7
https://github.com/Cyb3rWard0g/OSSEM
https://github.com/Cyb3rWard0g/mordor
https://pandas.pydata.org/pandas-docs/stable/index.html
本文翻译自:https://posts.specterops.io/threat-hunting-with-jupyter-notebooks-part-1-your-first-notebook-9a99a781fde7如若转载,请注明原文地址: https://www.4hou.com/system/20816.html