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 示例:
javaDocumentBuilderFactory 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 示例:
pythonfrom lxml import etree # 禁用外部实体 parser = etree.XMLParser(resolve_entities=False, load_dtd=False) tree = etree.parse("data.xml", parser)
PHP 示例:
phplibxml_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 解析器
推荐的安全配置:
javaDocumentBuilderFactory 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"));
最佳实践
- 禁用 DTD 和外部实体:这是防止 XXE 攻击的最有效方法
- 使用白名单验证:只允许预定义的元素和属性
- 输入过滤:过滤掉危险的 XML 结构
- 使用安全的解析器:配置解析器以禁用危险功能
- 最小权限原则:限制 XML 处理的权限
- 定期更新:保持 XML 解析库的最新版本
- 安全编码:遵循安全编码最佳实践
- 安全测试:定期进行安全测试和代码审查
检测工具
- OWASP ZAP:Web 应用安全扫描器
- Burp Suite:Web 应用安全测试工具
- XMLSec:XML 安全库
- SonarQube:代码质量和安全分析工具
XML 注入是一个严重的安全问题,必须在设计和实现阶段就考虑防护措施。通过禁用外部实体、输入验证和使用安全的解析器配置,可以有效地防止 XML 注入攻击。