Java 安全防守漏洞的识别与定位方法论
从"发现—定位—验证—修复"闭环角度,结合典型案例说明 Java 应用中防守漏洞如何识别与定位。

总体思路:分层识别
| 层次 | 识别手段 | 典型漏洞 |
|---|---|---|
| 代码层 | SAST 静态扫描、人工审计 | 注入、反序列化、硬编码密钥 |
| 依赖层 | SCA 软件成分分析 | Log4Shell、Shiro、Fastjson |
| 运行时层 | IAST/RASP、动态代理、日志 | 越权、SSRF、竞态 |
| 配置/运维层 | 基线核查、配置比对 | actuator 暴露、默认口令 |
常见漏洞类型的识别定位方法
注入类(SQL/命令/表达式)
识别:
- SAST 规则:
Statement.execute+ 字符串拼接、ProcessBuilder、Runtime.exec、SpelExpressionParser - 关键词: 、
String.format(、 拼接 SQL
定位案例:
// 危险点
String sql = "select * from user where name='" + name + "'";
stmt.execute(sql);
// 修复范式
PreparedStatement ps = conn.prepareStatement("select * from user where name=?");
ps.setString(1, name);
定位方法: 用 IDEA 的 Structural Search 或 SpotBugs 规则定位到具体行;通过 MyBatis XML 中 而非 定位。
反序列化漏洞
识别线索:
- 反序列化入口:
ObjectInputStream.readObject、JSON.parseObject(..., Feature.SupportAutoType)、XStream.fromXML、readObject重写 - 依赖:fastjson < 1.2.83、shiro < 1.8、commons-collections 3.2.1
定位方法:
- SCA 扫描定位脆弱依赖版本(
mvn dependency:tree) - 追踪反序列化入口 → 是否有外部可控输入
- 使用
ysoserial复现辅助定位利用链
越权/认证绕过
识别:
- 检查所有
@RequestMapping接口是否缺少权限注解 - 横切:
@PreAuthorize/@RequiresPermissions缺失 - 逻辑:是否仅靠前端隐藏按钮,后端未校验
定位案例:
@GetMapping("/order/{id}")
public Order get(@PathVariable Long id){ // 缺少当前用户归属校验
return orderService.getById(id); // 水平越权
}
定位方法: 用 Burp 遍历 ID 观察响应;代码层用 ArchUnit 或自定义规则扫描 Controller 无权限注解方法。
SSRF / 路径穿越
识别:
new URL(url).openConnection()、HttpClient.execute、RestTemplate、File(url)- 输入未做协议/主机白名单校验
定位:
// 危险 URL u = new URL(userInput); // 可 file:// 或内网 IP // 修复:白名单 + 协议限制 + 重定向禁用
敏感信息泄露
识别:
- 硬编码密钥:正则
(?i)(password|secret|apikey)\s*=\s*"..."、AES常量密钥 - 日志打印敏感字段:
log.info(..., password/token/idCard) - 响应返回全量实体:
return userEntity(含密码字段)
定位: 用 gitleaks、detect-secrets 扫描代码库;用 grep 追踪 toString() 打印实体。
依赖组件漏洞(案例)
Log4Shell 定位:
mvn dependency:tree | grep log4j-core # 定位版本 < 2.15.0 # 或 SCA 工具:Dependency-Check / Snyk / OWASP DC
定位链路: pom 依赖 → 实际 classpath 版本(注意传递依赖冲突)→ 是否被 JndiLookup 触及 → 验证触发点(用户输入进 logger.info)
工具链组合(实战推荐)
- SAST:SpotBugs+FindSecBugs、Semgrep、CodeQL(自定义规则)
- SCA:
mvn dependency-check:check、Snyk、Trivy - IAST/RASP:动态插桩,边跑测试边标红危险调用链
- 运行时可观测:反序列化类白名单日志、SQL 慢日志与异常堆栈关联
CodeQL 定位示例:
import java
from MethodAccess ma, Method m
where ma.getMethod() = m and m.hasName("exec") and m.getDeclaringType().hasQualifiedName("java.lang.Runtime")
select ma, "命令执行风险点"
定位闭环:从告警到根因
- 告警收敛:SAST/SCA 报告按"污点是否可达外部输入"降噪
- 调用链回溯:从 sink(危险 API)反向追踪 source(HTTP 参数、消息队列、文件)
- 可控性判定:确认输入是否经过过滤/白名单,是则降级
- 最小复现:单元测试 + payload 验证,如 SQL 注入用
' or '1'='1 - 定位产物:代码行号 + 请求路径 + 数据流链路 + 修复建议 + 回归用例
一页速查表
| 漏洞 | 快速识别关键词 | 定位工具 |
|---|---|---|
| SQL 注入 | 、、execute |
Semgrep/人工审计 |
| 反序列化 | readObject、parseObject |
SCA + ysoserial |
| 越权 | 缺权限注解 | Burp + ArchUnit |
| SSRF | new URL、openConnection |
污点分析 |
| 硬编码 | password= |
gitleaks |
| 组件漏洞 | 版本 < 修复版 | dependency-check |
| Actuator 暴露 | management.endpoints.web.exposure |
配置基线核查 |
核心结论: 识别靠"规则+依赖+运行时"三线并行,定位靠"source→sink 数据流回溯"+"可控性验证",最终以最小复现用例闭环,单纯依赖工具会大量误报,必须结合人工可达性分析。