计算机基础阅读 02月21日 14:22
什么是 XML 注入攻击,如何防止 XXE 攻击?
XML 注入是一种安全漏洞,攻击者通过在 XML 输入中注入恶意内容来操纵应用程序的 XML 解析行为。这种攻击可能导致信息泄露、拒绝服务、权限提升等安全问题。XML 注入的类型1. XML 外部实体(XXE)攻击XXE(XML External Entity)是最常见的 XML 注入攻击类型。攻击者利用 XML 解析器处理外部实体的能力来读取服务器上的敏感文件或发起 SSRF 攻击。攻击示例:<?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 文档的结构。攻击示例:<!-- 正常输入 --><user> <name>John</name></user><!-- 恶意输入 --><user> <name>John</name> <role>admin</role></user>3. XPath 注入类似于 SQL 注入,攻击者通过操纵 XPath 查询来获取未授权的数据。攻击示例:<!-- 正常查询 -->//user[username='john' and password='secret']<!-- 恶意查询 -->//user[username='john' or '1'='1']防护措施1. 禁用外部实体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 示例:from lxml import etree# 禁用外部实体parser = etree.XMLParser(resolve_entities=False, load_dtd=False)tree = etree.parse("data.xml", parser)PHP 示例:libxml_disable_entity_loader(true);$xml = simplexml_load_string($xmlString);2. 输入验证和过滤// 验证 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. 使用白名单验证// 白名单验证public boolean isValidElement(String elementName) { Set<String> allowedElements = new HashSet<>(Arrays.asList( "name", "email", "age" )); return allowedElements.contains(elementName);}4. 使用安全的 XML 解析器推荐的安全配置: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 注入防护// 使用参数化查询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 验证// 使用 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 注入攻击。