JSONP基础
JSONP(JSON with Padding) 其目的是为了绕过诸如同源策略强制执行XMLHttpRequest
(AJAX requests)去请求JSON数据。举个例子:
网站A: www.competition.com
提供赛事信息 其接口 competition.com/data.json
以json
格式返回了赛事数据,其分析子站B: analysis.competition.com
根据赛事信息进行分析 并展示给用户
那么B站的ajax
想要获取data怎么做?
答案是很困难的,普通的ajax
是无法完成的
因为ajax
遵守同源策略,A、B是异源,异源资源共享通常是不允许的(除了脚本、链接等 详情可以看同源策略这篇文章)
那么怎么办呢?
我们可以发现,同源策略是允许跨域加载脚本的,我们的思路就是把数据放进js文件中,由于跨域脚本嵌入是可行的,从而跨域加载数据,但直接把json数据方式js文件格式是不正确的,我们的思路是设置一个函数调用,把json数据作为实参传递进来,然后在B中对形参进行处理,这样就跨域获取到了json数据。即script标签不受同源安全策略限制,它可以向别的域发送get请求。
举个例子:
|
|
我们以程序员的角度来考虑,整个系统应该怎么编写,这样可以更好的帮助我们理解数据交换流程:
首先,定义一个用于接收数据的回调函数:
|
|
然后我们用<script>
标签去跨域请求数据:
|
|
当获取完如上url的内容后,会自动解释成js代码执行。由此来看,以上url访问输出的结果类似如下:
|
|
一般后台会根据fn
参数返回相应名称的函数,类似下面的方式:
|
|
JSONP 利用
JSON劫持
即JSON Hijacking
其实属于CSRF攻击的范围,当某网站使用JSONP传递敏感数据的时候,攻击者可以构造恶意JSONP调用界面,诱导被攻击者访问。
当我们找到一个jsonp接口且返回数据包含敏感信息时,我们可以在一个访问量高的站点或者自己博客插入一段js,去跨域加载这个jsonp接口,如果访问者之前登陆过(有cookie信息),则可以批量获取重要信息:
例如 我们在我们博客中加上这段内容
而aim.com
这个jsonp接口返回的信息又包含敏感信息:
|
|
当有用户访问我们博客且之前在aim.com
登陆过时,则可以批量劫持敏感信息。
这类攻击常见的防御方式是判断reference
是否为可信来源或添加随机值,但存在reference
伪造(qq.com.evil.com)、空reference、暴力穷举等问题,最有效的方式还是综合防御(判断reference
和添加随机字串),或使用加在url中的token
可以完美解决。
callback函数可定义的安全问题
根据上面的内容,我们可以看到,callback函数的名称可以自定义,而输出环境又是js环境,如果没有严格过滤或审查,可以引起很多其他的攻击方式。
比如后台使用$callback = $_GET['callback'];print $callback.'(data)';
这样子,认为callback
是可信的,而攻击者完全可以将alert(/xss/)
作为callback
参数传递进去。
这种问题有两种解决方案:
#严格定义 Content-Type: application / json
这样的防御机制导致了浏览器不解析恶意插入的 XSS 代码
#过滤 callback 以及 JSON 数据输出
这样的防御机制是比较传统的攻防思维,对输出点进行 xss 过滤。
基础函数调用
如果我们的回调函数被硬编码进响应(即多个不同类型的请求都采用同样的回调函数名,例如callback
等),那么就会存在基础函数调用的危害。
JSONP 漏洞挖掘
可以去搜索callback
、.json
关键字
利用搜索引擎
|
|
防御
- 调用
JSON
文件限制Refererence
、部署一次性Token
在url中(QQ这么做的·http://r.qzone.qq.com/cgi-bin/tfriend/friend_show_qqfriends.cgi?uin=[QQ号码]&g_tk=[随机token]
) - 严格暗账 JSON 格式标准输出
Content-Type
及编码(Content-Type
:application/json
;charset=utf-8
) 阻值了返回当成js执行的可能 - 严格过滤
callback
函数名及JSON
里数据的输出 按照xss过滤 - 严格限制对 JSONP 输出
callback
函数名的长度,函数调用名不可预测