json及jsonp注入


json以及jsonp

前言 

JSONP全名为JSON with Padding,其存在的意义便有绕过诸如同源策略强制执行XMLHttpRequest(AJAX requests)。是基于 JSON 格式的为解决跨域请求资源而产生的解决方案。他实现的基本原理是利用了 HTML 里 元素标签,远程调用 JSON 文件来实现数据传递。如要在 a.com 域下获取存在 b.com 的 JSON 数据( getUsers.JSON ):

JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。

JSONP注入是一个不太常见但影响非常广泛且极危险的漏洞,由于最近几年对JSON, web APIs以及跨域通信的需求增多,不得不引起我们的重视。

json基础 

JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。

1、JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号”“是定义符。

2、大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。

3、上述两种集合中若有多个子项,则通过英文逗号,进行分隔。

4、键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号”“,以便于不同语言的解析。

5、JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用,日期类型比较特殊,这里就不展开讲述了,只是建议如果客户端没有按日期排序功能需求的话,那么把日期时间直接作为字符串传递就好,可以省去很多麻烦。

json实例 

    // 描述一个人 

    var person = {

        "Name": "Bob", 

        "Age": 32, 

        "Company": "IBM", 

        "Engineer": true } 

    // 获取这个人的信息 

    var personAge = person.Age; 

    // 描述几个人 

    var members = [ 

    { 

        "Name": "Bob", 

        "Age": 32, 

        "Company": "IBM", 

        "Engineer": true 

    }, 

    { 

        "Name": "John", 

        "Age": 20, 

        "Company": "Oracle", 

        "Engineer": false 

    },

     {

         "Name": "Henry", 

        "Age": 45,

         "Company": "Microsoft",

"Engineer": false

    }

                 ] 

    // 读取其中John的公司名称 

    var johnsCompany = members[1].Company; 

    // 描述一次会议 

    var conference = { 

    "Conference": "Future Marketing", 

    "Date": "2012-6-1", 

    "Address": "Beijing", 

    "Members": 

    [ 

        { 

            "Name": "Bob", 

            "Age": 32, 

            "Company": "IBM", 

            "Engineer": true

         }, 

        { 

            "Name": "John", 

            "Age": 20, 

            "Company": "Oracle", 

            "Engineer": false 

        }, 

        { 

            "Name": "Henry", 

            "Age": 45, 

            "Company": "Microsoft", 

            "Engineer": false 

        } 

    ] 

                } 

    // 读取参会者Henry是否工程师 

    var henryIsAnEngineer = conference.Members[2].Engineer;

什么是jsonp 

1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;

2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如script、img、iframe);

3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;

4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;

5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。  (重点--简而言之。我们要加载远程文件而js又可以跨域,那么我们跨域调用远程js文件,便可以实现同源策略之下的跨域)

6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。

7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

jsonp跨域实例

前端

jsonp.html

     

    

    

    

jsonp测试页面

    

    

    

在用户访问恶意网站时:

    

(1).这段JS代码会要求浏览器发送一个GET请求到http://www.Bank.com/UserInfo,于是浏览器按照指示,带上本地的Cookie信息,发送一个http的GET请求。

(2).www.Bank.Com接受到请求后,确认身份后,响应请求返回了一个JSON数组/JavaScript代码段。

(3).客户端接受到这段JS脚本后,如果返回的是一个JSON数组,比如:

    [{"Id":3,"Name":hyddd,"Money":10000}]

JSON数组被认为是一段可执行的JavaScript脚本,于是浏览器会解析执行。

如果返回的是一个JSON对象呢?

    {"Id":3,"Name":hyddd,"Money":10000}

呵呵,这个是不会被浏览器执行的,因为浏览器认为:它不是一个JavaScript脚本。

如果它返回的是一个JavaScript脚本的话,恩,这得具体问题具体分析了,不一定能拿到什么数据。

(4).看下面这段JavaScript脚本:

    

它的作用就是发送受害者的私隐信息到恶意站点的。

这里可能有人不理解,我大概说一下:

Object.prototype.__defineSetter__,可以看做是JavaScript中的Hook(有人把这个称为JavaScript函数劫持,注意JavaScript的函数劫持和JavaScript Hijacking不是同一个概念,JavaScript Hijacking的核心思想和CSRF攻击的核心思想应该是一致的),这里是对Object的Money属性设置了一个Hook,在JavaScript中,由于其他的对象都是派生自Object的,所以这段代码就对所有对象的Money属性都做了一个Hook,当有对象设置它的Money属性时,都会触发上面这段代码的运行。注意的是:__defineSetter__这个在IE系列的浏览器好像是不受支持的(在IE6下试了不行),但FireFox系列的浏览器是肯定支持的。

后面的var objString=""...这就是发送受害者信息到恶意站点了,这里不说了。

当浏览器解析(3)中的JSON数组时,会新建一个对象并赋值,这时候就出发了上面这段代码,结果私隐信息就发送到恶意站点了。

通过

    Object.prototype.__defineSetter__

这个函数来触发自己的恶意代码。

但是这个函数在当前的新版本chrome和firefox中都已经失效了。

解决方法 

1、验证 HTTP Referer 头信息;

2、在请求中添加 csrfToken 并在后端进行验证;

jsonp劫持

寻找jsonp的接口 

1.burp抓包,一般有jsonp的数据传输会在mimetype中显示为script,通过排序可以快速得找到



2.火狐控制台查找包


3.fuzz

如果jsonp的接口没有敏感信息传输,json数据包中恰好有的话,我们可以尝试一下程序员是否有开发jsonp的格式,大多数程序员喜欢把jsonp的回传参数命名为callback

当然还有其他的可能,字典用Intruder Fuzz一下试试:

    callback=attack

    cb=attack

    call=attack

    jsonp=attack

    jsonpcallback=attack

    jsonpcb=attack

    json=attack

    jsoncallback=attack

    jcb=attack

某云实例 


复制到url里便可以检验是否存在jsonp接口漏洞。

修改callback原函数便可将json数据全部显示出来,一些敏感信息。

poc

    

    

poc可以继续构造制定发送到自己的页面,可见jsonp的原理与csrf基本为一致的,利用用户的身份来做一些事情,或者发送自己的信息给别人,

某X jsonp




POC

    

    

目前挖掘jsonp 一般是F12 寻找callback函数,推荐一款自动检测XSS jsonp的谷歌插件 XssSniper

绕过

一些对referer 进行验证,但是有的时候空referer可以绕过验证。

---

参考:https://blog.csdn.net/yjclsx/article/details/80340901

参考:http://www.cnblogs.com/hyddd/archive/2009/07/02/1515768.html

参考:https://shiyousan.com/post/635441704246553316

你可能感兴趣的:(json及jsonp注入)