点击阅读
XML外部实体注入(XML External Entity)
XML 指可扩展标记语言(eXtensible Markup Language)
XML 被设计用来传输和存储数据。
HTML 被设计用来显示数据。
xml文档结构
1 | <!--XML声明--> |
其中包括XML声明、DTD文档类型定义(可选)、文档元素
- DTD(Document Type Definition)
- DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
- 内部声明DTD
<!DOCTYPE 根元素 [元素声明]>
- 引用外部DTD
<!DOCTYPE 根元素 SYSTEM "文件名">
或者<!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">
- 内部声明实体
<!ENTITY 实体名称 "实体的值">
- 引用外部实体
<!ENTITY 实体名称 SYSTEM "URI">
或者<!ENTITY 实体名称 PUBLIC "public_ID" "URI">
- 参数实体
<!ENTITY % 实体名称 "实体内容">
或者<!ENTITY % 实体名称 "URI">
- 注意:参数实体是在DTD中被引用的,而其余实体是在xml文档中被引用的
不同程序支持的协议
libxml2 | PHP | Java | .NET |
---|---|---|---|
file | file | file | file |
http | http | http | http |
ftp | ftp | ftp | ftp |
php | https | https | |
compress.zlib | jar | ||
compress.bzip2 | netdoc | ||
data | mailto | ||
glob | gopher | ||
phar |
包含内部实体的XML文档:
1 | <?xml version="1.0" encoding="utf-8"?> |
包含外部实体的XML文档:
1 | <?xml version="1.0" encoding="utf-8"?> |
一些仅使用JSON去访问服务的客户端, 可能接受XML作为输入内容,这是可以修改Content-Type为xml看是否解析发送的内容
比如发送内容如下:
1 | <?xml version="1.0" encoding="utf-8"?> |
意思大概是我们定义了一个名为test2的,值为test3的实体<t>&test2;</t>
将实体呈现出来
只要稍加修改便可以访问系统上本地文件或是远程系统上的文件
如<!ENTITY test2 "test3">
改为<!ENTITY test2 SYSTEM "file:///home/test3.txt">
,便可读取/home/test3.txt
文件
以一道题为例
api调用
设法获得目标机器/home/ctf/flag.txt中的flag值。
题目入口:http://web.jarvisoj.com:9882/
抓包可看到传输的json数据
将Content-Type: application/json改为Content-Type: application/xml并传输xml格式的数据
1 | <?xml version="1.0" encoding="utf-8"?> |
读取flag
也可以读取/etc/passwd
xxe防御
- 使用开发语言提供的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
- 过滤用户提交的XML数据
关键词:<!DOCTYPE
和<!ENTITY
,或者,SYSTEM
和PUBLIC
参考: