为什么有的 AI 能稳定挖漏洞,有的却只会“胡说八道”?

张开发
2026/4/7 19:14:33 15 分钟阅读

分享文章

为什么有的 AI 能稳定挖漏洞,有的却只会“胡说八道”?
这两年安全圈里关于“LLM 能不能做代码审计”的争论一直没停过。乐观派认为大模型已经能读代码、理解业务逻辑、识别危险模式拿它做漏洞挖掘只是时间问题悲观派则认为LLM 连完整调用链都经常追不明白更别说在大型 Java 项目里稳定挖 0day 了。这两种说法都没错但都没有说到根上。真正的问题从来不是 LLM 会不会审计代码而是它知不知道该如何系统地做代码审计。它当然能读懂 Java也能识别 SQL 注入、命令执行、反序列化这些典型危险模式甚至在局部推理上比很多初级审计员还快。但问题在于它没有审计员脑子里的那套“工作骨架”拿到项目先看什么攻击面怎么摸哪些模块优先扫发现可疑点后怎么追调用链什么时候该深挖什么时候该止损最后又怎么把结果整理成一份可信、可复现、可交付的报告。一个资深审计员做审计不是“想到哪审到哪”而是在执行一套多年实战沉淀下来的流程而裸跑的大模型往往只有能力没有纪律。所以这篇文章不讨论空泛的 Prompt 技巧也不讨论“AI 会不会取代审计员”这种老问题。我们真正要拆解的是如何给 LLM 装上一套“资深 Java 审计员的工作骨架”如何让它从随机游走式审计变成系统化、可控、可复现的审计引擎本文聚焦上篇流程设计与效率优化。重点讲清三件事裸跑 LLM 做 Java 审计到底差在哪Skill 驱动与裸跑的本质差异是什么一套经过实战验证的 6 阶段审计流水线是怎么设计出来的下篇再专门展开质量保障怎么压制幻觉、怎么做覆盖率门禁、怎么判断漏洞成立条件、怎么给结果排优先级。一、LLM 做代码审计到底行不行这个问题其实没那么复杂行但不能裸跑。说它行是因为 LLM 确实具备代码审计所需的很多基础能力。它能快速阅读 Java 项目结构识别 Controller、Service、DAO、Entity 的职责边界能从代码里感知危险操作比如Runtime.exec()、动态 SQL 拼接、危险反序列化链、模板渲染、表达式求值也能围绕数据流做初步推理判断一个参数是不是外部输入是否经过过滤最终有没有进入危险 sink。但说它不能裸跑是因为真正的代码审计从来不是“识别几个危险 API”那么简单。代码审计是一项高约束、高流程、高优先级管理的复杂工作。它要求你始终记住项目背景、组件依赖、认证体系、攻击面分布、关键入口、历史结论、可疑点优先级以及当前到底覆盖到了哪里、还有哪些文件没看。而裸跑 LLM 的问题恰恰就在这里它不是不会看代码而是不会像一个老审计员那样有章法地工作。换句话说LLM 缺的不是知识而是工作方法。这也是为什么同样一个模型有人拿它能稳定挖到高质量漏洞有人跑出来的却是一堆看起来很像回事、实际一验证全是幻觉的报告。差别不在模型本身而在于你有没有给它一套可以执行的“审计协议”。而这套协议就是这里说的Skill。二、Skill 不是 Prompt而是“审计协议”很多人一提到 Skill会下意识把它理解成“高级 Prompt 模板”。这其实低估了它的作用。Prompt 解决的是“这一轮怎么问”。Skill 解决的是“这整件事该怎么做”。如果说裸跑 LLM 像一个聪明但缺乏训练的新手那么 Skill 扮演的角色更像是把多年经验固化下来的“审计作战手册 流程引擎 质量规范”。它不负责教模型“什么是 SQL 注入”因为模型本来就知道。它真正做的是把资深审计员脑子里的那些隐性经验转化成明确、可执行、可检查的约束审计从哪一步开始中间结果存到哪里哪些模块优先哪些文件只做轻量扫描什么情况下升级为深挖如何验证 Source 到 Sink 的可达性哪些结论必须附带行号和证据哪些结果没有验证就绝不能写进最终报告所以更准确地说Skill 工作流 资源调度 分层分析 质量约束 输出规范它不是给模型“加知识”而是给模型“装骨架”。这个骨架一旦建立起来LLM 的表现就会从“偶尔灵光一现”变成“持续稳定输出”。三、裸跑 LLM 做 Java 审计究竟差在哪把一个 Java 项目直接丢给 Claude、GPT 或其他模型说一句“帮我做安全审计”大概率会出现下面这几类典型问题。1. 随机游走覆盖率极低裸跑 LLM 最常见的行为就是看几个它觉得“重要”的文件发现一个可疑点就一路深挖下去挖完再回来时已经忘了自己看过哪些模块、没看哪些模块。这种方式在几千行的小项目里可能还能凑合因为代码量不大哪怕乱走一圈覆盖率也不至于太差。但一旦进入十万行以上的 Java 项目这种审计方式就会迅速失控。它可能在一个 Controller 上花很多时间却根本没把相邻模块走完也可能沿着一个命令执行路径追得很深却把旁边整个认证链都漏掉。最后看起来“分析很深入”实际上只是对局部进行了超配审计对全局则接近失明。2. 幻觉高报告不可信这几乎是裸跑 LLM 在代码审计场景里最致命的问题。模型经常会“记得有这么个逻辑”但一具体到文件名、方法名、行号、参数名就开始混。于是你会看到这样的输出引用了不存在的方法把 A 类的方法说成 B 类调用的行号前后错位描述的数据流链条和实际代码不一致把相似代码块脑补成完整漏洞链在通用问答里这种幻觉或许只是体验差但在安全审计里幻觉直接意味着报告失真。一份不能复核、不能定位、不能复现的问题清单本质上就不算合格的审计输出。3. 深度失衡资源浪费严重裸跑模型还有一个问题它没有优先级感。它可能在一个 SQL 注入疑点上写出一大段极其详细的分析连 payload 都替你脑补出来却完全没去看隔壁那个更危险的认证绕过点也可能在一堆低风险 Entity 类上停留过久只因为这些类的字段命名碰巧触发了它的注意。这不是模型不努力而是它不知道什么是入口层代码什么是核心攻击面什么该逐文件深挖什么只需快速扫一遍什么一旦命中高危模式就必须立刻升级分析没有优先级框架算力和上下文就会被浪费在错误的地方。4. 上下文易断长任务后劲不足大型 Java 项目审计本质上是一个长任务。而长任务对 LLM 的考验从来不是“能不能理解一段代码”而是“能不能在数十轮分析后仍然保持一致的全局认知”。裸跑时模型在前半程建立起来的那些重要理解比如权限模型、认证中间件、通用输入封装、DAO 层写法、统一异常处理机制很容易在后半程逐渐遗失。于是你会看到前后判断标准不一致、漏洞命名不一致甚至前面确认过的假设在后面又被推翻。5. 结果不可复现工程价值低同样一个项目同样一句“帮我做审计”不同时间跑两次结论可能差很多。这意味着它很难纳入工程体系。裸跑 LLM 更像一次“概率性挖掘”。运气好真能撞出几个洞运气不好输出就完全不稳定。但真正要在企业里落地的审计体系要求的不是“偶尔很强”而是流程可重复结果可回溯结论可验证输出可交付这就是为什么裸跑 LLM 很难成为“生产工具”最多只能算“灵感辅助器”。四、裸跑和 Skill 驱动差的不是能力而是章法很多人看到这里会误以为 Skill 的作用是“提升模型能力”。其实不是。Skill 并没有把一个普通模型直接变成“安全大神”。它做的事情更像是把原本松散、随机、跳跃的能力组织成一套可控的系统。如果非要概括两者差别可以这么说裸跑 LLM 像一个天赋很好、读书很多、反应很快的新人Skill 驱动的 LLM则更像一个被流程、规范、方法论训练过的职业审计员。它们在局部推理上可能差不多但在整体执行效果上会出现明显质变覆盖率从“看运气”变成“门禁强制”幻觉从“随时可能冒出来”变成“被规则压制”优先级从“模型自己感觉”变成“体系明确规定”上下文从“模型记不记得”变成“文件持久化状态”报告从“风格漂移”变成“模板化标准输出”所以后面要讲的不是某个神奇 Prompt而是一整套让 AI 像工程师一样工作的设计。五、一套完整的 AI Java 审计流水线应该长什么样真正可落地的审计 Skill不是一段长 Prompt而是一条严格分阶段的流水线。这条流水线的核心思想很简单不要相信模型的记忆要相信流程和状态。也就是说所有关键中间结果都必须被持久化所有阶段都要有明确输入和输出模型只负责在每一阶段执行受约束的任务而不是靠“记住前面发生过什么”来维持整个审计过程。一个成熟的设计通常会分成 6 个阶段。Phase 0代码库度量这一阶段不是让 LLM 找漏洞而是做工程度量。用脚本统计项目的 LOC、文件数、模块分布、Controller 数量、Service 数量、配置文件比例等指标先建立一张基础代码库画像。这一层看起来不性感但极其重要。因为没有度量就无法做后续的资源分配也无法决定该投多少 Agent、优先扫哪一层。Phase 1项目侦察与资源规划在这一阶段不是直接开扫而是先建立项目的审计地图。比如识别项目是 Spring Boot、Spring MVC还是传统 Servlet 结构摸清入口层在哪里判断认证授权是注解式、过滤器式还是自定义拦截链识别配置文件、关键安全组件、第三方依赖调用模式进行 T1 / T2 / T3 分层为后续资源调度做准备这是从“代码堆”走向“有结构的目标”的关键一步。Phase 2全量分层审计这是整条流水线的核心阶段。每个 Agent 按照分配范围对文件逐个审计但不是所有文件一视同仁而是根据层级使用不同深度的分析策略。这一阶段通常同时结合Layer 1 的规则预扫描结果Layer 2 的 LLM 双轨审计Layer 3 的语义验证能力也就是说真正高效的审计不是“LLM 单干”而是规则、推理、验证三者协同。Phase 3覆盖率门禁与补扫这是很多“AI 审计方案”最容易忽略的一层。因为只要没有门禁所谓“全量审计”就只是口号。Phase 3 的职责就是回答下面这些问题所有目标文件是否都被读过所有 T1 文件是否完成深度分析所有高危候选点是否完成复核是否仍有关键路径未覆盖没过门禁就不能进入最终报告阶段。这一步本质上是在把“覆盖率”从一个抽象目标变成强制执行条件。Phase 4规则沉淀对已经确认的漏洞模式做抽象把它们转换为静态规则例如 Semgrep 规则或内部规则引擎配置。它的意义不只在当前项目而在后续复用下次遇到类似项目可直接复扫可集成进 CI/CD 做持续检测可作为组织知识库积累这一步让单次审计从“项目交付”升级为“组织能力沉淀”。Phase 5标准化报告生成最后一步不是让模型自由发挥写作文而是基于预定义模板从确认后的结果中生成完整报告。通常包括Executive Summary漏洞描述影响范围触发条件调用链证据可利用性判断修复建议优先级评分这一阶段的重点不是“写得多漂亮”而是“输出必须稳定、完整、可交付”。六、EALOC把算力花在真正值得审的代码上做大型 Java 项目审计时一个现实问题很快就会冒出来并不是所有代码都值得花同样的分析成本。一个典型的 Java Web 项目里真正直接暴露给攻击者的代码通常只占整个代码库的一小部分。大量代码其实是Entity / DTO / VO简单数据映射类纯配置载体低风险工具封装这些代码不能说完全没风险但显然不值得和 Controller、Filter、Security 配置、核心 Service 一样逐行深挖。如果仍然按原始 LOC 平均投入审计资源就会出现一个很荒唐的现象大量时间被消耗在低风险区域而真正的攻击面没有得到足够深度的分析。这就是 EALOC 要解决的问题。什么是 EALOC它不是原始代码行数而是“有效审计代码量”。核心思想是不同层级代码按照不同权重计入审计工作量。一种常见设计是把代码分成三层T1Controller、Filter、Interceptor、SecurityConfig、外部接口入口等T2Service、DAO、Mapper、Util、配置文件等T3Entity、VO、DTO、POJO 等数据模型层然后定义一个加权公式EALOC T1 × 1.0 T2 × 0.5 T3 × 0.1这个公式背后的逻辑非常符合实际审计经验T1 是外部攻击面必须深挖T2 是业务逻辑中枢需要重点看关键路径T3 大多是低风险承载类通常只需轻量模式匹配这样一来一个原始 LOC 很大的项目实际“有效审计工作量”会大幅下降但覆盖质量并不会跟着下降。EALOC 真正解决的不只是算力问题它不是简单“省算力”而是在做一件更重要的事把资深审计员的经验判断转化为可以量化执行的资源调度模型。过去一个老审计员凭经验就知道“这类文件不用逐行看”现在这件事被明确写进了系统规则里。这一步非常关键。因为一旦经验无法被量化它就无法稳定复制也无法交给 AI 执行。分层规则不能拍脑袋代码分层也不能靠“看起来像什么就归什么”而应该有一套优先级明确的规则体系。比如第三方库源码直接跳过不审源码本体审调用方式Layer 1 命中高危候选动态提升优先级带Controller/RestController/Filter等标记归 T1带Service/Repository/Mapper归 T2类名含Util/Helper/Handler归 T2带Entity/Table/Data归 T3未命中任何规则默认归 T2而不是 T3这里最重要的原则只有一个宁可保守不可误降级。因为误把高风险代码丢到低优先级层损失的不是一点算力而是整条漏洞链可能被漏掉。七、三层审计架构机器扫广度AI 挖深度语义做验证真正稳定的 AI 代码审计不可能只靠一个 LLM 从头看到尾。原因很简单规则引擎擅长广度覆盖LLM 擅长语义理解和局部推理语义分析工具擅长精确追踪调用关系。这三种能力各有边界缺一不可。所以合理的设计一定是一个三层架构。Layer 1全量预扫描解决“广度”问题第一层尽量不用 LLM而是用规则和脚本扫全量代码。常见手段包括ripgrepSemgrep自定义 grep / AST 模式匹配XML / YAML / properties 配置扫描这一层的目标不是直接下漏洞结论而是先把“危险区域”粗筛出来告诉后面的 Agent哪些文件命中了高风险模式哪些地方可能存在危险 sink哪些配置看起来不安全哪些入口值得优先关注比如在 Java 场景下P0 级规则就不能只扫Runtime.exec()而应该覆盖一整套危险面原生命令执行各类反序列化入口模板渲染引擎表达式注入JNDI 使用动态类加载反射执行同时还要考虑 Java 生态的历史问题比如javax.*和jakarta.*两套命名空间并存否则规则覆盖天然不完整。Layer 1 的输出是“参考坐标”不是最终结论。它的作用是帮助后面提高效率而不是替代后续分析。Layer 2LLM 双轨审计解决“理解与挖掘”问题真正体现大模型价值的是第二层。在这一层里每个 Agent 对分配给它的文件执行两条并行审计轨道。第一条轨道Sink-driven从危险操作往上追。比如发现Runtime.exec(cmd)Statement.executeQuery(sql)ObjectInputStream.readObject()TemplateEngine.process()接下来就要问参数从哪来有没有经过过滤过滤是否有效有没有拼接、反射、隐式转换等绕过空间最终是不是可被外部输入控制这条轨道擅长找“有危险代码的地方”。第二条轨道Control-driven从入口往下看“该有的安全控制是否存在”。比如发现一个对外暴露的接口就要判断是否有认证是否有鉴权是否有角色边界是否有输入校验是否存在跨租户或越权问题是否依赖前端校验而后端缺失约束这条轨道尤其重要因为很多高质量漏洞并不是某一行代码写错了而是系统缺少了本应存在的安全控制。这也是裸跑模型最容易漏的一类问题。因为它天然更容易被“危险 API”吸引而不是主动发现“少了什么”。双轨并行才更接近真实审计逻辑。一个成熟审计员做审计时脑子里本来就同时在跑这两套逻辑一条是“哪里有危险行为”一条是“哪里少了应有控制”如果只有前者没有后者你会漏掉大量认证绕过、权限缺失、业务逻辑失控类问题如果只有后者没有前者你又会漏掉真正可触发的技术漏洞。Layer 3语义验证解决“到底成不成立”问题Layer 2 找到的是候选点但候选不等于成立。真正进入最终报告前必须有一层专门做语义级验证。最理想的能力是 LSP 或其他语义分析能力比如go to definitionfind referenceshover 类型信息调用关系追踪变量来源确认验证流程通常是找到疑似 sink定位该 sink 的真实实现向上追调用者确认中间变量类型与转换判断是否能追到实际 source判断中间是否存在有效 sanitization 或控制点最终输出的不该是“我觉得这里可能有问题”而应该是哪个 source通过哪些方法调用链到达哪个 sink每一跳在什么文件什么位置中间有没有安全控制为什么这些控制无效或可绕过当 LSP 不可用时当然也可以退化为 grep 手动追踪但精度和效率都会明显下降。所以 Layer 3 的存在本质上是在给 LLM 的推理“落地生根”防止它停留在概率判断层面。八、不同层级代码为什么必须区别对待三层架构解决的是“能力分工”问题但每个文件到底分析到什么深度还要结合代码分层来决定。这就是为什么 T1、T2、T3 不只是资源调度概念它还直接决定了审计深度。T1入口层必须做完整分析T1 主要包括ControllerFilterInterceptorSecurity Config对外 API 入口负责请求接入和权限校验的关键组件这些文件是攻击者最先接触到的代码必须执行完整分析通常至少包括数据流安全控制敏感操作自定义危险封装配置初始化业务逻辑约束端点枚举安全控制绕过假设在这里审计不是简单扫“危险函数”而是要站在攻击者视角把每个入口当成潜在突破点。T2业务中间层聚焦关键维度T2 主要包括ServiceDAOMapperUtil配置文件这一层不直接暴露给外部但它决定了数据怎么流转、危险操作怎么被封装、安全控制有没有真正落到实处。所以 T2 通常聚焦数据流危险操作安全控制它不需要像 T1 那样逐项展开但也绝不能只是“扫一下关键字”。T3模型层快速匹配即可T3 一般是EntityDTOVOPOJO这层大部分都是低风险代码所以不值得投入完整深度分析。但也不是完全跳过因为这里依然可能藏着Mass Assignment敏感字段暴露序列化泄露被框架自动绑定导致的业务风险所以 T3 更适合做快速模式匹配。动态升级机制很关键分层不是写死的。一个 T2 文件如果命中了高危模式比如危险命令执行封装、无校验动态 SQL 生成就应该立刻提升为 T1 深度分析一个 T3 文件如果出现了复杂业务方法也不能再按“低风险模型类”对待。这一步的意义在于分层是为了优化资源不是为了降低警觉。九、这套体系真正解决了什么问题把上面的设计拼起来就能看清它真正解决的不是“让 AI 更聪明”而是让 AI 更像一个合格的审计工程师。1. 它解决了覆盖率问题裸跑 LLM 的覆盖率看运气分层、分配、门禁、补扫机制则把覆盖率从“主观希望”变成“硬性要求”。2. 它解决了资源浪费问题不是所有代码都值得逐行深挖。EALOC 让资源投向真正高风险区域避免在低风险模型类上空耗上下文和算力。3. 它解决了幻觉问题通过分阶段执行、证据绑定、语义验证、状态持久化模型输出会被持续约束。它不再能随意“脑补一段调用链”就写进报告。4. 它解决了长任务崩坏问题中间结果落盘阶段状态持久化意味着上下文不再完全依赖模型记忆。模型遗忘不再等于项目失忆。5. 它解决了结果不可复现的问题固定的阶段、固定的规则、固定的输出格式让审计结果开始具备工程稳定性。到了这一步它才真正有资格进入团队协作、项目交付和产品化体系。十、AI 不会替代审计员但会淘汰“没有方法论的审计方式”很多人最关心的问题其实不是“这套体系怎么设计”而是代码审计工程师在 AI 时代到底会不会被替代我的判断是短期内不会长期看也不是“被替代”这么简单。因为大模型再强也只是把“能力”摊开放在你面前。真正把这些能力组织成生产力的仍然是方法论、流程设计、验证机制和优先级判断。换句话说未来更有价值的审计工程师不一定是那个手工追每一条调用链追得最快的人而是那个能定义下面这些事情的人审计流程怎么跑资源如何调度哪类问题必须优先验证哪些结论没有证据不能落报告如何把一次审计沉淀成团队规则和工具能力AI 会大幅压缩“纯体力型审计”的空间但会放大“体系设计型审计员”“方法论型审计员”“验证型审计员”的价值。所以从这个角度看Skill 体系的意义不只是为了让 AI 更会审计也是在重新定义审计工程师在新阶段的能力锚点。结语Skill 的本质是把“经验”变成“系统”回到最开始的问题为什么有的 AI 能稳定挖漏洞有的却只会生成一堆看起来很像回事的幻觉报告答案不是因为前者用了更玄学的 Prompt也不是因为它背后的模型“突然更懂安全”。真正的原因是前者不是在让模型自由发挥而是在让模型执行一套审计系统。这套系统里有流程有层级有资源分配有状态持久化有广度扫描有深度推理有语义验证也有输出规范。它不是让 AI 更像一个聊天助手而是让 AI 更像一个能被组织、能被约束、能被验证的审计引擎。归根到底这套 AI Java 代码审计 Skill 体系做成的是一件非常朴素、却又非常关键的事情把资深审计员多年隐性的工作经验变成一套可执行、可复制、可落地的工程系统。这才是 AI 真正进入代码审计行业的开始。

更多文章