本文目录导读:

我来列举一些常见的Java敏感信息泄露案例,这些在实际开发和安全审计中经常遇到:
配置文件泄露
案例:硬编码数据库密码
// 错误示例
public class DatabaseConfig {
private static final String DB_URL = "jdbc:mysql://localhost:3306/mydb";
private static final String USERNAME = "admin";
private static final String PASSWORD = "password123"; // 敏感信息硬编码
}
案例:配置文件被提交到Git
# application.properties spring.datasource.password=root123 spring.redis.password=redis@2024 aws.accessKeyId=AKIAIOSFODNN7EXAMPLE aws.secretKey=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
日志泄露敏感信息
案例:打印用户敏感数据
// 错误示例
logger.info("用户登录成功: {}", user.toString());
// 如果User类toString包含密码等敏感字段
// 或
logger.error("数据库操作失败: " + sqlQuery); // 暴露SQL语句和参数
案例:打印错误堆栈泄露路径
try {
// 业务逻辑
} catch (Exception e) {
e.printStackTrace(); // 泄露文件路径、类结构
logger.error("错误信息: " + e.getMessage()); // 可能包含敏感路径
}
API接口泄露敏感信息
案例:返回完整用户信息
@GetMapping("/api/user/{id}")
public User getUser(@PathVariable Long id) {
// 错误:返回了包含password_hash, id_card等敏感字段的完整User对象
return userService.findById(id);
}
案例:未过滤的错误信息
// 错误示例
@ExceptionHandler(Exception.class)
public ResponseEntity handleError(Exception e) {
// 返回完整错误堆栈
return ResponseEntity.status(500).body(e.getMessage());
// 可能泄露:SQL语句、文件路径、内部IP等
}
内存泄露敏感信息
案例:密码在内存中持续存在
// 错误示例
String password = "userInputPassword";
// 使用密码进行操作
authenticateUser(password);
// 密码字符串继续存在于内存中,直到GC回收
// 正确做法
char[] passwordChars = readPassword();
try {
authenticateUser(passwordChars);
} finally {
Arrays.fill(passwordChars, '0'); // 立即清除
}
URL参数泄露
案例:GET请求包含敏感参数
// 错误示例
@GetMapping("/api/reset-password")
public String resetPassword(
@RequestParam String email,
@RequestParam String token, // token会在URL中暴露
@RequestParam String newPassword // 密码在URL中暴露
) {
// URL可能被记录在:浏览器历史、服务器日志、referer头
}
缓存泄露
案例:敏感数据被缓存
// 错误示例
@Cacheable(value = "users", key = "#userId")
public User getUserFullInfo(Long userId) {
// 缓存了包含密码、身份证等敏感信息的完整User对象
return userRepository.findById(userId);
}
Java反序列化漏洞
案例:未验证的反序列化
// 错误示例
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
ObjectInputStream ois = new ObjectInputStream(req.getInputStream());
Object obj = ois.readObject(); // 危险:直接反序列化未验证的输入
}
前端JavaScript代码泄露
案例:API密钥在前端暴露
// 在JavaScript中硬编码
const API_KEY = "sk-xxxxxxxxxxxxxxxx";
const SECRET = "ss-xxxxxxxxxxxxxxxx";
fetch('/api/process', {
headers: {
'X-API-Key': API_KEY,
'Authorization': 'Bearer ' + SECRET
}
});
响应头泄露
案例:服务器信息暴露
// 错误示例
response.setHeader("Server", "Tomcat/9.0.0");
response.setHeader("X-Powered-By", "Spring Boot 2.7.0");
response.setHeader("X-Application-Version", "v1.0.0-rc2");
临时文件泄露
案例:临时文件未清理
// 错误示例
File tempFile = File.createTempFile("report", ".csv");
FileWriter writer = new FileWriter(tempFile);
writer.write(sensitiveData); // 包含客户信息的临时文件
writer.close();
// 没有及时删除临时文件
防护建议
- 配置管理:使用环境变量、密钥管理服务(Vault/Secrets Manager)
- 日志脱敏:使用logback/Log4j2的过滤器或自定义脱敏实现
- DTO设计:创建专门的VO/DTO对象,避免直接返回实体类
- 参数处理:使用POST请求传递敏感信息,避免URL参数
- 内存管理:使用char[]代替String存储密码,使用后立即清除
- 缓存策略:缓存前脱敏,或使用短暂TTL
- 安全配置:关闭详细的错误信息展示,使用统一错误格式
这些案例在实际开发中经常出现,推荐使用SonarQube、FindSecBugs等工具进行定期扫描。