ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于workbuddy与双模型驱动的漏洞扫描Agent实战

基于workbuddy与双模型驱动的漏洞扫描Agent实战 1. 为什么我要自己造一个漏洞扫描 Agent做安全审计这行的朋友应该都有体会传统漏洞扫描器的日子越来越不好过了。Nessus、AWVS、Xray 这些工具我用了快八年它们确实能跑出成千上万条告警但真正有价值的那几条往往淹没在误报的海洋里。一个中等规模的 Web 项目扫一遍下来两三千条告警是常态其中 SQL 注入误报能占四成XSS 反射型误报更是离谱。你让一个刚入行的安全工程师去逐条研判一天下来眼睛都花了最后真正能确认的高危漏洞可能就三五个。这个痛点催生了我用 workbuddy 搭建漏洞扫描 Agent 的想法。核心思路很直接让 AI 来做告警的二次研判和上下文关联分析把传统扫描器的规则匹配能力跟大模型的语义理解能力结合起来。我选了两个模型做双驱动——DeepSeek 负责深度推理和漏洞链分析laya 负责快速分类和优先级排序。整个 Agent 跑在 workbuddy 这个开发框架上它提供的 skill 机制和工具调用能力让整个流程编排变得非常顺手。这个 Agent 解决的核心问题有三个。第一是误报过滤通过语义分析判断告警是否真实可利用第二是漏洞链关联把单个低危漏洞串成完整攻击路径第三是修复建议生成针对具体代码上下文给出可落地的修补方案。适合有安全基础但想提升效率的工程师也适合想了解 AI Agent 在安全领域落地的开发者。下面我把整个搭建过程、踩过的坑和调优经验完整分享出来。2. 整体架构设计与双模型选型逻辑2.1 为什么是 DeepSeek 加 laya 的双模型组合单模型方案我试过不管是纯 DeepSeek 还是纯 laya都有明显短板。DeepSeek 的推理深度足够但响应速度在批量处理场景下会成为瓶颈扫一个中型项目动辄几百条告警每条都走深度推理时间成本扛不住。laya 的响应快、分类准但遇到需要多步推理的漏洞链分析就力不从心它更擅长模式识别而非逻辑推演。双模型的分工逻辑是这样的laya 做第一道过滤把明显误报和低价值告警快速剔除同时给剩余告警打上初步的严重等级标签。这一步的吞吐量要求高laya 的轻量特性正好匹配。然后 DeepSeek 接手做深度分析对 laya 筛选后的告警进行上下文关联、攻击路径推演和修复方案生成。实测下来这个两级过滤能把需要深度分析的告警量压缩到原始数量的 15% 到 20%整体处理时间比纯 DeepSeek 方案缩短了将近六成。注意双模型不是简单叠加关键在于设计好交接协议。laya 的输出格式必须结构化包含告警 ID、初步分类、置信度分数三个核心字段DeepSeek 才能高效接手。2.2 workbuddy 框架下的 Agent 编排设计workbuddy 的 skill 机制是我选它的主要原因。每个 skill 可以理解为一个独立的能力单元Agent 通过编排这些 skill 来完成复杂任务。我的设计里定义了四个核心 skill扫描器调用 skill、告警解析 skill、模型推理 skill、报告生成 skill。扫描器调用 skill 负责对接底层扫描引擎我用的是 Xray 的被动扫描模式通过它的 API 获取原始告警数据。告警解析 skill 把不同扫描器的输出格式统一成内部标准结构这一步很关键因为后面模型推理依赖这个标准格式。模型推理 skill 封装了 laya 和 DeepSeek 的调用逻辑包括 prompt 模板管理、重试机制和结果缓存。报告生成 skill 把最终结果输出成 Markdown 和 JSON 两种格式方便集成到 CI 流程里。整个编排用 workbuddy 的 workflow 定义支持条件分支和并行执行。比如 laya 过滤阶段可以并行处理多条告警DeepSeek 深度分析阶段则按漏洞类型分组串行执行避免上下文混淆。2.3 数据流转与状态管理方案Agent 运行过程中的数据流转需要仔细设计。原始告警从扫描器出来是 JSON 格式经过解析 skill 后变成内部标准结构包含漏洞类型、URL、参数、payload、原始请求响应等字段。laya 处理后的输出会增加分类标签和置信度DeepSeek 处理后的输出会增加攻击路径、影响评估和修复建议。状态管理我用的是 workbuddy 内置的 context 对象每个告警在处理过程中会携带一个状态标记从 pending 到 filtered 再到 analyzed最后到 reported。这样设计的好处是支持断点续跑如果某个环节失败可以从上次的状态继续不用从头再来。对于大型项目扫描这个特性非常实用。3. 核心细节解析与实操要点3.1 告警解析 skill 的标准化设计告警解析是整个流程的地基这里做不好后面全乱。不同扫描器的输出格式差异很大Xray 的 JSON 结构跟 AWVS 的 XML 完全不是一回事。我的做法是定义一个内部标准结构包含以下核心字段{ alert_id: 唯一标识, vuln_type: 漏洞类型枚举, severity: 原始严重等级, target_url: 目标地址, parameter: 涉及参数, payload: 触发载荷, request: 原始请求, response: 原始响应, scanner: 来源扫描器, timestamp: 发现时间 }解析 skill 的核心逻辑是适配器模式每个扫描器对应一个适配器负责把原始格式转换成标准结构。这里有个细节要注意payload 字段可能包含特殊字符必须做转义处理否则后面传给模型时会破坏 prompt 结构。我踩过这个坑一个包含反引号的 payload 直接把 prompt 模板搞崩了模型输出完全乱套。实操心得解析阶段就要做去重相同 URL 加相同漏洞类型的告警只保留置信度最高的那条。Xray 经常对同一个注入点报多条告警不去重的话后面模型要重复分析很多遍。3.2 laya 快速过滤的 prompt 工程laya 这一层的目标是快速准确地把误报筛掉。prompt 设计上我用了 few-shot 的方式给模型展示几个典型的误报案例和真实漏洞案例让它学会区分模式。prompt 模板大致是这样的结构先说明任务背景然后给出判定标准接着是几个示例最后是待判定的告警数据。判定标准我总结了四条第一payload 是否真的触发了异常响应还是只是被 WAF 拦截返回了通用页面第二参数是否真的进入了后端处理逻辑还是只是前端校验第三响应内容是否包含数据库报错、堆栈信息等确凿证据第四漏洞类型与响应特征是否匹配比如 SQL 注入告警但响应里全是静态 HTML那基本可以判定为误报。laya 的输出要求是 JSON 格式包含 is_real 布尔值、confidence 浮点数、reason 字符串三个字段。confidence 低于 0.3 的直接丢弃0.3 到 0.7 的标记为待确认高于 0.7 的进入 DeepSeek 深度分析。这个阈值是我调了十几轮才定下来的太低会漏掉真实漏洞太高会放太多误报进下一轮。3.3 DeepSeek 深度分析的上下文构建DeepSeek 这一层要做的事情复杂得多需要构建足够的上下文才能做出准确判断。我的做法是把告警相关的信息组织成一个结构化的分析请求包含漏洞基本信息、原始请求响应、目标应用的指纹信息、以及同目标的其他告警作为关联参考。上下文构建有个关键技巧不要把整个响应体都塞进去那样 token 消耗太大而且引入噪音。我的做法是提取响应中的关键片段比如报错信息、数据库版本、框架特征等用正则匹配提取后再传给模型。实测下来这样能把 token 消耗降低 70% 以上同时分析准确率反而提升了因为模型不会被无关内容干扰。DeepSeek 的分析输出包含四个部分漏洞确认结论、攻击路径推演、影响范围评估、修复建议。攻击路径推演是重点比如一个文件上传漏洞DeepSeek 会分析上传后的文件是否可访问、是否可执行、能否结合其他漏洞提权。这部分是传统扫描器完全做不到的。3.4 双模型交接的协议设计两个模型之间的交接协议我改了三个版本才稳定下来。第一版直接用自然语言传递结果 DeepSeek 经常误解 laya 的分类意图。第二版用 JSON 但字段定义不严谨遇到边界情况就解析失败。第三版才定型定义了严格的 schema 和错误处理机制。交接数据结构包含alert_id 用于追踪、laya_verdict 包含分类结果和置信度、context_hints 是 laya 给出的分析提示、raw_data 是原始告警数据。DeepSeek 收到后先验证 schema不合法就触发重试或降级处理。降级策略是直接用原始告警数据做分析跳过 laya 的提示信息。注意交接协议里一定要包含版本号字段。模型更新或 prompt 调整后旧版本的处理结果可能不兼容有版本号才能做数据迁移和回溯。4. 实操过程与核心环节实现4.1 workbuddy 环境搭建与项目初始化workbuddy 的安装过程比较直接官方文档写得还算清楚。我是在 Ubuntu 22.04 上部署的Windows 环境下有些依赖会有兼容性问题建议用 WSL2 或者直接上 Linux。安装完成后先跑一个 hello world 级别的 skill 验证环境确认模型调用链路通畅。项目初始化用 workbuddy 的 CLI 工具它会生成标准的目录结构。我的项目结构是这样的skills 目录放四个核心 skill 的实现prompts 目录放模型 prompt 模板config 目录放扫描器和模型的配置data 目录放扫描结果和缓存logs 目录放运行日志。这个结构不是 workbuddy 强制的是我根据项目需要自己定的清晰的结构对后期维护帮助很大。配置文件里需要填的关键参数包括DeepSeek 的 API endpoint 和 key、laya 的调用地址、扫描器的 API 地址、并发数限制、超时时间、重试次数。并发数我设的是 laya 阶段 10 并发DeepSeek 阶段 3 并发这个配置在 8 核 16G 的机器上跑得很稳。4.2 扫描器对接与数据采集底层扫描器我选的是 Xray原因是它的被动扫描模式对业务影响小而且 API 比较完善。对接方式是通过 Xray 的 webhook 把告警实时推送到 Agent 的接收端点。这里有个细节Xray 的 webhook 推送频率可能很高需要做缓冲队列否则 Agent 处理不过来会丢数据。缓冲队列我用的是 Redis 的 list 结构Agent 从队列里消费告警。消费速率可以动态调整根据当前模型调用的响应时间来控制。如果 DeepSeek 响应变慢就降低消费速率避免队列积压导致内存暴涨。这个自适应机制在实际运行中很有用模型服务偶尔会有波动有了它整个系统不会崩。数据采集阶段还要注意去重和限流。同一个目标短时间内可能产生大量相似告警需要在入库前做去重。限流是针对单个目标的告警数量做上限控制避免某个目标把整个队列堵死。我设的单目标上限是 500 条超过的告警进入低优先级队列等主队列处理完再处理。4.3 laya 过滤阶段的完整实现laya 过滤 skill 的核心代码逻辑是这样的从队列取出一条告警加载 prompt 模板把告警数据填充进去调用 laya 接口解析返回结果根据置信度决定去向。整个过程要处理各种异常网络超时、返回格式错误、模型拒绝回答等。prompt 模板我放在独立文件里管理方便调整。模板里用了变量占位符运行时替换成实际数据。这里有个技巧把判定标准写在 prompt 最前面因为模型对开头内容的注意力权重更高。示例放在中间待判定数据放在最后这样模型能带着标准去看数据。laya 的调用我封装了一个带重试的客户端超时设 10 秒重试 2 次重试间隔指数退避。实测下来 laya 的响应时间中位数在 1.5 秒左右P99 在 4 秒左右10 秒超时足够覆盖绝大多数情况。重试机制主要应对偶发的网络抖动。过滤结果会写入一个中间表包含原始告警 ID、laya 判定结果、置信度、处理时间戳。这个中间表是后续分析和调优的重要依据通过它能看到 laya 的判定分布如果发现某个漏洞类型的误报率异常高就需要针对性调整 prompt。4.4 DeepSeek 深度分析的实现细节DeepSeek 分析 skill 比 laya 复杂得多因为要构建丰富的上下文。我的实现分三步第一步是上下文提取从原始告警和响应中提取关键信息第二步是关联分析查找同目标的其他告警作为参考第三步是调用 DeepSeek 并解析结果。上下文提取用了一组正则表达式针对不同类型的漏洞提取不同的特征。比如 SQL 注入提取数据库报错信息XSS 提取响应中的脚本上下文文件上传提取上传路径和返回信息。这些正则是我根据大量真实告警总结出来的覆盖了常见场景。关联分析是 DeepSeek 方案的亮点。比如发现一个 SSRF 漏洞同时目标上还有一个内网服务的信息泄露DeepSeek 会把两者关联起来分析 SSRF 能否利用信息泄露中暴露的内网地址。这种跨漏洞的关联分析是传统扫描器完全做不到的。DeepSeek 的调用参数我调过好几轮。temperature 设 0.1因为安全分析需要确定性输出不能太发散。max_tokens 设 2000足够生成详细的分析报告。top_p 设 0.9保持一定的多样性但不过度。这些参数在不同模型版本上可能需要微调建议先用小批量数据测试再全量跑。4.5 报告生成与 CI 集成报告生成 skill 把分析结果输出成两种格式。Markdown 格式用于人工阅读包含漏洞摘要、详细分析、修复建议三部分。JSON 格式用于 CI 集成包含结构化的漏洞数据和严重等级方便流水线做质量门禁。CI 集成的逻辑是如果发现高危漏洞且置信度高于 0.8直接阻断流水线并通知安全团队。中危漏洞记录但不阻断低危漏洞只记录。这个策略可以根据项目阶段调整开发阶段可以放宽上线前收紧。报告里我加了一个误报反馈链接点击后可以把误报标记回传给 Agent用于后续的模型调优。这个反馈闭环很重要运行一段时间后积累的反馈数据能显著提升过滤准确率。5. 常见问题与排查技巧实录5.1 模型调用超时与降级处理模型调用超时是最常见的问题尤其是 DeepSeek 在高峰期响应会变慢。我的处理策略是分级降级第一次超时重试第二次超时切换到备用模型第三次超时直接标记为待人工分析。备用模型我配的是 laya 的增强模式虽然分析深度不如 DeepSeek但至少能给出基础判断。超时阈值设置也有讲究。laya 设 10 秒DeepSeek 设 30 秒。这个不是拍脑袋定的是我统计了两周调用数据后根据 P99 响应时间加 50% 余量定的。设太短会频繁触发降级设太长会拖慢整体流程。实操心得给模型调用加一个熔断器连续失败超过阈值就暂停调用一段时间。我有次遇到 DeepSeek 服务端故障没有熔断机制导致 Agent 疯狂重试把配额全耗光了。5.2 告警数据格式异常的排查扫描器输出的告警数据偶尔会有格式异常比如字段缺失、类型不对、编码错误等。这类问题在解析阶段就要拦截不能让脏数据流到模型层。我的做法是在解析 skill 里加严格的数据校验不通过的告警记录到错误日志并跳过。常见的格式异常包括response 字段是 base64 编码的、payload 包含未转义的特殊字符、URL 包含中文需要编码等。这些情况我都写了对应的处理逻辑。base64 自动解码特殊字符转义URL 编码规范化。处理不了的记录到异常表定期人工review。5.3 模型输出格式不稳定的应对模型输出格式不稳定是 prompt 工程的经典难题。即使要求输出 JSON模型偶尔也会加一些解释性文字或者格式错误。我的应对策略是三层防护第一层在 prompt 里强调格式要求并给出示例第二层用正则提取 JSON 部分第三层解析失败时调用模型做格式修复。格式修复的 prompt 很简单就是把原始输出和期望格式一起给模型让它重新输出。这个修复调用用 laya 就行速度快成本低。实测下来三层防护能把格式问题的处理成功率做到 99% 以上。5.4 误报反馈闭环的建立误报反馈是持续优化的关键。我在报告里加了反馈入口安全工程师标记的误报会进入反馈表。定期用这些反馈数据做 few-shot 示例更新把典型误报加入 prompt 的示例部分。这个闭环运行两个月后laya 的过滤准确率从最初的 72% 提升到了 89%。反馈数据的处理要注意去敏不能把包含敏感信息的告警数据直接用于 prompt。我的做法是提取告警的特征模式而非原始数据比如响应为通用错误页面且无数据库特征这样的模式描述而不是具体的 URL 和 payload。5.5 性能调优与资源控制Agent 运行时的资源消耗需要监控和控制。主要消耗在模型调用和数据处理两块。模型调用受 API 配额限制数据处理受内存和 CPU 限制。我的监控方案是用 workbuddy 内置的 metrics 功能记录每个 skill 的调用次数、耗时、成功率。性能调优的几个关键点laya 阶段用批量调用减少网络开销DeepSeek 阶段用流式输出降低内存占用数据处理用生成器避免一次性加载大量数据。这些优化做完后Agent 处理 1000 条告警的时间从 45 分钟降到了 18 分钟。问题类型典型表现排查思路解决方案模型超时调用无响应或超时检查网络和模型服务状态重试加降级加熔断格式异常解析失败或字段缺失查看原始告警数据数据校验加异常跳过输出不稳定JSON 解析失败检查 prompt 和模型版本三层防护加格式修复误报率高大量告警被误判分析反馈数据更新 few-shot 示例性能瓶颈处理速度慢监控各环节耗时批量调用加流式输出6. 实际运行效果与调优经验这套 Agent 我在三个中型项目上跑了完整流程累计处理告警一万两千多条。laya 阶段过滤掉了约 78% 的告警剩余 22% 进入 DeepSeek 深度分析。DeepSeek 确认了其中约 35% 为真实漏洞其余标记为待确认或误报。最终输出到报告的高置信度漏洞有 180 多条其中高危 23 条中危 67 条低危 90 多条。跟纯人工研判对比效率提升非常明显。以前一个安全工程师研判一千条告警需要大约两天现在 Agent 处理加人工复核只需要半天。而且 Agent 的漏洞链分析能力是人工很难做到的它能把分散的低危漏洞串成完整攻击路径这个价值远超单纯的效率提升。调优过程中最大的收获是 prompt 的迭代方法。我建立了一个测试集包含 200 条标注好的告警数据每次调整 prompt 后都在测试集上跑一遍看准确率和召回率的变化。这个数据驱动的方法比凭感觉调 prompt 靠谱得多。测试集要定期更新加入新的误报案例和真实漏洞案例保持跟实际数据的分布一致。另一个经验是模型版本管理。DeepSeek 和 laya 都会更新版本新版本的行为可能有变化。我的做法是固定使用某个版本等新版本稳定后再做迁移测试。迁移测试就是在新版本上跑测试集对比准确率变化确认没有退化再切换。最后分享一个实用技巧给 Agent 加一个解释模式在报告里附上模型做出判断的推理过程。这个对安全工程师复核很有帮助能快速理解 Agent 的判断逻辑也方便发现 Agent 的认知偏差。解释模式的输出会增加一些 token 消耗但换来的是更高的可信度和更快的复核速度很值得。
返回列表