引言:为什么Java应用程序安全至关重要?
Java仍然是构建企业级和Web应用程序最流行的语言之一。然而,这种流行也吸引了攻击者更多的关注。根据OWASP(开放Web应用程序安全项目)的数据,大多数入侵是由于开发人员的常见错误造成的,而不是平台本身的漏洞。在本文中,我们将分析Java应用程序中最危险的十大漏洞,展示代码示例,并提供实用的安全建议。
1. SQL注入(SQL Injection)
问题:将未经检查的用户数据传递到SQL查询中。
易受攻击的代码示例:
String query = "SELECT * FROM users WHERE username = '" + userInput + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
解决方案:使用参数化查询(PreparedStatement)。
String query = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, userInput);
ResultSet rs = pstmt.executeQuery();
2. 跨站脚本攻击(XSS)
问题:通过用户输入将恶意脚本注入到网页中。
漏洞示例:
String comment = request.getParameter("comment");
out.println("<div>" + comment + "</div>");
解决方案:转义HTML字符。使用诸如OWASP Java Encoder之类的库。
import org.owasp.encoder.Encode;
String comment = request.getParameter("comment");
out.println("<div>" + Encode.forHtml(comment) + "</div>");
3. 不安全的反序列化
问题:攻击者可以传递一个序列化对象,该对象在反序列化时会执行任意代码。
示例:
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Object obj = ois.readObject(); // 危险!
解决方案:
- 不要反序列化来自不可信来源的数据。
- 使用类白名单(look-ahead deserialization)。
- 使用带有安全配置的JSON(Jackson)。
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); // 不安全!
// 正确做法:禁用defaultTyping并使用@JsonTypeInfo
4. 跨站请求伪造(CSRF)
问题:攻击者诱使用户在受信任的网站上执行非预期的操作。
解决方案:使用CSRF令牌。在Spring Security中,这是内置的:
<form action="/transfer" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="text" name="amount"/>
<button type="submit">转账</button>
</form>
5. 身份验证和会话管理缺陷
问题:弱密码、未受保护的cookies、固定会话。
建议:
- 使用bcrypt或Argon2进行密码哈希。
- 为cookies设置
HttpOnly和Secure标志。 - 在N次登录失败后实现锁定机制。
PasswordEncoder encoder = new BCryptPasswordEncoder();
String hashedPassword = encoder.encode(plainPassword);
6. 不安全的配置(Security Misconfiguration)
问题:启用了调试模式、使用默认密码、未受保护的端点。
解决方案: