▼ 关注「Apache Flink」,获取更多技术干货 ▼
摘要:本文整理自奇安信集团高级技术专家覃永靖在 Flink Forward Asia 2021 行业实践专场的分享。本篇内容主要分为四个部分:
什么是安全分析
计算框架的选择
引擎设计
实践与展望
Tips:点击「阅读原文」查看原文视频 & 演讲PDF~
一、什么是安全分析
近 10 年来,大数据技术发展日新月异。安全分析场景和方法也更新换代。目前,常用的安全分析流程大概分为三个流程:
日志采集解析。通过各种方法,从服务器、网关设备、终端、数据库或其它数据源采集各种流量日志、威胁日志、运行日志,和终端日志等数据;
实时安全分析。分析过程主要有安全基线、关联分析、安全规则、威胁情报,和安全知识库;
安全运营和态势感知。这个流程基于安全分析的结果来实现态势可视化、安全运营、多设备安全联动、安全编排等能力。
如上图所示,安全领域主要有三个特点:
快速响应。因为安全事件经常是突发的,比如漏洞的披露、病毒的爆发等常常是在很短的时间突然发生,所以需要以非常有效和简单易用的方式来快速地对突发的安全事件进行处理,能第一时间响应客户的需求、应对各类安全事件;
场景定制。因为安全分析和常规的大数据分析场景会有一些不同,安全分析检测的是异常而不是正常,还有领域独有的一些需求,所以这里会涉及到很多领域定制开发的需求。
资源受限。相比常规互联网大数据平台使用方式,安全分析可使用的资源会有很多的限制,通常用户受限于预算和资源的限制,会尽可能地压缩和优化可用计算和存储资源规模,这会导致大量的组件采用混合部署的方式,且将来硬件和集群扩展成本也很高,流程很长。
在实时数据安全方面,一共有五点需求:
第一是需要实时分析。安全检测对时延要求严格,攻防双方抢时间差,需要能第一时间检测到异常。同时由于是安全事件驱动,要求解决方案上线快,响应及时,能在最短时间形成防护能力;
第二是需要提供非常丰富的分析语义。安全检测的场景通常比较复杂的,需要提供丰富的安全分析语义,覆盖大部分安全分析场景;
第三个是能灵活部署。因为客户的环境非常复杂,需要能支持各种大数据平台,比如客户自建的,或者是他购买的一些云平台,并且还要有最大的版本兼容性;
第四是需要实现最小的资源使用。支持部署从一到几十甚至上百台节点的集群,在资源占用尽可能小的同时支持大规模,比如上千条分析规则或安全基线同时运行;
最后是运行稳定。安全产品部署在客户侧,需要 7×24 小时不间断运行,需要提供极高的运行稳定性,尽可能减少人工维护和介入,让客户无感知。
传统的安全分析方法一般是基于先验知识,采用基于特征检测技术来进行异常检测,一般是通过分析检测对象的数据或日志特点,然后人工归纳和统计出可检测特征,建立安全模型,比如安全规则、威胁情报等。这种方式比较简单和可靠,可以很好的应对已有的攻击方法,但是它对未知的没有对应检测特征的攻击方法则不能有效的进行检测。
安全基线采用基于行为的检测方法,使用检测对象数据和日志,采用各种方法学习出行为特征,建立安全基线,并用于异常检测。
为了让大家能更好的理解安全基线的使用场景,这里列了三个真实场景:
场景一,DBA 用户账号登录异常。比如登录位置异常,登录时间异常,使用数据库的行为异常等。比如一个 DBA 用户,通常是在某些时间、某些 IP 或是某些地点登录,但是某天突然在另外一个地方登录了,且时间也不是通常登录时间,那这可能就是一个异常,需要生成异常事件;
场景二,邮件发送附件数量超过常规值。比如安全基线学习部门或者整个公司发送邮件的行为数据,发现某一个用户发送附件的数量和历史学习数据有较大出入,那这可能是一个异常;
场景三,最近账号登录 VPN 服务的次数异常。通过学习用户账号 VPN 历史登录行为,构建安全基线,如果将来发现账号登录异常,则产生异常事件。
二、计算框架的选择
目前主流实时计算框架主要有两个,Spark 和 Flink。我们当初设计这个引擎是在 2018 年左右,当时我们研究了 Storm、Spark、Flink 这三个计算框架,综合各方面因素最终选择了 Flink 作为底层计算框架。当时使用的 Flink 是 1.4 版本左右,是一个比较成熟的版本,相比其它框架,它的 API 以及它的底层分布式和流计算实现方式比较符合我们的使用场景。
Flink 的优势点比较突出,它是分布式计算框架,部署灵活,适配目前常见大数据平台。它拥有很好的处理性能,能达到高吞吐低延迟,这非常适合进行实时安全分析。它还提供灵活的 DataStreaming API,方便实现定制化需求。另外,还支持简单易用的检查点和保存点机制。并且,作为目前非常热门的计算框架,社区活跃,有丰富的文档和场景样例。
虽然Flink有很多优势,但当企业资源受限,规则集数量上千规模的情况下。Flink 在满足业务及性能需求上遇到了很多问题。比如无大规模规则语义/流优化,缺乏安全场景定制窗口和逻辑,无安全基线相关算子以及无资源保护机制等。
三、引擎设计
引擎应用框架分为三层:
底层是部署层,通常是一个大数据集群;
第二层是安全分析层,基于 Flink DataStreaming API 来构建安全基线引擎,Flink 负责底层的分布式计算和事件流发送,具体的业务计算由安全基线引擎来完成。安全基线引擎向用户提供的使用接口为规则和 DSL,用户通过界面来下发规则 DSL 给引擎,引擎根据规则和 DSL 来对事件流进行分析和计算,同时根据规则语义使用外部的数据,比如知识数据、威胁情报、资产和漏洞等;
用户通过第三层的应用层来管理和使用引擎。并基于引擎数据结果态势分析,安全运营,资源监控等具体安全业务。
引擎的业务流程分为三块,即用户界面,引擎服务和引擎分析任务。用户通过用户界面来进行规则配置、基线管理和运行监控。引擎服务以 RESTfull API 的方式向用户提供规则下发、基线下发、状态监控等服务。引擎服务在接收到用户的规则下发请求后需要对下发的规则集进行解析、优化之后生成分析任务代码包,分析任务代码提交大数据集群运行,分析任务在运行过程中接收引擎服务的基线发下数据,对运行时基线进行增删改操作。分析任务还向引擎服务报告任务运行状态,引擎服务将任务运行状态映射成业务监控信息,提供给用户查询和分析使用
由于大部分用户不是研发人员,所以需要提供一种针对安全分析场景,进行特定优化的安全分析语言。它需要具备以下几点:
简单易用,学习成本低,易上手,一个没有研发背景的人也能经过简单学习之后就能上手使用,且符合安全分析人员的直觉思维;
需要提供丰富的数据类型,首先要提供丰富的基础数据类型,其次是安全分析常用的数据比如 IP,各类时间、资产、漏洞、威胁情报、地理位置等提供直接支持,使用者可以不做任何定制就能直接使用各类数据;
提供丰富的语义,尤其对安全分析语义进行增强和定制;
支持扩展,虽然提供的安全分析语义比较全面,支持大部分安全分析场景,但还是会遇到一些无法直接支持的特殊场景,此时就需要以扩展的方式来支持这类需求。
安全分析语言需要设计一个专门的编译器来对安全分析人员设计的安全分析语句和规则进行编译和优化。编译器需要提供一些特性和优化的支持:
公共表达式优化。对分析语句中相同语义逻辑进行优化,降低重复计算和计算复杂度;
引用数据表优化。一个规则集中可能有上千条分析语句和规则,它们会大量的引用外部数据表数据,需要对表计算进行计算优化,比如 hash 匹配、大规模 IP 匹配优化、大规模正则匹配和串匹配优化等;
常量表达式优化。提高运行性能;
表引用优化。包含引用示例归并和引用语义归并两个部分,降低引用表的资源占用。
分析语句和规则编译之后生成运行子图,每一条语句和规则对应一个子图,此时需要集中所有规则进行图优化,分为四个流程:
第一步是图融合,图融合涉及子图融合,即将规则集中所有子图融合成一个运行图,然后进行图节点语义融合、时间窗口归并、引用公共资源优化;
第二步是数据流优化,降低图规模,减少传输数据量,主要进行 Key 前置、语义等价节点融合、网络吞吐均衡,减少数据倾斜、节点归并,大幅压缩超大图节点数量等操作;
第三步是字段裁剪,降低传输事件大小,进而降低网络 IO 压力,主要包含图上字段推导和裁剪以及字段归并;
最后是代码生成,将分析语句和规则语义生成代码,并将执行图映射到 Flink DataStream API。
实时计算一个核心要素是时间,不同的时间处理方法和实现方案会带来差异很大甚至完全不同的计算结果。实时分析中,时间主要影响两个功能,即时间窗口和时间线。
在安全分析场景里,时间窗口需要支持通用滑动时间窗口、也要支持自然时间滑动时间窗口,比如每年,每月,每星期等自然,甚至是变长时间、需要支持层叠窗口重复数据融合,降低数据存储量、能自动进行重复计算消除,避免重复告警、时间定时器归并、事件乱序正确处理,避免事件乱序引起错误计算。
时间线可分为事件发生时间和时间处理两类,进而延伸出时间精度,不同的时间精度会对处理性能和存储造成很大的压力,比如需要对时间进行排序的场景。由于实时分析中事件可能是乱序的,因此需要支持延迟时间,解决大部分因为乱序而造成的计算不准确问题。部分计算场景涉及系统时间<->事件时间之间的相互转换,需要能提供两种时间的转换计算方法。由于执行图是大量子图融合而来,因此需要同时支持对全局和局部时间水位进行管理,保证图上时间线能正确推进。
安全基线分为三类:
第一类是统计类安全极限,包含常见的时间类、频率类、空间类、范围类和多级统计类的安全基线;
第二是序列类,比如指数平滑类和周期类安全基线;
第三是机器学习类的安全基线,比如使用一些聚类算法的安全基线,决策树类安全基线等。
基线处理流程主要分为三个部分:基线学习、基线检测和基线路由,其中穿插事件过滤、时间窗口、基线降噪、基线管理等流程。基线学习流程包含从消息队列和存储中读取事件流,经过事件过滤和时间窗口聚合,事件流中可能包含噪音数据,还需进行数据降噪流程,最后基线学习流程学习输入的事件流程,生成对应的安全基线。学习完成的安全基线在进行基线管理流程之后用于异常检测,用于预测和异常检测,如果发现异常行为,则产生异常事件,输出到后续的处理流程,用于后续的业务的使用。用户在使用过程中可能需要修改或删除一些学习好的基线或者自己新建一个基线,这些基线的增删改操作通过基线路由功能来完成,基线路由流程将用户编辑的基线在图上路由之后正确的分发到对应的图节点实例中。
基线的周期分为 learn,ready,close,expire 四个阶段:
learn 表示学习阶段,在这个阶段基线学习输入的事件流;
ready 阶段表示当前时间线已经到了基线的学习截止时间,但是因为延迟时间,基线需要等待一个延迟时间,在这个时间段基线可以继续学习延迟的事件,同时基线可以用于异常检测;
close 表示当前时间线到了延迟时间,此时基线不再学习输入的事件,只用于异常检测;
expire 表示当前时间线到了基线超时时间,需要基线停止进行异常检测,并删除。
基线的计算由两种情况触发:
第一种是事件触发计算,每条事件到达之后会触发一次异常检测计算;
第二种是时间触发计算,基线周期会注册时间定时器,时间定时器触发之后会触发相关基线计算流程。
基线的输出分为基线异常事件输出和基线内容输出:
基线异常事件输出发生于基线异常检测过程,当发现异常事件时需要输出对应的事件;
基线内容输出发生于基线学习完成之后需要将基线本身进行输出,用于基线编辑和基线本身异常分析。
用户在使用过程中,可能会经常编辑已有基线或者自己根据一些分析和数据来新建特定场景的安全基线。基线编辑之后需要能下发到基线引擎中,这就涉及如何在线编辑和更新基线。
首先需要基线是可编辑的,要求分析语言支持基线编辑相关语义,同时基线数据结构的设计需要支持基线编辑的语义,最后是要提供一套基线编辑可视化流程,包含基线展示、修改、删除等功能,用户可以直接在页面进行基线的编辑和下发;
第二是要求基线是可路由的,分析语句和规则在经过编译和图优化之后的真实执行图和页面显示的规则运行会有很大的不同,一个可路由的基线要求实现编译时构建全局基线更新流图、一套运行时基线路由方法,包含执行流图的路由流构建,广播和定向路由的支持,最终实现精确的基线数据分发;
最后还要求基线是可更新的,需要有一套清晰的基线更新语义,定义基线运行周期和计算方法,然后在你基线更新过程中,任何一个位置都可能会发生异常导致更新失败,此时需要设计一套机制能在任何位置失败后将信息反馈用户,用于错误判定和问题修复。
在基线学习过程中,通常学习周期是比较长的,比如最近一周、最近一个月等,长周期的学习通常会面临一个数据割裂的问题,比如学习最近一周的数据,但是现在是星期三,也就是说最近一周的数据分成两个部分,其中从星期一到星期二的数据是保存在历史数据存储中,星期三及之后的数据是实时发生的,这里会涉及历史和实时数据融合学习的问题。这里可以分为三种情况:
第一是待学习数据全部是历史数据,这需要支持历史数据学习范围探测,和在线基线更新;
第二是待学习的数据全部是实时数据,这要求支持基线自动学习、基线自动检测和基线自动更新;
第三种是刚才举例的这种,也是最复杂的情况,即历史和实时数据融合,这需要支持历史和实时数据边界划分、基线融合、重复数据消除。
基线学习的数据中通常会有一些噪音,这些噪音可能是某一次异常操作,比如用户某一次的异常登录,也可能是数据采集的过程中引入的错误数据,因此需要对噪音进行消除,来增加基线准确性,减少误报。
数据降噪根据数据类型可以简单分为数值类数据降噪和非数值类数据降噪两种,这两种处理方式会有不同。噪音的判定主要有四种:
第一种是相对于本周期的数据来判断,即与本周期其他数据进行对比,判断是否是噪音;
第二是相比上一个周期,与最近一个周期的数据进行对比,判断是否是噪音;
第三个是相比历史数据,与历史上所有的数据来进行对比来判断是否是噪音;
最后是用户自定义一个噪音判定逻辑,比如设定大于多少小于多少它是噪音。
数据降噪时候通常会需要保存相关数据,比如要用历史的数据来进行噪音判定,那么就需要存储一些历史的关键数据,历史数据通常非常多,为了降低存储,需要进行优化降噪数据结构的优化,比如最小化降噪关键数据,字段裁剪等。
引擎运行中一个非常重要的部分是如何监控以及保护资源。涉及到三个方面的内容:
第一个是稳定性增强,需要动态监控基线运行过程中内存的占用,引擎中可能同时运行了几百上千基线规则,需要能监控每条基线规则内存占用有多少,对于内存占用异常的规则,需要采取内存保护的措施,比如删除一些数据或者将它隔离出来,防止影响其它正常规则的运行,删除的时候可以采用资源优先级的管理,如果优先级比较低,且同时占用大量的资源,就可能会把资源给减少甚至停用规则的运行。引擎同时还对基线计算过程进行监控,监控过程如果发现严重影响图处理性能的慢路径,则采用子图隔离的方式将慢路径对应的子图隔离出来,防止对其它分析流程造成影响;
第二是状态监控,状态监控包含两个部分,第一部分是引擎将执行图所有计算节点的状态数据,比如 CPU、内存、磁盘、输入输出等信息报告给监控服务;第二部分是监控服务将执行图的运行信息处理之后映射为规则状态信息,完成图状态到业务状态的转换。对于大规模执行图和高并发执行的分析任务需要对图状态报告流程进行优化,降低资源占用;
第三是流量控制,引擎的下游业务可能是一些处理能力比较慢的流程,比如数据库写等,此时需要支持流量控制,防止较快的处理流程向较慢的处理流程输入过多的数据而引起资源过度消耗和卡顿,流量控制需要支持主动流量控制、被动流量控制以及时间窗口相关的流量控制,通过用户配置或自动处理来解决前后处理性能不一引起的数据丢失和系统不稳定问题。
用户在使用过程中经常要对规则进行操作,这些操作会引起运行任务的启停,启停过程中数据需要前后保证一致,不能因为启停而导致保存的数据丢失。
Flink 本身支持任务重启时重新加载数据,但是在基线引擎这里问题会比较复杂,因为用户可能会停用、启用或者修改规则,这会引起规则集发生变化,进而引起执行图发生变化,为了保证任务重启时不变的规则能正确从 savepoint 加载到到正确的数据,需要支持图局部状态稳定,即在图优化过程中图局部变化不影响其它子图,同时在代码生成过程中保证稳定子图生成稳定的执行代码,变化规则只影响与其相关的子图,其它不变的规则不受影响。
基线学习过程中通常保存大量的中间数据,为了加快 savepoint 和 checkpoint 速度,需要对复杂数据结构的序列化和反序列化进行优化,还需支持增量状态。引擎服务通常需要对多用户提供分析服务,因此还需对多用户多任务的状态进行管理,保证每个任务都能准确关联到其对应的状态数据。
四、实践与展望
分析引擎提供的实时安全分析能力服务于公司大部分大数据产品,比如大数据与安全运营平台、态势感知、EDR、云安全、工控互联网、智能安全等。随着这些产品部署了近千个客户,包括央企、政府、银行、公安等,同时还支持常见国产化系统和各类私有云。部署的环境从一到几百台集群规模,事件量从几百到上百万 EPS,还参加和支持了上百次部委和央企的专项行动。
随着知识的扩散和各类安全漏洞的频发,各种攻击手法和安全威胁也层出不穷,这对安全分析能力的要求也越来越高,需要引擎能持续进行更新和优化,以提高对安全攻击的检测能力,后续需要继续将更多更好的行为学习算法和技术与安全基线集成,提高安全基线的检测能力。同时期望能将引擎的一些实践通过某些渠道回馈到社区,让更多的人能使用其中好的设计和实践。
往期精选
更多 Flink 相关技术问题,可扫码加入社区钉钉交流群~