基于SAST+AI代码审计 架构与功能详解

张开发
2026/4/11 19:13:51 15 分钟阅读

分享文章

基于SAST+AI代码审计 架构与功能详解
Java-Audit 架构与功能详解之前的代码审计项目由同事接手了然后他改了很多东西。那理论上我这水逼项目和产品也不搭边了所以直接开了相对于之前优化的点joern扫描结果的过滤 joern扫描出来的结果大部分都是噪音如果我们AI去读取那些结果以做分析会很浪费上下文。所以写了个过滤器只保留AI用于审计的部分。路由分析结果外部存储 将路由分析的结果写入到向量数据库中其他Agent要分析的时候直接到向量库里边查找即可。我感觉这个还能再优化得空研究研究项目地址https://github.com/sss12365/SAST2AI项目细节下边就是AI生成的了项目概述01Java-Audit 是一个基于 Joern CPG 静态分析 Claude AI 语义分析 的 Java Web 应用代码审计工具。CLI 界面Python 实现通过 OpenAI 兼容 API 调用 Claude 模型。核心理念 Joern 负责精确的代码属性图分析数据流追踪、Sink 发现AI 负责 Joern 无法完成的语义理解鉴权逻辑、业务漏洞、可控性推理。两者结果通过 ChromaDB 向量数据库共享Agent 按需检索最大限度减少 token 消耗。项目结构java-audit/ # 3956 行代码 ├── main.py # CLI 入口 (click) ├── config.yaml # 配置文件 ├── requirements.txt # Python 依赖 │ ├── core/ # 核心引擎层 │ ├── config.py # YAML 配置加载 Pydantic 校验 │ ├── models.py # 数据模型定义 │ ├── orchestrator.py # 三阶段异步编排器 │ ├── joern_runner.py # Joern CLI 交互封装 │ ├── joern_parser.py # Joern 原始输出压缩器 (99.4% 压缩率) │ ├── java_compressor.py # Java 源码压缩器 (60-85% 压缩率) │ └── audit_store.py # ChromaDB 向量知识库 │ ├── agents/ # AI Agent 层 │ ├── base.py # BaseAgent (OpenAI SDK 封装) │ ├── route_analysis.py # 路由分析 Agent │ ├── route_param.py # 参数追踪 Agent │ ├── auth_analysis.py # 鉴权分析 Agent │ ├── hardcoded_audit.py # 硬编码审计 Agent │ └── vuln_verification.py # 漏洞验证 Agent │ ├── prompts/ # Agent System Prompt │ ├── route_analysis.md # 路由提取指令 │ ├── route_param.md # 参数追踪 可控性分析指令 │ ├── auth_analysis.md # 鉴权绕过检测指令 │ ├── hardcoded_audit.md # 硬编码过滤指令 │ └── vuln_verification.md # 漏洞验证 PoC 生成指令 │ ├── joern_scripts/ # Joern Scala 查询脚本 │ ├── find_routes.sc # 路由发现 (Spring/Servlet/JAX-RS/Struts2) │ ├── find_sinks.sc # Sink 发现 (SQL/CMD/File/HTTP/XML/...) │ ├── dataflow_analysis.sc # Source→Sink 污点追踪 │ ├── hardcoded_secrets.sc # 硬编码密钥检测 │ └── find_auth.sc # 鉴权代码定位 │ └── report/ # 报告生成层 ├── generator.py # Markdown 报告生成器 └── templates/ └── report_template.md # 报告模板执行流水线02┌─────────────────────────────────────────────────────────────────┐ │ Stage 0: 预处理与索引 │ │ ┌──────────────────────┐ ┌─────────────────────────────────┐ │ │ │ Java 源码压缩 │ │ Joern 原始输出压缩 │ │ │ │ 565 files → 426 docs │ │ 3.2MB → 18KB (99.4%) │ │ │ │ aggressive compress │ │ 去噪 去重 关键步骤提取 │ │ │ └──────────┬───────────┘ └──────────────┬──────────────────┘ │ │ └──────────┬──────────────────┘ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ ChromaDB 向量库 │ │ │ │ source_code 集合 │ │ │ │ joern 集合 │ │ │ └──────────────────┘ │ ├─────────────────────────────────────────────────────────────────┤ │ Stage 1: 信息收集 (并行) │ │ ┌──────────────────────┐ ┌─────────────────────────────────┐ │ │ │ Route Analysis Agent │ │ Joern Full Scan │ │ │ │ AI 提取路由参数 │ │ CPG 构建 → 路由/Sink/数据流 │ │ │ │ 压缩源码 60K chars │ │ 或加载已有 joern-raw-output │ │ │ └──────────┬───────────┘ └──────────────┬──────────────────┘ │ │ └──────────┬──────────────────┘ │ │ ▼ 写入 routes / joern 集合 │ ├─────────────────────────────────────────────────────────────────┤ │ Stage 2: 深度分析 (并行) │ │ ┌──────────────────────┐ ┌─────────────────────────────────┐ │ │ │ Route Param Agent │ │ Auth Analysis Agent │ │ │ │ 从 store 按批加载路由 │ │ 从 store 检索 Filter/Config 代码 │ │ │ │ 检索相关 ServiceImpl │ │ 语义匹配鉴权相关 Joern 发现 │ │ │ │ 追踪 Source→Sink │ │ URI 绕过 CVE 架构分析 │ │ │ └──────────┬───────────┘ └──────────────┬──────────────────┘ │ │ └──────────┬──────────────────┘ │ │ ▼ 写入 dataflows / auth 集合 │ ├─────────────────────────────────────────────────────────────────┤ │ Stage 3: 验证与报告 (并行) │ │ ┌──────────────────────┐ ┌─────────────────────────────────┐ │ │ │ Hardcoded Audit Agent│ │ Vuln Verification Agent │ │ │ │ Joern 结果语义过滤 │ │ 从 store 只加载 HIGH 发现 │ │ │ │ 排除误报 │ │ 检索可控 dataflow │ │ │ └──────────┬───────────┘ │ 代码证据验证 │ │ │ │ │ CVSS 三维评分 │ │ │ │ │ 生成 PoC 伪代码 │ │ │ │ └──────────────┬──────────────────┘ │ │ └──────────┬──────────────────┘ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ Report Generator │ │ │ │ Markdown 审计报告 │ │ │ └──────────────────┘ │ └─────────────────────────────────────────────────────────────────┘核心模块详解031. CLI 入口 ( main.py , 144 行)命令: scan project_path 完整审计 --config, -c 配置文件路径 (默认 config.yaml) --output, -o 输出目录 --joern-output, -j 已有 Joern 输出文件 (跳过 Joern 扫描) check 检查配置和依赖 parse-joern file 独立压缩 Joern 输出 -output, -o 输出文件伪代码:def scan(project_path, config, output, joern_output): cfg load_config(config) # 加载 YAML orchestrator AuditOrchestrator(cfg) # 初始化编排器 report asyncio.run( # 异步执行 orchestrator.run(project_path, output, joern_output) ) print(fReport: {report})2. 配置系统 ( core/config.py , 52 行)# config.yaml model: base_url: https://your-api.com # OpenAI 兼容 API 地址 api_key: sk-xxx # API 密钥 (或 ANTHROPIC_API_KEY 环境变量) model_id: claude-opus-4-6 # 模型 ID max_tokens: 16000 # 最大输出 token joern: home: /path/to/joern-cli # Joern 安装目录 output: dir: ./audit_output # 输出目录 (仅 --output 指定时使用默认输出到项目 report/)Pydantic 校验:api_key: 为空时自动读取ANTHROPIC_API_KEY环境变量joern.home: 校验目录存在3. 数据模型 ( core/models.py , 141 行)# 核心数据结构 RouteInfo # 路由: path, method, handler_class, handler_method, params, burp_template RouteParam # 参数: name, java_type, http_location, required CallChainNode # 调用链节点: level, class_name, method_name, code_snippet, param_mapping DataFlowChain # 数据流: source_param → sink_type chain[] controllable pseudocode Vulnerability # 漏洞: vuln_id, severity_score, poc_request, dataflow_chain, remediation AuthInfo # 鉴权: framework, version, route_auth_mapping, bypass_findings HardcodedSecret # 硬编码: secret_type, value_preview(脱敏), file_path JoernResult # Joern 结果: routes, sinks, dataflows, hardcoded_secrets AuditReport # 最终报告: 所有结果汇总 # CVSS 三维评分 SeverityScore: score R × 0.40 I × 0.35 C × 0.25 # R可达性, I影响, C复杂度 (0-3) cvss score / 3.0 × 10.0 severity: C (Critical): score 2.70, CVSS 9.0-10.0 H (High): score 2.10, CVSS 7.0-8.9 M (Medium): score 1.20, CVSS 4.0-6.9 L (Low): score 0.10, CVSS 0.1-3.9 # Sink 类型枚举 SinkType: SQL | COMMAND | HTTP | FILE | XML | LDAP | EXPRESSION | DESERIALIZE | RESPONSE | PATH4. 编排器 ( core/orchestrator.py , 220 行)async def run(project_path, output_dir, joern_output_file): # 默认输出到 project_path/report/每次清空重建 output output_dir or Path(project_path) / report if output.exists(): shutil.rmtree(output) output.mkdir(parentsTrue) store AuditStore(output / .audit_store) store.reset() # Stage 0: 索引源码到向量库 index_source_code(project_path) # → 读取所有 .java → aggressive 压缩 → 存入 source_code 集合 # Stage 1: 并行 if joern_output_file: # 加载已有 Joern 输出 → 压缩 → 存入 joern 集合 parsed parse_joern_output(raw_text) compact to_compact_text(parsed) store.store_joern_findings(compact, parsed.findings) route_result await route_agent.analyze(project_path) else: route_result, joern_result await gather( route_agent.analyze(project_path), joern.full_scan(project_path), # CPG 构建 5 个查询脚本 ) store.store_routes(route_result[routes]) # Stage 2: 并行, Agent 从 store 按需检索 param_result, auth_result await gather( param_agent.analyze_with_store(store, joern_result), auth_agent.analyze_with_store(store, joern_result), ) store.store_dataflows(param_result) store.store_auth(auth_result) # Stage 3: 并行, VulnVerify 只加载 HIGH 发现 hardcoded_result, vuln_result await gather( hardcoded_agent.audit(joern_result), vuln_agent.verify_with_store(store, joern_result), ) # 生成报告 report_gen.generate(all_results, output_path)5. Joern 集成5.1 Joern Runner ( core/joern_runner.py , 121 行)class JoernRunner: async def build_cpg(project_path): # javasrc2cpg project -o workspace/cpg.bin # 超时 900 秒 async def full_scan(project_path): cpg await build_cpg(project_path) # 并行执行 5 个查询脚本: routes, sinks, dataflows, hardcoded, auth await gather( run_script(find_routes.sc, cpg), run_script(find_sinks.sc, cpg), run_script(dataflow_analysis.sc, cpg), run_script(hardcoded_secrets.sc, cpg), run_script(find_auth.sc, cpg), )5.2 Joern 查询脚本 ( joern_scripts/ , 550 行 Scala)**find_routes.sc** (174 行) — 路由发现: scala // Spring MVC: RequestMapping/GetMapping/PostMapping/... cpg.annotation.name(RequestMapping|GetMapping|PostMapping|...).method → 提取 path, httpMethod, params // Servlet: HttpServlet.doGet/doPost cpg.typeDecl.filter(_.inheritsFromTypeFullName(.*HttpServlet.*)).method.name(doGet|doPost) // JAX-RS: Path GET/POST cpg.annotation.name(GET|POST|PUT|DELETE).method → 合并 class Path method Path // Struts2: ActionSupport.execute() cpg.typeDecl.filter(_.inheritsFromTypeFullName(.*ActionSupport.*)).method.name(execute) // 输出 JSON: RouteEntry(path, httpMethod, handlerClass, handlerMethod, filePath, lineNumber, framework, params[]) **find_sinks.sc** (80 行) — 危险 Sink 发现: scala // SQL: executeQuery, executeUpdate, prepareStatement, createQuery // Command: Runtime.exec(), ProcessBuilder.start() // File: FileInputStream, FileOutputStream, Files.read/write/copy // HTTP: HttpClient.execute(), URL.openConnection() // XML: DocumentBuilder.parse(), SAXParser // Deserialize: ObjectInputStream.readObject(), JSON.parseObject() // LDAP: DirContext.search() // Expression: SpelExpression.getValue(), Ognl // XSS: PrintWriter.write(), response.getWriter() // 输出 JSON: SinkEntry(sinkType, callName, className, filePath, lineNumber, code) **dataflow_analysis.sc** (87 行) — 污点追踪: scala // Sources: getParameter(), RequestParam, PathVariable, RequestBody 等 // Sinks: 按类别定义 (SQL/COMMAND/FILE/HTTP/XML/DESERIALIZE/EXPRESSION) // 使用 Joern reachableByFlows 进行 Source→Sink 可达性分析 sinks.reachableByFlows(sources) → 输出每条流的完整步骤 // 输出 JSON: DataFlowEntry(sourceParam, sinkType, steps[FlowStep(class, method, code, file, line)]) **hardcoded_secrets.sc** (106 行) — 硬编码检测: scala // 模式 1: 敏感变量名 字符串字面量赋值 // password, secret, apiKey, token, privateKey, encryptKey, jdbc 等 cpg.assignment.where(_.target.name((?i).*password.*)).where(_.source.isLiteral) // 模式 2: 敏感方法调用 字符串参数 // setPassword(), setSecret(), setApiKey() 等 cpg.call.name(setPassword|setSecret|...).where(_.argument(1).isLiteral) // 模式 3: JDBC URL 含内嵌凭据 cpg.literal.code(\jdbc:.*\).filter(_.contains(password)) // 值预览: 前4后2位 **** // 输出 JSON: HardcodedEntry(secretType, variableName, valuePreview, className, filePath, lineNumber) **find_auth.sc** (103 行) — 鉴权代码定位: scala // Shiro: 继承 org.apache.shiro.*, RequiresAuthentication/Permissions/Roles // Spring Security: EnableWebSecurity, PreAuthorize, SecurityFilterChain // JWT: jwt 相关的 parse/verify/decode/sign 调用 // Filter: implements javax.servlet.Filter → doFilter() // Interceptor: implements HandlerInterceptor → preHandle() // URI 解析: getRequestURI/getServletPath/getPathInfo 调用位置 (潜在绕过) // 输出 JSON: AuthEntry(authType, className, methodName, filePath, code, details) 5.3 Joern 输出压缩器 ( core/joern_parser.py , 415 行)问题 : Joern 原始输出 3.2MB (20772 行), 其中 92% 是构建日志噪音。三层压缩 :Layer 1: 噪音过滤 (去除 92% 构建日志) - [INFO] Pass io.joern.x2cpg... completed (25 行 pass 日志) - [INFO] Calculating reaching definitions (8852 行) - [INFO] Number of definitions (8852 行) - [INFO] Could not create edge (1405 行) Layer 2: Taint Flow 关键步骤提取 (每条 flow 30→5 步) - 去除: $obj3, empty, RET, StringUtils.xxx(), StringBuilder - 保留: Source 入口, 文件边界跳转, 危险操作 (executeQuery/readObject/transferTo), Sink 终点 示例: 原始 (30 步): FileController:82 → FileServiceImpl:43 → L47 → L90 → L99 → getOriginalFilename() → StringUtils.isBlank → concatPath → FileUtils:57 → L59 → L62 → operator.arrayInitializer → L31 → L34 → L35 → L38 → StringUtils.appendIfMissing → L40 → StringUtils.removeStart → ... → transferTo 压缩 (5 步): FileController:82:RequestParam MultipartFile → FileServiceImpl:43:MultipartFile → FileUtils:57:String path → FileServiceImpl:100:withBasePath → L102:transferTo(new File(fullPath)) Layer 3: 相同 Sink 去重合并 - FILE_UPLOAD: 31 findings → 19 unique 12 duplicates merged - 合并后只保留一条代表性 flow, 列出所有入口点: entries(7): FileController.java:47, :55, :69, :82, FileServiceImpl:43, :90, :99压缩效果: 3,212,959 bytes → 18,308 chars (99.4% reduction)独立使用:python3 main.py parse-joern joern-raw-output.txt -o compressed.txt6. Java 源码压缩器 ( core/java_compressor.py , 342 行)两种模式 :Normal 模式 (~25% 压缩):去除: import, 单行注释, javadoc, 空行, 日志语句, Lombok 注解 保留: 大部分代码逻辑Aggressive 模式 (~60-85% 压缩):只保留:✅ 路由注解 (RequestMapping, GetMapping, PostMapping, Path, WebServlet...)✅ 鉴权注解 (PreAuthorize, RequiresAuthentication, Secured...)✅ 方法签名 (public/protected/private 方法声明)✅ 危险 Sink 调用 (executeQuery, readObject, getConnection, transferTo, Runtime.exec...)✅ 输入获取 (getParameter, RequestParam, RequestBody, getInputStream...)✅ SQL 字符串拼接 (SELECT variable)✅ 安全相关字段 (password, secret, token, filter, datasource...)✅ 类/接口声明去除:❌ import 语句❌ 注释 (单行/多行/javadoc)❌ 空行❌ 日志 (logger.debug/info/trace/warn)❌ getter/setter 方法体❌ Lombok 注解 (Data, Getter, Setter...)❌ 纯业务逻辑 (与安全无关的计算/转换)实测压缩率 :VizServiceImpl.java: 24,944 → 3,668 chars (85%) DataProviderServiceImpl.java: 19,830 → 2,588 chars (87%) ShiroSecurityManager.java: 13,238 → 2,026 chars (85%) DataProviderController.java: 4,981 → 2,636 chars (47%) # Controller 本身就紧凑7. 向量知识库 ( core/audit_store.py , 399 行)ChromaDB 持久化存储 , 6 个集合:class AuditStore: # 6 个集合 collections { source_code: # 每个 Java 文件一条文档 (aggressive 压缩后) metadata: {path, filename, file_type, size, full_content} # file_type: controller/service/filter/interceptor/config/dao/entity/security routes: # 每个 HTTP 路由一条文档 metadata: {path, method, handler_class, handler_method, framework, param_count, param_names, has_body, full_json} joern: # 每个 Joern finding 一条文档 metadata: {severity, category, location, full_json} dataflows: # 每条 Source→Sink 链一条文档 metadata: {route, source_param, sink_type, controllable, severity, full_json} auth: # 鉴权分析结果 metadata: {type: auth_analysis} vulns: # 验证后漏洞 } # Agent 专用查询方法 get_routes_for_param_analysis(batch_idx, batch_size) # 按批加载路由 get_auth_related_code() # 语义检索鉴权代码 → query(source_code, authentication authorization filter..., where{file_type: {$in: [filter,interceptor,config,security]}}) get_findings_by_severity(HIGH) # 只加载 HIGH → query(joern, vulnerability injection..., where{severity: {$in: [CRITICAL,HIGH]}}) get_controllable_dataflows() # 只加载可控数据流 → query(dataflows, controllable SQL..., where{controllable: True}) get_dangerous_routes(n20) # 高危路由 get_controller_code() # Controller 源码渐进式加载示意 :Route Param Agent batch 3: 1. store.get_routes_for_param_analysis(2, 10) → 10 条路由 (~3K chars) 2. 提取 handler_class 名 → UserController 3. store.query(source_code, UserController) → 相关 ServiceImpl (~5K chars) 4. store.get_findings_by_severity(HIGH) → Joern 高危发现 (~10K chars) 5. 组装 user_message: ~18K chars (vs 之前每 batch 80K)8. AI Agent 层8.1 BaseAgent ( agents/base.py , 102 行)class BaseAgent: def __init__(config, agent_name): self.client OpenAI(api_key, base_url /v1, timeout300s) self._system_prompt load_prompt(fprompts/{agent_name}.md) def _call_model(user_message, system_promptNone): messages [ {role: system, content: system_prompt}, {role: user, content: user_message}, ] response client.chat.completions.create(model, max_tokens, messages) return response.choices[0].message.content async def _call_model_async(user_message): return await asyncio.to_thread(_call_model, user_message) def _read_source_files(project_path, extensions[.java,.xml,.properties,...]) def _read_specific_files(project_path, patterns[*Controller.java,...])8.2 Route Analysis Agent ( agents/route_analysis.py, 95 行)输入: 项目源码路径 处理: 1. compress_java_project(project_path, max_total_chars60000) # 压缩源码 2. 调用 AI 分析所有路由 输出: {routes: [{path, method, handler_class, handler_method, params[], burp_template}], framework_info} 支持框架: Spring MVC, Servlet, JAX-RS, Struts 2, CXF Web Services 参数解析: RequestParam(Query), PathVariable(Path), RequestBody(Body), RequestHeader(Header), CookieValue(Cookie)8.3 Route Param Agent (agents/route_param.py, 209 行)两种模式: analyze_with_store(store, joern_result) # 向量库模式 (推荐) analyze(route_result, joern_result) # 直接传参模式 (fallback) 向量库模式: 1. joern_context store.get_findings_by_severity(HIGH) joern dataflows # 一次性加载 2. for batch in batches(10): routes store.get_routes_for_param_analysis(batch_idx) code store.query(source_code, handler_classes) result AI(routes code joern_context) # 每 batch 只加载相关代码 输出 (每个有危险 Sink 的路由): {route_path, dataflow_chains: [{ source_param, sink_type, sink_location, chain: [{level, class_name, method_name, code_snippet, param_mapping}], controllable, controllability_note, pseudocode, poc_request }]} 可控性判定: 参数传到 Sink? → 硬编码覆盖? → 安全检查? → 可绕过? 结论: ✅ 完全可控 / ⚠️ 条件可控 / ❌ 不可控8.4 Auth Analysis Agent ( agents/auth_analysis.py , 167 行)两种模式: analyze_with_store(store, joern_result) # 向量库模式 analyze(route_result, joern_result) # 直接传参模式 向量库模式: 1. auth_code store.get_auth_related_code() # 语义检索 Filter/Interceptor/Config 2. routes store.query(routes, all, n100) 3. joern_auth store.query(joern, authentication filter interceptor...) 4. AI(auth_code routes joern_auth) 检测范围: - 鉴权框架识别: Shiro, Spring Security, JWT, Filter, Interceptor - 组件版本 CVE: Shiro 1.11.0, Spring Security 5.7.5 等 - URI 解析绕过: getRequestURI() vs getServletPath(), 分号注入, 双斜杠, URL编码 - 鉴权架构分析: Filter → Interceptor → Action 各层 - 路由鉴权映射: 每个路由的鉴权状态 输出: {auth_framework: {name, version, config_files, known_cves}, auth_architecture: {layers[]}, route_auth_mapping: {/path: 状态}, bypass_findings: [{vuln_id, title, severity, poc_request, remediation}]}8.5 Hardcoded Audit Agent ( agents/hardcoded_audit.py , 69 行)输入: Joern 硬编码扫描结果 处理: AI 语义过滤, 区分真实密钥 vs 误报 误报排除: - 占位符: ${password}, %s, {0} - 空值/null - 测试代码 (test/ 目录) - 示例值 (your-api-key-here) - 已哈希密码 ($2a$10$...) - 配置引用 输出: {hardcoded_secrets: [{secret_type, risk_level, variable_name, value_preview(脱敏), file_path, line_number, remediation}], filtered_count: 12, filter_reasons: {placeholder: 5, test_code: 3, ...}}8.6 Vuln Verification Agent ( agents/vuln_verification.py , 174 行)两种模式: verify_with_store(store, joern_result) # 向量库模式 verify(param_result, auth_result, ...) # 直接传参模式 向量库模式 — 只加载真正需要验证的内容: 1. controllable_flows store.get_controllable_dataflows() # 可控数据流 2. high_findings store.get_findings_by_severity(HIGH) # 高危 Joern 发现 3. auth store.query(auth, bypass vulnerability) # 鉴权绕过 4. code store.query(source_code, 危险 Sink 关键词) # 相关源码 5. AI(controllable_flows high_findings auth code) 核心原则: 只报告有代码证据的真实漏洞 ✅ 代码中确实存在 SQL 拼接 / readObject() / 未过滤输入到 Sink ❌ 推测性 (如果服务端没有校验...) ❌ 框架已自动防护 (MyBatis #{}, PreparedStatement) ❌ 证据不足的 IDOR 验证流程: 1. 可达性验证 (外部可访问? 需要什么权限?) 2. 数据流验证 (Source→Sink 真实存在? 中间有过滤?) 3. 可控性验证 (用户输入能控制到 Sink? 硬编码覆盖?) 4. 利用可行性 (需要特殊条件? WAF 拦截?) 5. 影响评估 (实际影响?) 6. 代码证据 (具体文件名、行号、代码片段) 输出: {verified_vulnerabilities: [{ vuln_id, title, severity_score: {R, I, C}, cvss, severity, exploitability: confirmed/pending/not_exploitable, location, description, dataflow_chain: {source, sink, chain_summary, pseudocode}, poc_request, remediation }], dismissed_findings: [{original_finding, dismiss_reason, location}]}9. Prompt 设计 ( prompts/ , 470 行)每个 Agent 的 System Prompt 包含:角色定义 (专业 Java Web 安全审计专家)检测范围和边界输出格式 (严格 JSON schema)关键规则 (零遗漏 / 只报真实漏洞 / 代码证据)特色设计:vuln_verification.md : 6 条不报告规则, 避免推测性漏洞auth_analysis.md : 完整的 URI 绕过模式表 CVE 版本对照表route_param.md : 可控性判定决策树 MyBatis 安全/危险模式区分10. 报告生成器 ( report/generator.py , 286 行)Markdown 报告结构 :# {project} - Java 代码审计报告 ## 1. 审计概述 (框架识别、路由总数、分析方法) ## 2. 风险统计 (C/H/M/L 四级表) ## 3. 漏洞详情 ### [{vuln_id}] {title} | 严重等级 | CVSS | 可达性 | 影响 | 复杂度 | 可利用性 | 位置 | **描述** **执行链 (Source → Sink)** — 伪代码 **利用数据包 (PoC)** — Burp Suite HTTP 请求 **修复建议** ## 4. 数据流追踪 (每个参数的 Source→Sink 链) ## 5. 鉴权分析 (框架 CVE 路由鉴权映射 绕过) ## 6. 硬编码审计 (类型/变量/值预览/文件/风险) ## 7. 审计结论 (统计汇总)Token 优化效果总结04优化层技术压缩率Joern 输出噪音过滤 Taint Flow 关键步骤 Sink 去重99.4% (3.2MB → 18KB)Java 源码Aggressive 模式: 只保留安全骨架60-85%上下文传递ChromaDB 向量库按需检索替代全量传输~70%Batch 优化Joern context 一次加载 batch_size 5→10~50% API 调用总计 : 单次审计 token 消耗从 ~340K 降至 ~95K ( ~72% reduction )支持的漏洞类型05类型Joern 检测AI 检测示例SQL 注入✅ Source→Sink 数据流✅ 可控性/绕过分析String 拼接 SQL, MyBatis ${}命令注入✅ Runtime.exec() 追踪✅ 参数过滤分析ProcessBuilder, Runtime.exec反序列化✅ readObject() 定位✅ Gadget Chain 可用性ObjectInputStream, JSON.parseObject文件上传✅ transferTo() 追踪✅ 路径穿越/类型校验MultipartFile, 无路径保护文件读取✅ FileInputStream 追踪✅ 路径遍历分析path traversal (../)SSRF✅ HttpClient/URL 追踪✅ 内网探测分析HttpClient.execute, URL.openConnectionXXE✅ XML 解析器定位✅ 外部实体配置DocumentBuilder, SAXParserJDBC 注入✅ getConnection() 追踪✅ H2/MySQL 反序列化JDBC URL INITRUNSCRIPT鉴权绕过✅ URI 方法定位✅ 路径匹配差异分析getRequestURI vs getServletPath越权访问❌✅ 权限校验缺失IDOR, 参数可控资源 ID硬编码密钥✅ 模式匹配✅ 语义过滤误报数据库密码, API Key, JWT Secret表达式注入✅ SpEL/OGNL 追踪✅ 输入可控性SpelExpression.getValue()LDAP 注入✅ DirContext.search() 追踪✅ 过滤器拼接分析LDAP filter injectionXSS✅ response.write() 追踪✅ 输出编码分析反射型/存储型支持的 Java 框架06框架路由发现参数解析鉴权分析Spring MVCRequestMapping, GetMapping, PostMapping...RequestParam, PathVariable, RequestBodySpring SecurityServletHttpServlet, WebServlet, web.xmlHttpServletRequestFilter ChainJAX-RSPath, GET, POSTQueryParam, PathParam, FormParam-Struts 2struts.xml, ActionSupportAction 属性InterceptorApache Shiro--shiro.ini, RequiresAuthenticationJWT-Bearer TokenJWT 签名验证MyBatis-#{} (安全) / ${} (危险)-最后想说的07这一段话改了好多好多次改了又删删了又改。简单点说就是过我手的东西我会尽责任去做好去完善。但是每当我对公司产品提出问题的时候现在身边的同事都在跟我说客户不关心这个只关心结果。就算以结果导向也没看见很好的结果。只有光鲜亮丽的前端格式规整封面华丽的报告。说实话不知道我对技术、产品的精益求精理念是对还是错。就这样吧祝师傅们清明安康。结语一寸灰兄弟的钻研与创新精神值得我们持续学习这个世界有它的问题我们一定不要怀疑自己的赤子之心。如果十年后我们还能保持今日的热血我想那是最值得感恩的事情。——千里

更多文章