黑客攻防技术——防止JSON劫持

JSON 劫持是一种特殊的 XSRF 攻击,在某些情况下,它可以违反浏览器的同源策略。它允许一个恶意Web站点获取并处理来自另一个域的数据,因此能够避开通常实施 XSRF 攻击时面临的“单向”限制。

JSON劫持源自于同源策略中的一个怪癖。回到前面浏览器把JavaScript当作代码而非数据处理的示例(它们允许一个Web站点获取并处理来自另一个域的代码)。应用程序在处理跨域代码时,把这些代码视为与调用它的Web站点来自相同的域,因而它们可在那种情况下执行。这种怪癖之所以能够导致漏洞,是因为如今的许多复杂的Web应用程序使用JavaScript传送数据,而当初人们在制定同源策略时并没有预见到这种情况。

12.6.1 JSON

JSON(JavaScript Object Notation, JavaScript 对象符号)是一种可用于序列化任意数据,并能够被JavaScript注释器直接处理的简单数据交换格式。Ajax 应用程序常使用JSON代替最初用于数据传输的XML格式。举一个典型的示例。如果用户执行一项操作,客户端JavaScript使用XMLHttpRequest向服务器传送这项操作。然后,服务器返回一个包含JSON格式数据的轻量级响应。接下来,客户端脚本处理这些数据,并对用户界面进行相应更新。

例如,一个基于 Ajax 的Web邮件应用程序中有一个允许用户在不同数据之间转换的面板。如果用户单击“联系人”(Contacts)选项卡,浏览器就会使用XMLHttpRequest获取用户的个人联系信息,这些信息以JSON格式返回:

 

返回的消息中包含定义一个数组所需的有效JavaScript语法。然后,客户端脚本使用JavaScript注释器构建数组,并处理其内容。

12.6.2 攻击JSON

由于JavaScript被用于传送数据而不是纯粹的代码,因此,一个恶意Web站点可以利用同源策略处理JavaScript方面的缺陷,访问由其他应用程序生成的数据。如前所述,实施这种攻击时需要提交一个 XSRF 请求。但是,由于现在恶意站点能够读取在跨站点响应中返回的数据,因而它能够与目标应用程序进行双向交互。

当然,恶意Web站点还是不能从另一个域加载一段脚本并查看它的内容。无论这时响应中是包含JavaScript还是其他内容,这样做依然会违反同源策略。于是,恶意Web站点使用一个<script>标签将目标脚本包含在内,并在自己的页面中执行这段脚本。这样,恶意站点就能够访问脚本中包含的数据。

到本书截稿时止,我们知道恶意站点可以通过两种方法实施这种攻击:覆写默认的数据构造器或运行一个适当的回调函数(callback function)。

1. 覆写数组构造器

如果目标应用程序返回的JSON数据中包含一个序列化数组,那么恶意Web站点就可以覆写默认的数组构造器,以在构造数组时访问JSON数据。在 Firefox 浏览器中,攻击者可以使用以下脚本实施这种攻击:

 

 

这个概念验证攻击执行以下三项关键操作。

q   它运行一个叫做capture的函数,该函数生成一个警报,显示传送给它的任何数据。

q   它覆写Array对象,并将数组中前三个元素的 setter 定义为capture函数。

q   它通过将相关URL设置为一个<script>标签的src属性,将目标JSON对象包含在页面中。

当实施这个攻击时,<script>标签的目标被获取并执行。同时,序列化对象也得以构建;它是一个多维数组,其中包含受害用户的联系信息。确定数组的每一个元素后,攻击者的脚本调用覆写后的setter,截取元素的内容。在这个示例中,脚本仅显示一系列包含数组数据的警报。

2006年,Jeremiah Grossman在GMail应用程序中发现了这种漏洞。在其他情况下,攻击者也可以覆写Object而非Array对象,达到同样的目的。

2. 执行一个回调函数

在一些应用程序中,易受攻击的应用程序返回的JavaScript并不仅仅包含一个JSON对象,而且还对那个对象调用一个回调函数。例如:

 

“混搭”(mash-up)常常使用这种技巧,其中一个应用程序包含一个来自另一个域的JSON对象,并在它访问脚本的请求中指定一个回调函数。返回的脚本对JSON对象调用指定的回调函数,允许调用函数的应用程序以任意方式处理数据。

由于这种机制主要是为解决浏览器的同源限制而特别设计的,因此攻击者当然可以利用它来截获从其他域返回的数据。在前面的示例中,攻击者只需运行showContacts函数并包含目标脚本,就可以实施攻击。例如:

 

12.6.3 查找JSON劫持漏洞

由于JSON劫持属于一种跨站点请求伪造漏洞,因此可以使用与前面描述的查找 XSRF 漏洞时使用的相同方法来查找某些JSON劫持漏洞。但是,因为攻击者可以利用JSON劫持获取其他域中的任意数据,而不仅仅是执行跨域操作,所以,与查找标准的XSRF漏洞时不同,这时还必须探查其他一些功能。

 

渗透测试步骤

q   如果应用程序使用Ajax,寻找任何包含JSON格式的敏感数据或其他JavaScript的响应。

q   与利用标准XSRF漏洞时一样,确定是否可以构造一个跨域请求获取上述数据。如果请求中存在一些能够预测的参数,那么应用程序可能易于受到攻击。

q   只有使用GET方法才能实施JSON劫持攻击,因为只有使用这个方法才能获取在<script>中指定的URL。如果应用程序自己的请求使用POST方法,确定在将请求中的方法改为GET方法并将主体参数移动到URL查询字符串中之后,应用程序是否依然接受这个请求。

q   如果前面的要求得到满足,确定是否可以构造一个Web页面,并将其包含在<script>标签中,成功访问目标应用程序响应中的数据。尝试使用前面的两种方法或者其他任何适用于特殊情况的方法实施攻击。

 

12.6.4 防止JSON劫持

如前文所述,实施JSON劫持攻击必须满足几个前提条件。因此,要防止这种攻击,必须违反其中至少一个前提条件。到本书截稿时止,下面的每一种防范机制应足以挫败JSON劫持攻击。但是,随着对这些攻击研究的深入,要想获得深层保护,我们建议在防御攻击时同时采用几种防范措施。

q   应用程序应使用标准的反XSRF防御阻止跨域请求访问敏感数据。访问JSON对象的请求中应包含一个无法预测的参数,并且在返回数据前应对其进行确认。

q   当应用程序从它自己的域中获取JSON对象时,并不仅限于使用<script>标签包含这个对象。因为请求在站内执行,客户端代码可以使用XMLHttpRequest自由访问响应数据,并可在将其作为JavaScript解释前对它进行其他处理。这意味着,为防止JOSN劫持,应用程序可以在响应的开始部分插入无效或有问题的JavaScript,客户应用程序在处理脚本前将会删除这些内容。Google 在防止前述针对 GMail 的攻击时即采用了这种方法,在返回的脚本开始部分插入以下代码:

while(1);

q   由于应用程序可以使用XMLHttpRequest获取JSON数据,因此它也可以使用POST请求完成这项任务。如果应用程序仅接受使用POST访问JSON对象的请求,它就能够阻止第三方站点将这些请求包含在<script>标签内。

posted on 2013-05-30 11:28  一个石头  阅读(3144)  评论(0)    收藏  举报