乐闻世界logo
搜索文章和话题

什么是 XML 注入攻击,如何防止 XXE 攻击?

2月21日 14:22

XML 注入是一种安全漏洞,攻击者通过在 XML 输入中注入恶意内容来操纵应用程序的 XML 解析行为。这种攻击可能导致信息泄露、拒绝服务、权限提升等安全问题。

XML 注入的类型

1. XML 外部实体(XXE)攻击

XXE(XML External Entity)是最常见的 XML 注入攻击类型。攻击者利用 XML 解析器处理外部实体的能力来读取服务器上的敏感文件或发起 SSRF 攻击。

攻击示例:

xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE data [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <data> <username>&xxe;</username> </data>

危害:

  • 读取服务器上的敏感文件
  • 发起 SSRF(服务器端请求伪造)攻击
  • 执行远程代码执行(在某些情况下)
  • 拒绝服务攻击

2. XML 注入攻击

攻击者通过注入 XML 标签来修改 XML 文档的结构。

攻击示例:

xml
<!-- 正常输入 --> <user> <name>John</name> </user> <!-- 恶意输入 --> <user> <name>John</name> <role>admin</role> </user>

3. XPath 注入

类似于 SQL 注入,攻击者通过操纵 XPath 查询来获取未授权的数据。

攻击示例:

xml
<!-- 正常查询 --> //user[username='john' and password='secret'] <!-- 恶意查询 --> //user[username='john' or '1'='1']

防护措施

1. 禁用外部实体

Java 示例:

java
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.setXIncludeAware(false); dbf.setExpandEntityReferences(false); DocumentBuilder db = dbf.newDocumentBuilder();

Python 示例:

python
from lxml import etree # 禁用外部实体 parser = etree.XMLParser(resolve_entities=False, load_dtd=False) tree = etree.parse("data.xml", parser)

PHP 示例:

php
libxml_disable_entity_loader(true); $xml = simplexml_load_string($xmlString);

2. 输入验证和过滤

java
// 验证 XML 输入 public boolean isValidXML(String xml) { try { // 检查是否包含恶意内容 if (xml.contains("<!DOCTYPE") || xml.contains("<!ENTITY")) { return false; } // 验证 XML 格式 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); DocumentBuilder db = dbf.newDocumentBuilder(); db.parse(new InputSource(new StringReader(xml))); return true; } catch (Exception e) { return false; } }

3. 使用白名单验证

java
// 白名单验证 public boolean isValidElement(String elementName) { Set<String> allowedElements = new HashSet<>(Arrays.asList( "name", "email", "age" )); return allowedElements.contains(elementName); }

4. 使用安全的 XML 解析器

推荐的安全配置:

java
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); // 使用 Schema 验证 dbf.setNamespaceAware(true); dbf.setSchema(schema);

5. XPath 注入防护

java
// 使用参数化查询 public User getUser(String username, String password) { try { XPathFactory xPathFactory = XPathFactory.newInstance(); XPath xpath = xPathFactory.newXPath(); // 使用变量而不是字符串拼接 XPathExpression expr = xpath.compile( "//user[username=$username and password=$password]" ); XPathExpression expr = xpath.compile( "//user[username=$username and password=$password]" ); // 设置参数 SimpleVariableResolver resolver = new SimpleVariableResolver(); resolver.addVariable(new QName("username"), username); resolver.addVariable(new QName("password"), password); xpath.setXPathVariableResolver(resolver); Node node = (Node) expr.evaluate(doc, XPathConstants.NODE); return parseUser(node); } catch (Exception e) { throw new RuntimeException("XPath query failed", e); } }

6. 使用 XML Schema 验证

java
// 使用 Schema 验证输入 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = factory.newSchema(new File("schema.xsd")); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setSchema(schema); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File("input.xml"));

最佳实践

  1. 禁用 DTD 和外部实体:这是防止 XXE 攻击的最有效方法
  2. 使用白名单验证:只允许预定义的元素和属性
  3. 输入过滤:过滤掉危险的 XML 结构
  4. 使用安全的解析器:配置解析器以禁用危险功能
  5. 最小权限原则:限制 XML 处理的权限
  6. 定期更新:保持 XML 解析库的最新版本
  7. 安全编码:遵循安全编码最佳实践
  8. 安全测试:定期进行安全测试和代码审查

检测工具

  1. OWASP ZAP:Web 应用安全扫描器
  2. Burp Suite:Web 应用安全测试工具
  3. XMLSec:XML 安全库
  4. SonarQube:代码质量和安全分析工具

XML 注入是一个严重的安全问题,必须在设计和实现阶段就考虑防护措施。通过禁用外部实体、输入验证和使用安全的解析器配置,可以有效地防止 XML 注入攻击。

标签:XML