Java应用程序安全:十大漏洞——第二部分
在第一部分中,我们分析了Java应用程序的前五个关键漏洞。今天我们继续学习,并探讨每位开发人员都应了解的剩余五个威胁。Java入门和资深程序员——这些信息将帮助您编写更安全的代码。在编程世界中,安全不是可选项,而是必需品。
6. 外部XML实体(XXE)
XXE攻击发生在应用程序处理包含外部实体引用的XML文档时。攻击者可以读取本地文件、执行SSRF攻击或引发拒绝服务。
易受攻击的代码
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xmlData)));
防护措施
- 禁用外部实体和DTD
- 使用安全的解析器
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
7. 不安全的反序列化
反序列化不可信数据可能导致任意代码执行。这是Java中最危险的漏洞之一,因为它通常允许完全攻陷服务器。
攻击示例
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
Object obj = ois.readObject(); // 危险!
防护方法
- 不要反序列化来自不可信来源的数据
- 使用类白名单
- 采用替代格式(JSON、Protocol Buffers)
8. SQL注入
尽管这是编程中的经典问题,但SQL注入在Java应用程序中仍然存在。始终使用参数化查询。
错误做法(易受攻击)
String query = "SELECT * FROM users WHERE name = '" + userName + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
正确做法(安全)
String query = "SELECT * FROM users WHERE name = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, userName);
ResultSet rs = pstmt.executeQuery();
对于Java入门者,这条规则应成为公理:永远不要拼接字符串来构造SQL查询。
9. 认证和会话管理缺陷
弱认证、易受攻击的会话以及密码管理不当是Java Web应用程序中的常见问题。
建议
- 使用现代密码哈希算法(bcrypt、Argon2)
- 正确设置会话生命周期
- 使用安全的cookie(HttpOnly、Secure、SameSite)
- 实施多因素认证
10. 使用含有已知漏洞的组件
Java生态系统拥有丰富的库,但许多项目使用带有公开CVE的过时版本。这是最常见的安全问题之一。
如何防护
- 定期更新依赖项
- 使用分析工具(OWASP Dependency-Check、Snyk)
- 订阅所用库的安全通知
- 自