XXE

XXE

XML 指可扩展标记语言(EXtensible Markup Language)
XML 是一种标记语言,很类似 HTML
XML 的设计宗旨是传输数据,而非显示数据
XML 标签没有被预定义。您需要自行定义标签。
XML 被设计为具有自我描述性。
XML 是 W3C 的推荐标准
XML标签根据自己主观定义,不像HTML是被预定义好的

1
2
3
4
5
6
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>

上例中的标签没有在任何 XML 标准中定义过(比如 和 )。这些标签是由文档的创作者发明的。

这是因为 XML 没有预定义的标签。

这是因为 XML 没有预定义的标签。

在 HTML 中使用的标签(以及 HTML 的结构)是预定义的。HTML 文档只使用在 HTML 标准中定义过的标签(比如html,body等等)。
XML 允许创作者定义自己的标签和自己的文档结构。

DTD
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。

它使用一系列的合法元素来定义文档结构。可被成行地声明于 XML 文档中,也可作为一个外部引用。

1.假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0"  encoding="utd-8"?> ##version声明版本号,encoding声明编码方式一定要写
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>黑娃</to>
<from>铁蛋</from>
<heading>语录</heading>
<body>加油!奥利给!</body>
</note>

//该代码块的意思就是,像上面说的xml语言就是没有预定义的,也就是每一个标签都需要自己创建,然后这里是就是声明编码格式和版本然后
声明下面要引用的几个标签

2.假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:

//文件名是指上面代码块中元素声明保存的在哪个文件的文件名,类似于首先将元素声明写在该文件中然后通过SYSTEM调用该文件,在下方的代码中则不需要再写元素申明
注意外部实体引用时的关键字“SYSTEM”,同时也可以使用“PUBLIC”这个关键字,这两者的区别在于,SYSTEM表示私有的DTD,PUBLIC表示共有的DTD。

3.在 DTD 中,XML 元素通过元素声明来进行声明。
1.元素声明使用下面的语法:

1
2
<!ELEMENT 元素名称 类别>
例:<!ELEMENT to CDATA>
1
2
或者是:<!ELEMENT 元素名称 (元素内容)>
例:<!ELEMENT note (to,from,heading,body)>

2.对于空元素则通过类别关键词EMPTY进行声明:

1
2
<!ELEMENT 元素名称 EMPTY>
例:<!ELEMENT note EMPTY>

XML中5个预定义好的符号

1
2
3
4
5
6
7
8
<  小于号
> 大于号
& & 和
’ ’ 单引号
" " 双引号
尤其是<和&符,在我们编写时不能自定义使用,倘若我们非要使用这些符号,某些文本,比如 JavaScript 代码,包含大量 “<” 或 “&” 字符。为了避免错误,可以将脚本代码定义为 CDATA。怎可以通过CDATA编码。
##在CDATA编码,被CDATA框住的部分,XML编译器会直接忽略,在这其中我们可以包含XML中禁止自定义的5中标识符
CDATA 部分由 “<![CDATA[" 开始,由 "]]>” 结束:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
<![CDATA[
function matchwo(a,b)
{
if (a < b && a < 0) then
{
return 1;
}
else
{
return 0;
}
}
]]>
</script>

CDATA 部分不能包含字符串 “]]>”。也不允许嵌套的 CDATA 部分。

标记 CDATA 部分结尾的 “]]>” 不能包含空格或折行。

DTD外部实体及内部实体
1)内部实体声明:
声明语法:

1
2
3
4
5
6
<!ENTITY 实体名称 "实体的值">
一个实体的引用,由三部分构成:&符号, 实体名称, 分号。
内部实体引用示例:

<?xml version="1.0" encoding="UTF-8"?>
]>

&test;
使用浏览器进行访问,并将xml代码作为参数传入,可以不复制xml声明,记得要将引用实体时的“&”手动编码为“&”(因为我们这里使用的是GET传参的方式,所以传入的内容会被进行URL编码,但是&在URL中被认为是两个参数的分隔符,所以如果我们不对其进行URL编码转换,浏览器会把它当作参数的分隔符来处理)
2)外部实体声明:
声明语法:

1
2
3
4
5
<!ENTITY 实体名称 SYSTEM "URI/URL" >
外部实体引用示例:

<?xml version="1.0" encoding="UTF-8"?>
]>

&xxe;
声明一个外部实体的关键在于“SYSTEM”这个关键字。SYSTEM在此意图让xml解析器知道,现在声明的是一个外部实体,需要从后面的外部资源中获取内容并存储在内部实体,如果后面的外部资源的语法,存在特殊符号,那么xml解析器会报错。
外部实体引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,比如http、file、ftp等,具体内容如下所示:
参数实体应注意以下几点:

Snipaste_2022-05-27_15-28-29

DTD参数实体
参数实体声明:

内部:
外部:
(1)使用 % 实体名(这里面空格不能少) 在 DTD 中定义,并且只能在 DTD 中使用 “%实体名;” 引用
(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用

简单理解呢,就是参数实体不能像普通实体那样在xml文档内容中进行引用,它的引用范围只在当前xml文件的DTD声明中,或者是当前的DTD文件中。

参数实体引用示例:

1
2
3
<?xml version="1.0" encoding="UTF-8"?>
%xxe;
]>

Snipaste_2022-05-27_15-31-02

XXE漏洞
XXE就是XML外部实体注入。当允许引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。

利用场景:有回显和无回显
有回显的情况可以直接在页面中看到Payload的执行结果或现象(带内XML外部实体(XXE),即攻击者可以发送带有XXE有效负载的请求并从包含某些数据的Web应用程序获取响应)
抓包后构造外部实体引用,一般填写本地系统中一定纯在的文档如图中所示,发送包后可以发现文件内的内容被显示了出来

Snipaste_2022-05-27_15-35-23

这样我们就读取到了windows系统的system.ini的文件内容。
但是这样也不代表这个payload的就适用于任何情况,比如我们更换一个读取的文件xmltest2.txt,内容是:

Snipaste_2022-05-27_15-36-08

发送数据包后就会发现产生报错,原因是xml对于5种预定义符是会产生报错提示的

Snipaste_2022-05-27_15-36-38

Snipaste_2022-05-27_15-37-03

解决办法:XML CDATA

Snipaste_2022-05-27_15-38-17

我们也大概知道了CDATA的使用方式,但是其还需要注意几点:
a. CDATA 部分不能包含字符串 “]]>”。也不允许嵌套的 CDATA 部分,这样会导致异常的闭合,从而使解析器报错。

b. 标记 CDATA 部分结尾的 “]]>” 不能包含空格或换行。

链接:

1
https://blog.csdn.net/W_seventeen/article/details/104525167