做安全运营这几年,我最头疼的事情之一就是:日志里明明有攻击痕迹,但攻击从哪里来、打了哪些点、怎么一步步打穿的,排查起来却像拼一版缺了一半碎片的拼图。告警只会告诉我“有异常”,却很少告诉我“攻击者为什么这么做、下一步指向哪里”。直到我们把 SecGPT-14B 引入流量分析流程之后,这个局面才真正改观。它做出来的攻击流量溯源图谱,能把分散在几万条日志里的实体串成一张图;攻击链自动还原,则把这张图从“谁连了谁”推进到“谁先打谁、中间又借谁跳到了哪台服务器”。这篇文章就把我们这次实战的完整过程拆开讲一遍,包括使用思路、提示词设计、参数设置,以及那些单纯看官方文档学不来的坑。
我做安全分析这些年,最大的体会是:人眼不适合在纯文本日志里找逻辑关系。你面对的是几万行告警和会话记录,源 IP、目标 IP、端口、协议、时间戳、域名、用户账号,每一条看着都有关系,但真正把它理成攻击链又极其吃力。SecGPT-14B 这类安全大模型的价值,不在于“又多了一个能对话的框”,而在于它能把日志读进去之后,用图谱的方式把实体和关系吐出来,我拿到的不再是几十页聊天记录,而是可以直接用于研判的点和线。如果你是做安全运营、应急响应、威胁情报分析的从业者,或者正在评估大模型在安全分析场景里能不能落地,这篇文章正好适合你,我会把我们的用法、效果和教训都列出来。
1. 溯源到底难在哪:厘清图谱与攻击链要解决的问题
1.1 告警连不成线的真实场景
先还原一个最常见的现场。某天下午,态势感知平台弹出一条中危告警:某内网服务器对外发起异常外联,目标 IP 属于云上某个网段。点开详情,里面只有时间、源 IP、目的 IP、端口四个字段。接着你去看防火墙日志、DNS 日志、终端日志,又翻出来一批相关的记录:主机 A 访问过主机 B 的 445 端口,主机 B 随后向主机 C 发起了 WinRM 请求,主机 C 后台下载了一个未知文件。单看这些记录,每一条都不特别起眼,但把它们串在一起,就是一个明显的横向移动路径。
问题是,把这些记录串起来这件事,目前大部分平台做得并不好。传统关联规则只能做“若 A 且 B 则告警”,例如“同一源 IP 在十分钟内访问超过五个内网主机”,这类规则能抓异常,却抓不住“为什么是这个路径、下一步是什么”。安全分析师不得不手工把多个来源的数据导出到表格里,按时间排序、按 IP 筛选,一点一点拼接。遇到攻击者故意拉长时间线、穿插白域名探测的时候,手工分析基本等于大海捞针。
攻击流量溯源图谱要解决的就是这个问题。它不是简单画一张拓扑图,而是把攻击行为涉及的实体和关系,从告警日志、网络会话、终端日志、DNS 记录中提取出来,组织成一张带证据锚点的关系图。有了这张图,你看到的不是孤立的“谁访问了谁”,而是攻击者从入口到内部再到出口的完整路径,每条边都能挂上对应的日志记录,随时可回溯。
1.2 选 SecGPT-14B 而不选通用大模型的理由
在 SecGPT-14B 出现之前,我们团队也试过两三条路。一是直接用通用的对话模型,让它读日志、给结论。效果不能说完全不行,但很不稳定。通用大模型没有经过安全语料的专门微调,分不清端口扫描和正常业务握手,经常把心跳包当成恶意流量,更严重的问题是它会“脑补”:日志里明明没有出现过主机 D,为了把故事讲圆,它可能推断出一个并不存在的中间跳板。
二是传统的图计算方案,比如把日志导入图数据库,写一批查询语句,人工定义实体抽取规则。这个方案稳,但维护成本高:每接入一种新日志格式就得改解析规则,攻击者换一个攻击手法,规则就要重新调,做起来很累人。
SecGPT-14B 的定位介于两者之间。它接受的是安全分析任务专用训练,输入输出都围绕威胁检测、实体关联、攻击阶段识别来做,解析能力、意图判断能力比通用模型稳很多。14B 参数规模又意味着它能在中等性能的服务器上跑起来,不需要动不动上几十张卡。我们用它主要是为了三件事:把文本日志结构化抽取出来、把多源实体做归一化关联、把时间线和因果逻辑组织成攻击链视图。这三个能力叠加,恰好覆盖了手工分析最耗时的那部分。
提示:我不是说通用大模型完全不能做安全分析,而是说在溯源这种对准确性要求极高的场景里,通用模型需要写非常复杂的约束提示词才能勉强控制输出质量。安全专用模型在相同条件下出结果的稳定性和可解释性明显更好,至少在我们的测试里是这样。
2. 核心原理:图谱如何生长,攻击链如何串联
2.1 图谱的节点、边和证据锚点
攻击流量溯源图谱,本质上是一个知识图谱,只不过它的领域限定在了“一次或一组攻击事件”里。图里有两种基本元素:节点和边。节点是实体,常见的包括 IP 地址、域名、URL、用户账号、主机名、进程名、文件哈希;边是关系,常见的有“IP A 连接了 IP B”“主机 A 执行了文件 B”“账号 C 登录了主机 D”“域名 X 解析到了 IP Y”。
只看这一步,有人会问:这不就是数据库里的关联查询吗?关键差异在“证据锚点”。图谱里每一条边都对应一条或一组原始日志,边上有时间戳、日志 ID、原始字段值。比如“IP A 连接了 IP B”这条边,证据是某防火墙会话日志里的一条记录,记录写着 A 到 B 的 443 端口握手成功,时间精确到秒。有了证据锚点,这张图就不是凭空生成的,图表上的任何一个环节,分析人员都能点回去看原始日志,这也是应急处置里最看重的一点。
SecGPT-14B 处理图谱构建时,第一步做的就是实体抽取和实体归一化。日志里同一个主机可能出现过三种写法:内网地址、主机名、登录账号后缀,模型要把它们合并成一个节点。这一步很多图数据库方案会做,但规则很难覆盖所有写法。一个比较典型的例子:某台机器在防火墙日志里叫 192.168.1.10,在 AD 日志里叫 WEB-SRV-01,在终端日志里又出现一个账户 WIN-SRV-01\admin。传统规则需要提前维护映射表,而模型可以基于上下文推断出这些写法指代的是同一实体,然后统一挂到同一个节点下。
2.2 从时间线到因果链:攻击链还原的推理逻辑
攻击流量溯源图谱解决的是“谁和谁发生了关系”,攻击链自动还原解决的是“这些关系按什么顺序、为什么串成了一条攻击过程”。这就不能只看单条边的存在性,还要看时间先后和因果逻辑。
攻击链还原的第一步是给图中边排时间序。模型逐条读取边的证据锚点,把时间戳从小到大排序。这个步骤看着简单,但很关键,因为攻击者在真实攻击中经常做端口扫描、漏洞探测、权限获取、横向移动、数据外传,各项动作有时间差,有些恶意行为甚至故意穿插在正常业务流量中间,不按边界对齐就会把顺序全搞反。
第二步是阶段归因。我们把网络安全里常见的攻击阶段定义成若干个环节,比如探测侦察、初始攻陷、权限提升、内网横移、数据收集、外带传输,然后让模型把每条边归到对应阶段。归因时模型会综合端口类型、协议行为、目标性质去判断:源 IP 对多个主机发起 445 端口扫描,大概率属于侦察;内网主机从公网下载一个罕见文件并执行,更像是初始攻陷或权限提升;一台数据库服务器主动向外部云存储上传大量数据,则是典型的数据外带。
第三步是因果校验。假设模型把边 E1 和 E2 归成了一个链,但要检验 E2 是不是真的由 E1 引起,至少要满足几条约束:E1 的时间戳早于 E2;E1 涉及的至少一个实体在 E2 里再次出现;两个阶段之间存在合理的攻击行为逻辑,比如“先扫描到漏洞端口,再发起利用请求”是合理的,而“先横向移动、再扫描漏洞端口”就违背了攻击常识。SecGPT-14B 会把检验不通过的链打上低置信度标记,而不是直接删除,这样分析人员还能看到这些线索,决定是否需要人工复核。
2.3 置信度打分与人为干扰的抑制
大模型输出文本时,天然自带“生成性”,哪怕它不确定也会把话说完。所以我们在设计还原流程时,强制要求模型对每一个还原出的攻击链给出置信度评分,并且只有分数超过阈值的链才会自动标注为“高置信攻击链”,其余一律进入待人工复核清单。
置信度评分不是模型随便拍脑袋给出的数字,而是由几个因素合成出来:证据覆盖度(一条链上有多少条原始日志作为支撑,覆盖度越高,分数越高)、时间紧密性(相邻阶段时间间隔是否合理,过度紧凑或过度松弛都会扣分)、因果完备性(是否出现了阶段跳跃,比如前一阶段还在扫描、下一阶段突然就开始数据外带,中间缺少利用和提权环节,这种跳变必须扣分)、实体唯一性(同一实体是否反复出现在链的不同阶段,同一实体在所有阶段都只出现一次并不能说明问题,但关键跳板主机多次出现,通常说明链比较完整)。
举个例子来说明人为干扰。有一次,某系统入口服务器的 SSH 登录日志里出现一条来自境外 IP 的失败记录,通用模型很容易把它当成攻击链的第一环。但 SecGPT-14B 在证据锚点里发现这条失败记录只出现一次,没有后续的爆破递增、没有成功登录、也没有命令执行痕迹,于是把这条链的置信度打成极低,最终归为噪声。这类误报过滤,对实际运营的帮助非常大。
3. 完整实操:把原始日志变成可视化溯源图谱
3.1 接入数据前先做字段标准化
正式使用 SecGPT-14B 之前,数据预处理这关必须做扎实。你不做标准化,模型就得同时面对十来种完全不一样的日志格式:防火墙的字段分隔符是竖线,DNS 日志是空格分隔,Windows 安全日志又带着大段 XML。上下文窗口再大,也经不起这些噪音消耗。
我们团队的做法是:先写一套轻量级解析脚本,把多源日志统一转成一种 JSON Lines 格式,保留最核心的字段。五个必留字段是:时间戳、源 IP、目标 IP、协议、动作。其他字段按日志类型可选,但也要尽量标准化成统一命名,比如“目标域名”统一叫 dst_domain,“用户账号”统一叫 account,“文件哈希”统一叫 file_hash。字段名一乱,后面让模型做实体归一化时,它要把同样的语义对应起来,容易出现遗漏。
标准化之后还有一步:过滤冗余。不是所有人都愿意做这一步,但我强烈建议做。比如防火墙每隔几秒产生的 keep-alive 会话,扫描器产生的全量端口探测包,这些数据量巨大但对攻击链还原没什么贡献。我们会在预处理阶段设置白名单和降噪规则,先把明显不相关的会话滤掉,保留的日志再做时间分段。以我们常用的三天窗口为例,过滤后大概能从几十万条日志压缩到 3 到 5万条左右,大大减轻了上下文压力。
3.2 提示词结构与关键参数配置
使用 SecGPT-14B 时,提示词结构直接决定输出质量。我们把它拆成四个部分:角色设定、分析任务、输入数据、输出格式约束。缺一个都不行。角色设定要写明“你是资深威胁分析师,专注于基于日志的溯源分析”,目的是把模型拉入安全分析语境;分析任务要明确列出“提取实体、构建关系、划分攻击阶段、生成攻击链”;输入数据直接贴上面标准化好的日志片段;输出格式则用 JSON Schema 固定下来,不允许自由发挥。
下面是我们实际用的提示词模板简化版:
你是资深威胁分析师,长期从事网络安全事件溯源与攻击链分析。请根据以下日志记录完成三个任务: 1. 提取所有安全相关实体,并给出每类实体的关键字段; 2. 识别实体之间的访问、登录、执行等关系,注明关系对应的事件时间; 3. 基于时间线判断攻击链阶段,输出完整的攻击链,必要时可以标注置信度。 日志记录如下(已按时间排序): {trace_logs} 请以JSON格式输出,必须包含 nodes、edges、attack_chain 三个字段,不要输出多余解释。这里的 {trace_logs} 就是我们前面预处理完的日志片段。注意我们没有塞进去全部几十万条,而是先按“攻击时间窗口+关联跳数”做了一个初步筛选,只保留与初始告警相关的主机、IP、账号附近两跳之内的记录,大概两三千条。两跳以内的意思就是:初始告警中出现的源 IP 和目标 IP 算一跳,与它们直接相连的其他实体算一跳之后的延伸。这个范围足够覆盖大多数攻击链的核心部分,又不至于把上下文撑爆。
参数设置方面,我们用的核心配置是:温度设为 0.1。安全分析属于典型的高要求准确率任务,温度越低,模型每次给出的结果越稳定,虽然牺牲了一点创造性,但这里不需要创造性。最大输出长度要看预期的图谱大小,通常设 8192 到 12万,以防模型因为输出截断把一张图拆成两半。解码策略我们没做太多微调,保持官方推荐值即可。重点要调的反而是输入端的处理:上下文窗口有限,不要把无关日志塞进去,宁可少塞一点,也要保证输入数据是有序且完整的。
3.3 输出格式约定和后处理校验
SecGPT-14B 给有风险的是结构化输出,我们行不行,在于你后面有没有做严格校验。我们给模型定了三个字段:
{ "nodes": [ {"id": "node-1", "type": "ip", "value": "192.168.1.10", "properties": {"hostname": "WEB-SRV-01"}}, {"id": "node-2", "type": "file", "value": "unknown.exe", "properties": {"md5": "abcdef..."}} ], "edges": [ {"source": "node-1", "target": "node-2", "relation": "executed", "timestamp": "2024-03-15 08:32:11", "evidence": "log-id-88453"} ], "attack_chain": [ {"stage": "recon", "edge_ids": ["edge-1"], "confidence": 0.9}, {"stage": "initial-access", "edge_ids": ["edge-2"], "confidence": 0.85} ] }拿到 JSON 之后,我们不会直接拿去渲染,而是先做三层校验。第一层是格式校验,看 JSON 能否正常解析、字段是否齐全、类型是否符合约定。第二层是引用一致性校验,检查 attack_chain 里的 edge_ids 是否都能在 edges 中找到,edges 里的 source 和 target 是否都能在 nodes 中找到,如果模型输出了一条边引用了不存在的节点,我们会自动丢弃或重新请求补全。第三层是时间序校验,把 attack_chain 中的边按时间戳排一遍,只有时间严格递增的链才进入最终展示列表。
最后一步是把图谱送进可视化工具,我们这边用的是图关系展示组件,节点布局按攻击阶段分层:最左是外部攻击源,中间是入口和内网跳板,最右是数据出口。图中每个节点和边都能点击查看证据详情。这一步虽然简单,却对运营人员非常友好,他们不用再一个个翻日志,直接看图就能聊处置方案。
4. 实战演练:一次内网横移事件的全过程还原
4.1 初始告警与信息收集
这次事件发生在某企业内网环境,初始告警来自终端检测平台:一台研发网段的 Windows 服务器弹出恶意文件检测,文件路径在临时目录下,哈希被情报平台标记为恶意。这个告警如果单独看,只是终端上封掉一个文件的事,但我们没有停在单点处置上,而是拉取了事发前后七十二小时的原始日志,包括防火墙会话日志、DNS 解析日志、AD 域控登录日志、终端进程日志。整理后的数据量大概四万六千条,按三小时分段时间分别喂给 SecGPT-14B 去分析。
初始信息里最明显的可疑点是:恶意文件出现前两小时,研发网段一台跳板机上的本地管理员账号发生过一次异常登录,登录来源 IP 是一个从未在该网段出现过的地址。同时,防火墙日志显示这个来源 IP 当天的前半段还在对研发网段多个主机发起 445 端口扫描。这两条线索加在一起,基本可以推断是一次有预谋的横向移动尝试,但具体攻击路径和最终目标还看不清楚。
我们没有急着下结论,而是先把初始告警里的恶意文件哈希、异常登录 IP、扫描源 IP 三个实体作为起点,输入给 SecGPT-14B,让它围绕这三个实体做实体关联和时间流程分析。这里有个经验:与其让模型漫无目的地分析所有日志,不如先选一组高价值的种子节点,让模型围绕它们扩展,输出会精准很多。
4.2 SecGPT-14B 产出溯源图谱
模型给出的图谱共识别出 24 个节点和 58 条边。节点里包括 9 个内网 IP、3 个公网 IP、4 个域名、2 个文件哈希、2 个用户账号、其他若干资产标识。图谱一眼看去,整个攻击路径非常清楚:公网 IP A 先对研发网段做端口扫描,命中一台暴露了远程桌面服务的 Windows 主机;随后通过弱口令爆破成功登录,写入恶意文件;恶意文件执行后回连到公网 IP A 控制端,下载了第二个工具集;第二个工具集在内网做了横向传播,登录了另一台数据库运维主机;最后这台数据库运维主机批量访问了数据备份服务器的 SMB 共享。
这里最值钱的不是那一串 IP,而是“边的证据锚点”。模型在图谱里对每条边都挂上了对应的日志 ID,我们点开任意一跳,都能直接看到原始记录。比如“恶意文件回连控制端”这条边,证据是 DNS 日志里的一条域名解析记录加防火墙会话日志里的一次外联请求,时间只差几秒,完全吻合。这让整个图谱站得住脚,不是模型编出来的故事。
4.3 攻击链还原结果与处置闭环
攻击链还原出来的结果一共分为五个阶段,每个阶段都有独立的置信度评分:
| 阶段 | 关键事件 | 涉及实体 | 置信度 |
|---|---|---|---|
| 侦查探测 | 公网 IP A 扫描研发网段 445 端口 | 公网 IP A、多个内网主机 IP | 0.92 |
| 初始攻陷 | 爆破远程桌面服务并成功登录 | 公网 IP A、Windows 主机、本地管理员账号 | 0.88 |
| 权限维持 | 写入恶意文件并回连控制端 | 恶意文件哈希、控制端域名、公网 IP B | 0.95 |
| 横向移动 | 使用管理员账号登录数据库运维主机 | Windows 主机、数据库运维主机、账号 | 0.84 |
| 数据外带 | 访问数据备份服务器 SMB 共享并大量拉取文件 | 数据库运维主机、备份服务器、共享目录路径 | 0.78 |
这个结果直接改变了处置优先级。以前遇到这种告警,第一反应就是隔离那台弹出恶意文件的服务器,但攻击链告诉我们:数据已经被拖到了备份服务器层面,只隔离单台机器根本不够。我们按图谱顺序做了闭环处置:先封锁公网 IP A 和 B 的出口连接,再下线那台 Windows 主机做镜像取证,然后重置所有被入侵账号密码,最后在备份服务器上检查文件访问记录,确认外带范围。
从这次实战效果看,攻击链还原的价值不只是响应,更在于后续加固。拿到一张完整的攻击路径图,你可以很清晰地看到:爆破入口的弱口令问题、管理员账号复用问题、备份服务器权限过宽问题,这些都是图谱里具体边对应的短板,逐条修下去,才能堵住下一次同类攻击。
5. 排错实录与调优速查
5.1 常见失败模式汇总
任何大模型在实际生产环境里都不会一次跑通。我们前前后后调试了两周,遇到了几个高频问题,在这里列一个速查表,供后面接手的团队参考。
| 问题 | 典型表现 | 排查思路 | 我们的解决方法 |
|---|---|---|---|
| 上下文溢出 | 输入日志过多,模型输出中断或遗忘早期信息 | 检查输入 token 是否超限,优先压缩无关数据 | 按时间窗口和关联跳数筛选,只保留种子实体两跳内的日志 |
| 输出 JSON 非法 | 模型返回内容不满足 JSON 格式,或字段缺失 | 看返回结果是截断还是格式错乱 | 增加格式约束提示,启用后处理解析,解析失败自动重试一次 |
| 实体名不一致 | 同一个 IP 在 nodes 里出现多个不同 id | 检查实体归一化逻辑是否生效 | 在提示词里增加“同一实体只允许出现一个节点”的指令,并做后处理合并 |
| 攻击链断裂 | 缺少中间阶段,比如没有初始攻陷直接跳到横向移动 | 检查输入日志是否遗漏了关键时段 | 扩大时间窗口,补充 AD 登录日志和终端进程日志 |
| 低置信度误报 | 模型把单次扫描当成攻击链起点 | 看边的证据覆盖和时间紧密度 | 调整置信度阈值,对只有一条证据且后续无动作的边降权 |
这里特别要提醒的是“攻击链断裂”问题。有一次我们只给了防火墙会话日志,结果还原出来的链总是缺初始攻陷环节,排查半天才发现问题不在模型,而在于防火墙日志只记录了网络层连接,看不到远程桌面登录成功和文件落地的过程。后来把终端日志和 AD 域控日志也接进来,链条马上就完整了。
5.2 调优要点与实际经验
下面这几条经验,是我们跑了大量真实数据后沉淀下来的,常规文档里一般不会写。
第一,不要迷信一次出图。我们实际工作中,几乎每一条完整攻击链都不是一次输出就到位了。SecGPT-14B 的多轮对话能力可以充分利用起来:第一轮先出实体图谱,第二轮针对图谱里的存疑节点提问,第三轮再让它补全攻击链。这种多轮拆解的方式,比把所有要求一次性塞进提示词里稳定得多。
第二,时间窗口是攻击链还原最重要的超参数。窗口太小,中间环节会断;窗口太大,日志噪音会淹没关键线索。我们三天的默认值,是针对大多数内部网络的访问节奏设定的。如果遇到攻击者明显在刻意拉长时间线,比如每天只做一步操作,那就要把窗口扩到七天甚至更长。窗口的设置直接决定模型能看到多少因果上下文,宁可在预处理阶段多做几次尝试,也不要从一开始就固定死。
第三,保留“低置信度”元素而不是让模型强行补全。大模型为了完成输出,在链不完整的时候倾向于猜一个中间环节。我们给 SecGPT-14B 的指令里特别加了一条:如果某条链中间缺失证据节点,不要猜测补充,直接在对应位置标注 unknown。这个策略对实际判断很重要,因为未知本身就是一种信息,它提示你去翻更多日志找那个失落的节点,而不是被骗进一条看似完整其实虚构的链路里。
第四,人工复核永远需要。这不是客套话。SecGPT-14B 可以把分析时间从小时级压缩到分钟级,但它对新型攻击变体的适应性仍然依赖训练数据。在我们遇到的一次钓鱼邮件案例里,模型把带附件的邮件误归为普通文档传输,经提醒后才发现附件带有恶意宏。这类误判虽然不常出现,但一旦出现,影响都不小。所以在最终处置环节,我们始终保留一名资深分析师对高置信度攻击链做人工抽验,尤其是涉及数据外带和权限变化的环节。
第五,迭代时把“图”当作分析对象,而不是结论。很多团队拿到一张生成的溯源图,就急着拿去汇报,我建议反过来:先把它当作分析线索,去验证每条边的原始证据,再去修改和重跑。我们现在的流程是模型先出图,运营人员对图里的每个高风险边做点验,确认无误后生成正式报告。这样既发挥了模型的高速处理能力,又保住了人工分析的可信度。
我个人在实际操作中的体会是,SecGPT-14B 这类安全模型最舒服的使用姿势,不是让它替代分析师,而是让它替代分析师的“重复劳动”:读日志、提实体、列关系、排时间线。它把这些脏活累活干完之后,分析师只需要把精力放在最有价值的两件事上:判断链的合理性,以及决定处置动作。这比起以前一整个下午被埋在几万行日志里,效率提升确实不是一个量级。后续我们还在试一个扩展:把还原出来的攻击链结构化信息存成图谱数据,沉淀成外部攻击特征库,下次再碰到类似的攻击模式,直接从库里检索,连第一步分析都能省掉。这个方向我觉得很有潜力,做出来以后再来分享。