JSON

JSON劫持漏洞攻防原理及演练 - 技术狂

字号+ 作者:H5之家 来源:H5之家 2017-01-22 15:00 我要评论( )

JSON劫持漏洞攻防原理及演练 - 技术狂

注* 作者发表这篇文章的时间较早,某些方法可能并不是最好的解决方案,但针对这种漏洞进行的攻击还依然可见,如早期的: QQMail邮件泄露漏洞 ,下面介绍的是对这种攻击原理的介绍。

不久之前,我写了一篇文章《一个微妙的JSON漏洞》,文中讲到这个漏洞可能会导致敏感信息泄露。针对该漏洞的特点,通过覆盖JavaScript数组构造函数以窃取(暴露)JSON返回数组,而现在大多数浏览器还无法防范这种攻击。

然而,通过和微软的Scott Hanselman交流,我了解到另外一个方法可能会影响更多的浏览器。在上周的挪威开发者大会上,我做了一个针对Json劫持漏洞的演示。

在我进一步讲之前,我先说一说,这个漏洞可能带来的影响。

在以下条件下,会出现这个漏洞:首先暴露JSON服务,并且该服务会返回敏感数据;返回JSON数组;对GET请求做出响应;发送这个请求的浏览器启用了JavaScript并且支持_defineSetter_方法。

如果我们不使用JSON发送敏感数据,或者只对报文请求做出响应,那么我们的网站就不存在这个漏洞。

我不喜欢用流程图展示这个过程,我会尽量用图表描述。在第一页截图上,我们可以看到不知情的受害者登陆漏洞网站,漏洞网站返回了一个身份认证的cookie。

我们都可能收到过一些垃圾邮件,邮件中附有链接,发送者声称这有一段搞笑视频。这些大量的垃圾邮件都是一些别有用心的人发的。

但是实际上,这些链接指向的是那些坏家伙自己网站。当我们点击了链接,接下来的两个步骤会迅速进行。第一,我们的浏览器向这些网站发送请求。

  

第二,那些网站会响应一些包含JavaScript的HTML。这些JavaScript会带一个script标记。当浏览器检测到script标记,它就会向那些漏洞网站再发一个下载脚本的GET请求,携带着身份验证的cookie。

这样,那些坏家伙就伪装成了受害者的浏览器,利用其身份发出了一个包含敏感数据的JSON请求。接着,把JSON加载为可执行的JavaScript,这样以来,那些黑客就能够获取到这些数据。
为了加深理解,我们可以看看一个攻击的实际代码。假如漏洞网站返回带有敏感数据的JSON响应通过如下方式发送:

[Authorize] publicJsonResultAdminBalances(){ varbalances=new[]{ new{Id=1,Balance=3.14}, new{Id=2,Balance=2.72}, new{Id=3,Balance=1.62} }; returnJson(balances); }

需要说明的是,上面的演示不是专门针对ASP.NET或者ASP.NET MVC,我仅仅是恰巧用ASP.NET MVC来演示这个漏洞而已。
假如这是HomeController的一种方法,我们通过对/Home/AdminBalances发送了一个GET请求,并且返回如下JSON文本:

[{“Id”:1,”Balance”:3.14},{“Id”:2,”Balance”:2.72},{“Id”:3,”Balance”:1.62}]

注意,我定义这个方法时使用了Authorize属性,用来验证请求者的身份。所以一个匿名的GET请求将不会得到敏感数据。
重要的是:这是一个JSON数组。包含JSON数组的文本是一个有效的JavaScript脚本,并且可以被执行。仅仅包含JSON对象的脚本不是一个有效的JavaScript可执行文件。
举个例子,如果我们有一个包含如下JSON代码的JavaScript文档:

{“Id”:1,”Balance”:3.14}

并且有一个指向这个文档的脚本标签:

这样,我们会在HTML页中得到一个JavaScript错误。然而,倘若存在一个不幸的巧合,如果我们有一个script标签,这个标签指向仅仅含有一个JSON数组的文档,这样的话,这个标签就会被误认为是有效的JavaScript,并且数组会生效。

下面就让我们看看那些别有用心的人的服务器上的HTML页。

注*这里我们可以看到使用 Json Object 而不是Json Array返回你的数据,可以在一定程度上预防这种漏洞。

...

看到了什么?黑客正在改变对象的原型,用_defineSetter_这种特殊方法,覆盖JSON对象(Object)原本应有的默认行为。

在这个例子中,一个命名合适的ID在任何时候都可以被设置到任何对象上时,一个匿名的函数将会被调用,这个函数将会利用alert 函数显示属性值。注意,这时脚本仅仅会将数据发回给那些坏家伙,而不会发送敏感数据。

就像之前提到的,坏家伙需要使我们在登录漏洞网站后不久并且在会话仍旧有效时,访问他的恶意的网页。通过含有恶意网站链接的邮件进行钓鱼攻击的方式是很典型的。

如果你仍旧点击链接登录原网站,浏览器将会在加载脚本标签中引用的脚本并向网站发送你的身份验证cookie。直到连接上原网站,我们对JSON数据发出一 个有效的身份验证请求,并且会收到在我们浏览器中响应的有效数据。这些话可能听着很熟悉,因为它是一个真的变种伪造跨站请求,之前我写过这种情况。

因为在IE8上_defineSetter_是一个无效的方法,所以在IE8上看不到现象。我在Chrome和Firefox上都试过,都可以。

避免这个漏洞也很简单:或者从不发送JSON数组,或者只访问HTTP POST以获得需要的数据。举个例子:在ASP.NET MVC中,你可以用AcceptVerbsAttribute来实现:

[Authorize] [AcceptVerbs(HttpVerbs.Post)] publicJsonResultAdminBalances(){ varbalances=new[]{ new{Id=1,Balance=3.14}, new{Id=2,Balance=2.72}, new{Id=3,Balance=1.62} }; returnJson(balances); }

这个方法的一个问题就是:像jQuery这样的很多JS库默认都是用GET方式发送JSON请求,而不是POST。举个例子,$.getJSON 默认发起的是GET请求。所以,当进行这种JSON访问时,我们需要确信我们是用客户端库发起的POST请求。

ASP.NET和WCF JSON服务端实际上在对象中用了“d”属性,包裹了他们的JSON,这我在另一篇 文章 中讨论过:

必须经过这些属性获得数据,似乎有些奇怪,但这需要通过一个客户端代理来实现来去除“d”属性,,以便不影响最终用户。

在ASP.NET MVC下,绝大多数开发者没有生成客户端代理,而是使用jQuery和其他类似的库,这样一来使用“d”属性的就有些尴尬。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Json解析教程(一.org.json的使用)

    Json解析教程(一.org.json的使用)

    2017-01-23 09:00

  • 2.8.3 解析JSON和XML:jQuery.parseJSON( data )、jQuery.parseX

    2.8.3 解析JSON和XML:jQuery.parseJSON( data )、jQuery.parseX

    2017-01-22 14:04

  • 批量提交form表单(JSON格式)

    批量提交form表单(JSON格式)

    2017-01-22 13:00

  • 基于json的AJAX高级开发技术

    基于json的AJAX高级开发技术

    2017-01-22 12:02

网友点评
/