如果你在一家中等规模的公司做安全运营,大概率会遇到这个场景:告警平台一夜之间堆了几千条告警,打开每条看都是孤零零的事件,有的命中威胁情报,有的只是端口扫描,看不出彼此联系。而攻击者可能早就用一次钓鱼、一次横移、一次外传走完了整条链路。关联分析这个词在不同领域含义差别很大,做生物信息学的人想到的是全基因组关联分析,做安全的我们想到的则是攻击链路展示——把散落的单点告警还原成一条有头有尾的完整攻击故事。这套系统我从模型设计到可视化落地做过好几轮,中间踩了不少坑,这篇把完整思路和实现细节复盘一遍。
1. 单条告警是一颗散落的弹壳:关联分析要解决什么
1.1 一个让我彻底改变看法的告警场景
早些年我做安全运营的时候,最痛苦的不是没有告警,而是告警多到没人看得过来。某天早上打开平台,里面有这么几条:
- 09:12,邮件网关:员工收到一封主题为“2024Q4_Bonus.xlsm”的带宏附件邮件;
- 09:13,终端EDR:该员工的办公PC上Excel进程拉起了一个powershell进程;
- 09:14,DNS日志:该PC解析了一个从未见过的域名,并建立了外联;
- 09:26,域控认证日志:从该PC对域控发起了一串密码尝试,前面五十次失败,最后一次成功;
- 09:42,出口流量:域控主动向一个境外IP持续发送压缩数据。
单独看,第一条可能是普通垃圾邮件,第二条可能是运维脚本,第三条可能是误报,第四条像是暴力破解,第五条又像是异常上传。但如果把五条按时间和实体排开,你会发现这是一个标准的多阶段攻击:投递、执行、命令控制、横向移动、数据外传。问题在于,当时的告警平台里它们没有任何关联,分散在邮件网关、EDR、DNS日志、认证日志、流量分析五个独立模块里。
这就是关联分析天然要解决的命题:让数据自己把这条链路“串”出来。攻击者在一次攻击里会在不同设备上留下痕迹,而这些设备各自只能看到自己那一小段视野。只有把跨数据源、跨时间线的告警拼到一起,攻击者的完整路径才会从一团噪音里浮现出来。
1.2 日志检索与关联分析的本质区别
很多团队一开始会觉得,这事用日志检索也能干。毕竟Elasticsearch(ES)足够强,我可以把五个模块的日志全部收进来,然后手动或者写固定查询把相关事件捞出来。理论上可以,实际上走不通。
日志检索是“人工假设驱动”的。你必须先猜测IP之间可能有关系,才知道去搜哪几个字段。问题在于,真实攻击里的后续跳板往往是你猜测之外的节点。分析师的经验决定了能发现多少攻击路径,而经验本身就是最大的瓶颈。
关联分析是数据驱动的:它不依赖人先给出假设,而是通过实体和时间的匹配自动把两条原本不相干的告警“发现”为同一条攻击链路的片段。
打个比方。日志检索是拿对讲机问另一个保安“你那边是不是有个戴帽子的人经过了”,然后自己跑过去看监控录像。关联分析是直接在总控室的大屏上,把这个戴帽子的人从进门到进电梯的每一帧轨迹自动连成一条线。一个人看单帧画面永远看不出完整路线,但把轨迹拉成线之后,路线本身会说话。
这也是“攻击链路展示”这个需求的核心意义所在——展示的本质不是画一张好看的图,而是把分析维度从“单事件”提升到“完整叙事”。有了叙事,一个初级分析师也能看懂攻击者从哪里进来、经过了哪些资产、最终要干什么。
1.3 攻击链路系统要交付的三大难题
这套系统从立项到可用,我总结下来绕不开三座山:
第一是数据孤岛。不同安全设备对同一个事件的描述完全不一样。同一个源IP,有的字段叫src_ip,有的叫source_ip,有的叫sip;时间有的用字符串,有的用时间戳。不解决这个问题,甚至没法判断两条告警里的“同一个IP”是不是同一个IP。
第二是告警风暴。生产环境里的告警量级不是几百条,而是几千万条。如果关联逻辑不先做降噪和聚合,结果就是图里塞满了边,最后呈现出来的链路密密麻麻根本没法看。这一步做得不好,关联分析反而会把告警风暴进一步放大成“链路风暴”。
第三是可视化信息密度。安全分析师要看细节,管理层要看结论。一张图同时满足两者很难,链路太粗则没有证据价值,链路太细则没有人能看懂。
这三座山对应了后文讲的三块内容:模型设计解决“怎么关联”,数据处理解决“哪些数据能进关联”,可视化解决“关联出来怎么让人看懂”。
2. 实体、事件与时间窗:攻击链路模型的底层设计
2.1 实体归一化:IP、域名、文件、账号如何成为图的节点
刚开始设计这个系统的时候,我犯过一个很常见的错误:试图用“告警”作为关联分析的基本单元。结果就是图上一堆告警节点,关联逻辑只能靠人工配置告警之间的跳转关系,维护成本极高,根本推不到规模。
后来才换过思路来。攻击链路的图模型里,节点不能是“告警”,而应该是攻击者操作所针对的对象:主机IP、外连域名、恶意文件、登录账号、进程。告警本身则是连接两个实体的一条边,描述“这个实体对那个实体做了什么”。
举个例子。有一条告警是“内网IP 10.10.8.21对10.10.8.55发起445端口扫描”,在链路模型里它不是单个节点,而是被拆成:源IP实体10.10.8.21、目标IP实体10.10.8.55,中间一条事件类型的边“扫描探测”。这样做的好处是,当另外一条告警“10.10.8.55执行了powershell”进来时,两条告警共享实体10.10.8.55,就自然产生了一个连接点——你不用写任何关联配置,两者的关系在图里已经存在了。
实体归一化要做的事,就是给每个实体建立唯一的ID。这个ID不是原始日志里的字符串,而是经过资产库、威胁情报库、主机名映射之后的标准标识。比如同一个内网IP在不同日志来源可能写成10.10.8.55、office-lisa-023、主机名lisa-pc,系统要能通过资产库把它们归一到同一个实体上。这一步做不好,后面所有的关联都是鸡同鸭讲。
2.2 事件类型与时间窗口:怎么定义“相关”
实体解决了“谁和谁有关系”,下一步要解决“什么时候算相关”。
我建议事件类型要自定义一套分类体系,但粒度别太细。太细了后续建模和可视化都极其痛苦,太多了也不好。我最后用的是二十多种核心事件类型,覆盖攻击生命周期的主要动作:
| 事件类型 | 含义 | 对应阶段标签 |
|---|---|---|
| 扫描探测 | 端口扫描、漏洞扫描、目录爆破 | 侦察 |
| 暴力破解 | 认证失败或批量登录尝试 | 初始访问/横向移动 |
| 恶意文件落地 | 下载、打开恶意文件 | 初始访问/执行 |
| 命令执行 | 终端执行了可疑命令或脚本 | 执行 |
| 权限提升 | 提权、创建特权账号、修改权限 | 权限提升 |
| 持久化 | 计划任务、自启动、服务安装 | 持久化 |
| 内网横移 | 同一账号/工具在内网多台主机出现 | 横向移动 |
| C2外联 | 与威胁情报命中的域名/IP建立连接 | 命令控制 |
| 数据外发 | 异常大流量出网、压缩包外传 | 数据外传 |
“相关”的定义,我用了两条硬条件:两个事件至少共享一个实体,并且发生时间差落在时间窗口内。时间窗口的设计要分两层,短窗口用5到15分钟捕捉探测到利用这种快速推进,长窗口用24小时捕捉从投递到横移的慢速攻击。
有一点非常重要:时间窗口不是越大越好。窗口拉长确实能关联出更多事件,但误关联也会成倍增加。攻击者的确可能潜伏几周再横移,但对一个初始版本来说,用24小时窗口已经能覆盖绝大多数自动化攻击链,先做对再做大。
2.3 攻击阶段标签:让链路能讲出战术故事
有了实体、事件和时间,链路还只是一堆节点和边的集合。要让它变成一个“看得懂的故事”,还需要给事件打上攻击阶段标签。
这部分我建议参照ATT&CK的战术阶段来设计,但不用追求到“子技术”级的精细化。每个事件类型映射一个阶段标签,比如“恶意文件落地”映射到初始访问,“C2外联”映射到命令控制。链路图生成之后,链路每跨过一个新阶段,界面上就把这个阶段高亮一次,读者一眼就能看出攻击推进到了哪一步。
我见过一些团队在战术标签上过度较真,为了一条告警到底是Execution还是Persistence吵半天。实际上,链路的阶段标签是给人阅读理解用的,不是给学术评审用的。它的核心价值是让男的事能进图建模的时候尽量少。”高一级的粒度更能稳定地支撑跨设备关联。
3. 数据地基:告警结构化提取与降噪预处理
3.1 字段标准化:跨设备告警的第一步
任何关联分析系统,第一步都是跟字段名较劲。真实环境里的告警来源五花八门:EDR、防火墙、邮件网关、蜜罐、流量探针、认证日志……它们对同一个字段的命名方式基本处于“各写各的”状态。
我建过一张很长的映射表,把来自不同设备、同义不同名的字段全部映射到一个标准schema上。简单展示几个典型对照:
| 标准字段 | EDR来源 | 防火墙来源 | 认证日志来源 |
|---|---|---|---|
| src_ip | pid | src_ip | client_ip |
| dst_ip | target | dst_ip | server_ip |
| event_time | event_time | timestamp | DateTime |
| user_name | user | src_user | samAccountName |
标准字段不要做得太细,够用即可。我当时只保留了十来个核心字段:源IP、目的IP、源端口、目的端口、协议、时间、源账号、目标账号、文件哈希、域名、进程名、事件类型、原始日志ID。这些字段覆盖了关联分析需要的全部维度,多余的字段全部丢进一个json扩展字段里原样保留,关键时候还能回溯。
时间字段特别提醒一下:统一成epoch毫秒加ISO8601字符串两种格式。只用字符串会在窗口滑动和排序时浪费大量性能,只用毫秒值则在排查问题时肉眼根本看不出几点几分。两种都保留,排序用long,展示用字符串。
3.2 聚合去重与置信度富化
告警进入关联引擎之前,必须先做一轮聚合。不然一天几千万条告警打进去,图直接炸掉。
聚合并不能把事件丢了,而是要在事件之间去除“重复”。比如一台主机被端口扫描,IDS可能产生几千条几乎相同的告警。这些不需要逐条进图——我会把相同源IP、相同目标IP、相同事件类型、发生时间落在同一分钟内的告警合并为一条聚合告警,同时记录count、首末时间,并保留一个原始告警ID列表。这样后续点击链路节点时,仍然能展开全部原始告警,但图上的边只有一条。
置信度富化也很关键。每个事件本身要有一个严重级别,但在进入关联计算前,我会把威胁情报的附加信息(恶意标签、情报来源、命中次数)和资产属性(主机是否核心资产、责任人)挂到实体上。这样后面计算链路置信度时,就不需要每个事件临时查库,直接读节点上挂的属性就能打分。
3.3 基于资产属性的过滤决策
很多初版系统垮掉,都是因为过滤器设计得太粗暴,直接谁都不用。我踩过的坑是:第一版把扫描器IP全部拉黑之后,监控组过了几天发现一个真正的攻击流量被一起误滤了,因为攻击者借用了扫描器所在网段的一个跳板。
后来我把过滤改成了三层,而且原则上“有标记可审计,不悄无声息地丢”。
第一层是静态白名单:公司自有扫描器、堡垒机、监控探针等固定IP列表。这层过滤最确定,但也要留个旁路开关,关键时刻可以一键关闭。第二层是动态白名单:运维计划任务的时间段和常用脚本签名。动态白名单的核心是周期判断——比如某个主机每天凌晨两点准时批量拉起一批SSH连接,这属于基线行为,链路计算时不参与。第三层是基于资产权重做弱化:低价值资产上的低危告警不参与链路初始化,但一旦这条链路蔓延到高价值资产,则整条链路上的低危事件全部重新激活作为证据。
这三层设计之后,能明显减少关联引擎的空转,同时不会让真正重要的链路因为一次错误过滤而断掉。
4. 关联引擎实现:规则编排、时间窗口滑算与图路径发现
4.1 三层规则体系:单点、序列与链式
关联引擎是整个系统的心脏。我在实现时把规则分了三个层次。
单点规则最简单:一个事件本身命中威胁情报或者高危特征,比如某个内网主机直接连了已知恶意域名。这类单点事件是链路的“锚点”,往往能标记一条攻击旅程的起点或终点。
序列规则处理“先A后B”的因果关系:事件A在事件B之前发生,两者共享一个实体,且时间差在窗口内。比如“恶意文件落地—命令执行—C2外联”就是很典型的序列。序列规则的价值在于,把几个相邻阶段绑成一个小片段。序列规则的实现要处理时间上的相对顺序——A和B共享主机实体,A的时间必须早于B。
链式规则是最终产出链路的层次:把多个序列片段通过共享实体拼接成一个完整的有向图。这里我不用复杂的图匹配算法,而是用一个“从锚点扩展”的方式:先选定一批高置信度的锚点事件,比如已经确认的C2外联,然后沿共享实体向时间前向回溯它的前因,再向前推导它的后果。
规则引擎的选型上,我的建议是不用重型的Drools这类规则引擎,而是直接用代码写Pipeline。规则本质上是“条件判断加动作”,用Groovy脚本或者Python脚本描述清楚每一步的过滤条件、时间窗口、拼接规则,比堆一堆XML规则文件要可维护得多。规则文件一旦多了,排查问题时想死的心都有。我后面版本干脆把规则定义成一段可版本化、可单测的代码类,每个规则类对应一种攻击模式。
4.2 时间窗口内的实体-事件索引
实现关联引擎时最需要注意的性能问题,是把所有告警两两比较来建边。这个O(n²)复杂度在告警量上来之后会直接把内存和CPU打爆。
我的做法是建实体倒排索引。维护一个哈希表:实体ID是key,value是一个时间有序的事件指针列表。这样当一条新告警进入窗口时,不需要把它和All events比较,只需要取出它涉及的所有实体,然后翻这些实体各自的事件链表,看是否有时间差在窗口内的事件。
再配合时间分桶:每个实体的事件列表按一分钟一个桶来组织,滑动窗口推进时直接移出过期桶。这个设计让“找候选关联事件”的复杂度从O(n)降到近似O(候选数),在一天几千万告警的规模下基本能平稳运行。
这里有一个细节:实体的事件列表不是无限增长的。内存里每个实体最多保留最近24小时的事件,超过的直接淘汰。需要回溯更早期历史时再去查离线存储,图引擎只处理在线滑动窗口内的数据。
4.3 路径发现算法与深度控制
当图关系构建完成后,真正“展示攻击链路”的动作从这一步开始:从链路图里搜索出有意义的路径。
我第一版是用DFS从每个高危事件回溯前驱事件。结果就是在一些告警密集的时间段,出现一堆非常相似的路径,图上面全是重复边,根本没法看。必须加约束。
约束条件按重要性排序如下:
- 深度限制:默认从终点回溯不超过4跳。超过4跳的路径要么是误报,要么说明中间有大量未被观测到的环节,强行把它展示出来,不如不展示。
- 边过滤:只保留置信度大于某个阈值的边,弱关联边会在路径搜索时被剔掉。阈值初始设置为0.6,后面根据误报反馈动态调整。
- 节点去重:同一主机在一段时间内反复出现的同类事件边,合并成一条带次数和总时长的聚合边。
- 起点启发式:优先选择“外部IP实体”“邮件投递事件”“未授权设备”这类节点作为起点,终点优先选择“域控”“数据库主机”“备份服务器”这类高价值资产上的事件。
路径搜索我用的是基于DFS的改进版,边按时间序展开,遇到已经访问过的节点且时间更新则不再回溯,避免成环。这样搜索出的结果是有向无环的时序路径,正好匹配“攻击者从A到B再到C”的叙事结构。
5. 可视化叙事:把关联结果画成攻击者的完整路径
5.1 时序泳道图加拓扑图的双层视图
开发到可视化这层,最纠结的问题是:到底用什么图才能让攻击链路“一眼看懂”。
纯拓扑图的问题在于它丢失了时间维度的信息。攻击链路的本质是时序推进,如果只画节点和边,攻击者到底先打了A还是先打了B,画面上根本看不出来。纯时间轴又看不清楚实体之间的关联关系。
我们的方案是拆成上下两层视图。上层是横向的时序泳道图:横轴是时间,纵轴按攻击阶段分道,每个事件按发生时间落在对应阶段的行里。这条泳道图展现的是“攻击叙事”的时间节奏——什么时候开始的、中间停顿了多久、最后动作发生在哪个阶段。下层是带密度的拓扑图:实体是节点,事件是边,边宽代表关联强度,节点颜色代表实体类型。
技术选型上,早期用D3.js自己撸,后来切到AntV G6,原因主要是G6自带布局算法、边交互和聚合折叠能力,省了很多造轮子的精力。节点颜色规则我们做了统一约定:主机IP用蓝,域名/外联IP用紫,文件哈希用橙,账号用绿,核心资产加粗边框。
5.2 节点的交互下钻与原始告警回溯
一张静态图是没法让分析师信服的。分析师真正需要的是:看到一条边,能点开它,看到支撑这条边的原始证据;看到前一个节点,能回溯这条路径上每一跳的完整上下文。
交互层我们做了三件事。
第一,点击节点,右侧抽屉展示该实体的全部属性:IP、所属资产、责任人、情报标签,以及与该实体相关的全部事件列表,按时间倒序。第二,点击边,展开这条连接的证据面板,列出支撑该边的原始告警ID、来源设备、命中规则、原始日志摘要。这一步特别重要,因为关联分析本质上是“由系统提出假设,由人来确认”,没有证据回溯功能,分析师不敢信自动关联的结果。第三,全局时间范围滑杆。默认显示24小时窗口,分析师可以缩小到1小时只看瞬时动作,也可以拉长到7天看慢速潜伏链。
有一个小细节值得做:图上的每条边都带一个“完整度”小标记。节点颜色太杂、边上事件太少、路径覆盖阶段太少时,系统可以自动把线画成虚线,提示分析师这条链路证据链不完整,需要谨慎判断。这比把所有链路的可信度都画成一个强度,好理解得多。
5.3 为管理层准备的一页纸攻击故事
提供给分析师的图,信息量一定很大,但管理层不需要看那么多原始证据,他们只需要知道:是不是真被攻了、攻到哪了、影响哪个资产、要不要联动应急。
我们在系统里单独做了“摘要模式”。它会自动从完整链路里提取几个关键信息:攻击源、入口方式、第一步动作、攻陷的核心资产、横向移动跳数、最终动作、影响评估。生成的页面是一张纵向的“攻击行程卡”,从攻击者进入到最后动作,每行一个大阶段图标和一句描述。如果有威胁情报背景,还会自动附上一段攻击组织画像,例如“该IP曾关联到某类恶意样本传播事件”。
这一步自动生成的逻辑不算复杂:从已经拼接好的链路里找起点节点、终点节点、含高危事件数最多的路径,以及路径上覆盖的阶段标签列表。但它对推动安全团队向上汇报的效率提升非常明显——以前应急响应写报告要手动翻日志理时间线,现在系统直接把“故事线”生成好了。
6. 实战拦路虎:误报、漏报与性能的取舍平衡
6.1 误报治理:白名单体系的演进
关联分析上线第一周,我就收到了很多抱怨:链路数量不仅没减少,反而变多了。原因很简单,自动化运维、监控探针、CDN回源这类正常行为,在时间窗口和共享实体的规则下被大量拼接成了“伪攻击链路”。
印象最深的一次误报:某业务在促销活动期间,CDN回源节点的连接量陡增。我们的系统把回源源站节点和业务服务器的高频外联误判成了“C2外联加数据外发”,生成了好几条高置信度误报链路。这让我意识到,单纯加IP白名单不够。
白名单体系我迭代了三版。第一版是固定IP名单,对付扫描器。第二版加入了“周期基线”:记录每个资产每周每天各时段的外联行为习惯,形成基线画像。如果一条事件的实体组合和当前时段基线一致,它在参与关联计算时权重降为原来的20%。第三版加入了“相似链路聚合”:如果同一批实体组合在一周内反复生成结构相同的链路,默认这是一条批量脚本行为,需要人工确认一次后才进入观察名单。
最重要的一点是,白名单命中必须留操作日志。分析师点开任何一条被过滤的告警,都能看到“因为命中哪个基线、在什么时间被过滤”的记录。这一点在出现疑难争议时能救命。
6.2 漏报是设计边界而非事故
误报聊完之后必须聊漏报。很多团队追求把“所有攻击”都关联出来,结果往往是强行拼接,制造出一堆逻辑不通的假链路。我的原则是:宁可展示两条断裂链路,也不生成一条虚假链路。
真实环境里,日志总有缺失环节。比如攻击者在内网横移时,某台网络设备没有开日志,中间一跳就断了。此时系统如果强行把前后片段拼起来,就会生成一条缺失中间节点的不可信链路。我们选择的做法是在链路图上保留断点标记,明确标出“该路径中间存在未观测到的事件”,同时降低这条链路的整体置信度。分析师看到后可以自己去补查那台设备的日志,或者干脆把这条链路标记为“待完善”。
漏报的系统化治理还有一个关键工具——链路完整度评分。就是一个链路上实际覆盖的阶段标签数量除以理论期望阶段数。覆盖超过5个阶段的链路,通常是比较完整的攻击叙事;覆盖率只有两三个阶段的,大概率只是某个异常片段,需要分析师重点核查。
6.3 性能优化:从全量扫描到索引驱动
最后说一下性能。在一天近亿条日志、近千万条告警的环境里,如果关联引擎不做优化,单机内存命中率会非常难看。我遇到最明显的问题是GC频繁,排查下来发现是因为每个事件对象里存了太多String字段。
几个立竿见影的优化手段:
- 事件对象紧凑化:时间戳用long,IP用整数封装,进程名和域名用字符串池常量。事件对象整体体积从几百字节压缩到几十字节。
- LRU缓存资产属性:实体资产属性不要每个事件查库,用LRU缓存顶住热数据,缓存命中率基本在95%以上。
- 按实体哈希分片:对实体ID做一致性哈希,把不同实体的关联计算分到多个worker并行执行,每个worker只需要和本地分片内的事件做图构建,最后通过一次聚合合并全局路径。
- 依托离线存储做长历史回溯:在线内存图只保留24小时内的事件,更长历史的关联需求走离线计算,结果缓存到结果库中,不反复重算。
这套优化做完之后,单集群在高峰期能稳定支撑每秒几千条告警的实时关联。
7. 一条真实攻击链路的完整演示
7.1 输入告警:几个看似无关的事件
说再多理论,不如把一个完整案例走一遍。以下是我在测试环境里构造的一条典型钓鱼攻击链路,原始告警如下:
| 告警序号 | 时间 | 来源 | 事件内容 |
|---|---|---|---|
| A1 | 09:12:33 | 邮件网关 | 员工lisa收到带附件邮件2024Q4_Bonus.xlsm,发件人hr-noreply@lookalike.example |
| A2 | 09:12:50 | 终端EDR | 主机host-lisa-023下载并打开2024Q4_Bonus.xlsm,宏自动执行 |
| A3 | 09:13:02 | 终端EDR | 主机host-lisa-023上excel.exe拉起powershell.exe,命令行含-enc参数 |
| A4 | 09:13:20 | 出口流量 | 主机host-lisa-023外连域名cdn.oss-update-zone.example,命中威胁情报 |
| A5 | 09:26:44 | 域控认证 | 账号lisa.q从host-lisa-023尝试登录DC01失败50次后成功1次 |
| A6 | 09:41:52 | 出口流量 | DC01向198.51.100.87的8443端口持续发送约200MB压缩数据 |
这六条告警分布在四个独立数据源里,按设备单独看,哪条都可能被当成事件处理掉。
7.2 实体抽取、片段拼接与置信度打分
进入关联引擎后,第一步是实体抽取。A1到A4里抽出的关键实体有:文件2024Q4_Bonus.xlsm、进程powershell.exe、主机host-lisa-023、域名cdn.oss-update-zone.example、账号lisa.q。A5里又出现了主机host-lisa-023和账号lisa.q与DC01的关联。这样,前四件事和后两件事通过同一主机和同一账号自然衔接,无需任何人工干预。
拼接过程大致是这样:时间窗口24小时内,A1、A2、A3共享“主机host-lisa-023”和“文件”实体,先连成“投递到执行”的序列片段;A4与A3共享主机,补上“命令控制”环节;A5与前序片段共享主机和账号,形成“横向移动”环节;A6再通过DC01连接A5,形成“数据外传”终点。
置信度打分用了一个简单而透明的模型:每个事件的基准权重乘以时间衰减因子,再乘以资产重要性系数。关键系数举例如下:
| 事件类型 | 基准权重 | 时间衰减(每30分钟) |
|---|---|---|
| 恶意文件落地 | 40 | 0.98 |
| 命令执行 | 50 | 0.98 |
| C2外联 | 60 | 0.97 |
| 横移成功 | 70 | 0.95 |
| 数据外传 | 80 | 0.90 |
DC01是域控,资产重要性系数1.5。算下来这条链路的总分超过300分,远高于默认上报阈值200分。阶段标签覆盖初始访问、执行、命令控制、横向移动、数据外传共5个环节,链路完整度约83%。系统自动判定这条链路需要优先展示。
7.3 最终的链路视图与复盘思考
分析师最后在界面上看到的是一张图:起始节点是发件邮箱和恶意文件,中间经过主机、命令控制域名、横向移动到域控,终点是外传IP。时间轴上六个点依次排开。点击A4那条边,能直接看到DNS解析记录和外联流量的原始日志;点击域控节点,能看到该资产的关键级别和继任负责人的联系方式。
这套系统真正跑起来之后,我最大的感受是:攻击链路展示能力的下限取决于数据质量,上限取决于模型取舍。做一个这样的平台,核心不是算法选型多高级,而是把“字段标准化”这个最土最累的地基工作做扎实。
如果你也在做类似的东西,我的建议是:先别急着调算法和画图,回去花两周时间把告警字段映射表和实体资产库整清楚,后面所有的关联逻辑都会顺畅起来。可视化也只是为了让已经存在的因果关系更可读——真正重要的是前面的数据链路能不能把事情说圆。
这个内容后续还有很多可以扩展的玩法。比如把链路结果直接联动到SOAR平台触发自动封禁和应急处置;又比如把基线和白名单做成持续学习的模型,让误报率随着运行时间自动下降。但这些都是在这个地基之上锦上添花的事了。