Java 应用安全防守漏洞的识别与定位
在 Java 应用安全中,防守漏洞(Defensive Vulnerability)指应用在防护机制上存在的缺失或缺陷,导致攻击者可以绕过防线,下面从识别方法论、常见漏洞类型、定位技术三个维度系统讲解。

识别方法论
威胁建模(Threat Modeling)
- STRIDE 模型:Spoofing、Tampering、Repudiation、Information Disclosure、DoS、Elevation of Privilege
- 数据流图(DFD):标出信任边界(Trust Boundary),边界处即是防守重点
- 攻击树分析:从攻击者视角逆向推导防护缺口
代码审计三视角
| 视角 | 关注点 |
|---|---|
| 输入侧 | 参数校验、反序列化、文件上传 |
| 处理侧 | 权限检查、业务逻辑、并发控制 |
| 输出侧 | 编码转义、日志脱敏、错误信息 |
动态验证
- 黑盒扫描(Burp、AWVS)+ 白盒审计(Fortify、CodeQL)交叉验证
- 灰盒测试:配合 SkyWalking/Arthas 观察运行时行为
Java 常见防守漏洞类型与定位
认证与授权缺陷
典型问题:
- 越权访问(水平/垂直)
- Session 固定、JWT 伪造
- 权限校验遗漏
定位方法:
// 反模式:只在 Controller 层校验,Service 层裸奔
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
// 缺少 @PreAuthorize 或用户归属校验
return userService.findById(id);
}
识别技巧:
- 搜索
@PreAuthorize、@Secured、Shiro注解覆盖率 - CodeQL 查询:
Semmle/java的MissingAuthorization - 检查
@RequestMapping方法是否有对应的权限注解
注入类漏洞
SQL 注入定位:
// 危险 1:字符串拼接
String sql = "SELECT * FROM user WHERE name='" + name + "'";
// 危险 2:MyBatis ${} 拼接
<select id="query">SELECT * FROM user WHERE name='${name}'</select>
// 安全:PreparedStatement / #{}
检测手段:
- 正则扫描:
Statement.execute.*\+、(MyBatis XML) - 使用 CodeQL
java/sql-injection查询 - 使用 SpotBugs + Find Security Bugs 插件
命令注入:
Runtime.getRuntime().exec("ping " + ip); // 危险
ProcessBuilder pb = new ProcessBuilder("ping", ip); // 相对安全
反序列化漏洞
高危点:
ObjectInputStream.readObject()- Fastjson
JSON.parseObject()(autoType) - Jackson
enableDefaultTyping() - XStream、Hessian、Shiro rememberMe
定位命令:
# 全局搜索危险反序列化入口 grep -rn "readObject\|parseObject\|fromXML\|enableDefaultTyping" src/
运行时定位:
# 使用 RASP 或 Java Agent hook ObjectInputStream java -javaagent:rasp-agent.jar -jar app.jar
敏感信息泄露
识别点:
- 异常堆栈直接返回前端
- 日志打印密码/token
- Actuator 端点未鉴权(
/actuator/env、/actuator/heapdump) - 配置文件硬编码密钥
定位:
# 检查 Actuator 暴露 curl http://target/actuator # 检查堆转储泄露 curl http://target/actuator/heapdump -o heap.hprof
SSRF / XXE / 文件上传
SSRF 定位:
// 危险:URL 参数直接发起请求 new URL(userInput).openConnection(); HttpClient.create().get(userInput);
- 检查是否使用
URL白名单、是否禁用内网 IP
XXE 定位:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 缺少 dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
文件上传:
- 检查是否校验后缀、Content-Type、Magic Number
- 检查上传目录是否可被 Web 访问
依赖漏洞(SCA)
# Maven mvn org.owasp:dependency-check-maven:check # Gradle ./gradlew dependencyCheckAnalyze # 在线 # 查看 pom.xml → 匹配 CVE → log4j2 <= 2.14.1 = CVE-2021-44228
业务逻辑漏洞
- 并发下单/超卖
- 支付金额篡改(前端校验但后端未校验)
- 短信轰炸、验证码复用
- 优惠券重复使用
定位:需结合需求文档 + 数据库 + 抓包分析,工具难覆盖。
定位技术实战
静态分析(SAST)
工具链:
CodeQL → 深度数据流分析(推荐)
Fortify → 商业级,规则全
SonarQube + FindSecBugs → 轻量级
CodeQL 示例(找 SQL 注入)**:
import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.SqlInjection from SqlInjectionQuery q, DataFlow::PathNode source, DataFlow::PathNode sink where q.hasFlowPath(source, sink) select sink, source, sink, "SQL injection from $@.", source, "user input"
动态分析(DAST + IAST)
- 黑盒:Burp Suite + 扫描插件(活跃扫描)
- IAST:
DongTai、JVM-Sandbox植入 Agent,运行时追踪污点传播 - RASP:
openrasp实时拦截并可告警
Arthas 定位可疑调用:
watch com.xxx.Controller getUser '{params, returnObj}' -x 3
trace com.xxx.Service process
日志与监控
- ELK 收集审计日志,识别异常访问模式
- SkyWalking 追踪链路,发现未鉴权调用
- MDC 打标关键操作,
MDC.put("uid", userId)
JVM 层面定位
# 查看加载的类,找到可疑反序列化链 jcmd <pid> GC.class_histogram | grep -i "gadget\|Invoker" # Heap dump 分析内存中的敏感数据 jmap -dump:live,format=b,file=heap.hprof <pid> # 使用 MAT / JProfiler 分析
识别流程总结
资产梳理 → 确定攻击面(API、页面、MQ、定时任务)
2. 威胁建模 → 标出信任边界
3. SAST 扫描 → CodeQL/Fortify 初筛
4. 人工审计 → 关注框架特性(Spring/Shiro/MyBatis)
5. IAST/DAST → 运行时验证
6. SCA → 依赖漏洞排查
7. 业务逻辑 → 人工渗透
8. 修复 → 回归 → 加入 CI 门禁
防御加固建议
| 层面 | 措施 |
|---|---|
| 编码 | 参数化查询、白名单校验、最小权限 |
| 框架 | 升级 Spring Security、关闭 Actuator 敏感端点 |
| 依赖 | 定期 SCA 扫描、Dependabot 自动升级 |
| 运行时 | 部署 RASP,JVM Sandbox 隔离 |
| 监控 | 审计日志、异常告警、WAF |
| 流程 | SDL 左移,安全测试进 CI/CD |
核心思路:输入不可信 → 边界必校验 → 权限必后端 → 输出必编码 → 依赖必扫描 → 运行时必监控,识别靠工具+人工双轮驱动,定位靠数据流追踪+运行时观测锁定根因。