Ajax调用'for (;;);{json data}'的意思吗?

< p > 可能的重复: < br > 为什么人们会写这样的代码:“不要作恶。(“;;;);”;在json响应前? < / p >

我发现这种语法在Facebook上用于Ajax调用。我对响应开始时的for (;;);部分感到困惑。它的用途是什么?

这是调用和响应:

GET http://0.131.channel.facebook.com/x/1476579705/51033089/false/p_1524926084=0

回应:

for (;;);{"t":"continue"}
49619 次浏览

我怀疑它存在的主要原因是控制。它部队你通过Ajax检索数据,而不是通过JSON-P或类似的(使用script标记,因此会失败,因为for循环是无限的),从而确保同源策略生效。这让他们可以控制哪些文档可以调用api。具体来说,只有与该API调用具有相同起源的文档,或者Facebook通过歌珥(在支持CORS的浏览器上)特别授予访问权限的文档。因此,您必须通过浏览器强制执行SOP的机制请求数据,并且必须了解该序言,并在反序列化数据之前删除它。

所以,是的,这是关于控制(有用的)访问数据。

for(;;);是一个无限循环(如果你想的话,你可以使用Chrome的JavaScript控制台在一个选项卡中运行该代码,然后看着任务管理器中的cpu使用率一路飙升,直到浏览器杀死该选项卡)。

所以我怀疑它可能是放在那里挫败任何人试图解析使用eval或任何其他技术执行返回的数据的响应。

为了进一步解释,使用JavaScript的eval()函数解析一些json格式的数据是相当常见的,方法如下:

var parsedJson = eval('(' + jsonString + ')');

...这被认为是不安全的,然而,如果由于某种原因,您的json格式的数据包含可执行的JavaScript代码,而不是(或除了)json格式的数据,那么该代码将由eval()执行。这意味着如果您正在与一个不受信任的服务器通信,或者如果有人破坏了一个受信任的服务器,那么他们可以在您的页面上运行任意代码。

正因为如此,使用eval()这样的东西来解析JSON格式的数据通常是不受欢迎的,而Facebook JSON中的for(;;);语句将阻止人们以这种方式解析数据。任何尝试的人都会得到一个无限循环。所以从本质上讲,这就像Facebook试图强制人们使用其API,以一种不会让他们容易受到未来试图劫持Facebook API作为载体的攻击的方式。

这看起来像是一个防止CSRF攻击的黑客。有特定于浏览器的方法来挂钩到对象创建,所以恶意网站可以先这样做,然后有以下:

<script src="http://0.131.channel.facebook.com/x/1476579705/51033089/false/p_1524926084=0" />

如果在JSON之前没有一个无限循环,则会创建一个对象,因为JSON可以是eval()艾德作为javascript,钩子将检测它并嗅探对象成员。

现在,如果你通过浏览器访问该网站,同时登录到Facebook,它可以获取你的数据,就像它是你一样,然后通过AJAX或javascript帖子发送回它自己的服务器。

我来晚了一点,tj基本上已经解开了这个谜团,但我想我应该分享一篇关于这个特定主题的好论文,其中有很好的例子,并对这个机制提供了更深入的见解。

这些无限循环是对抗“Javascript劫持”的对策,这种攻击类型因耶格罗斯曼发布的对Gmail的攻击而引起了公众的关注。

这个想法很简单,也很漂亮:许多用户倾向于永久登录Gmail或Facebook。所以你要做的就是建立一个网站,在恶意网站的Javascript中重写对象或数组构造函数:

function Object() {
//Make an Ajax request to your malicious site exposing the object data
}

然后在该站点中包含<script>标记,例如

<script src="http://www.example.com/object.json"></script>

最后,您可以在恶意服务器的日志中读取有关JSON对象的所有信息。

如前所述,指向. xml的链接。

Facebook内部有大量开发人员参与许多项目,有些人犯小错误是很常见的;无论是像无法转译插入HTML或SQL模板中的数据这样简单而严重的问题,还是像使用eval(有时效率很低,可以说是不安全的)或JSON.parse(兼容但不是普遍实现的扩展)而不是“已知的良好”JSON解码器这样复杂而微妙的问题,重要的是要找到方法,轻松地在开发人员群体中实施最佳实践。

为了面对这一挑战,Facebook最近一直在“全力”设计内部项目,以优雅地执行这些最佳实践,老实说,对这个特定情况真正有意义的唯一解释只是:内部有人决定,所有JSON解析都应该通过其核心库中的单个实现,而强制执行的最佳方法是让每个API响应自动在前面添加for(;;);

这样做,开发人员不能“懒惰”:如果他们使用eval(),他们会注意到立即,想知道发生了什么,然后意识到他们的错误并使用批准的JSON API。

所提供的其他答案似乎都分为两类:

  1. 误解JSONP,或者
  2. 误解“JSON劫持”。

第一类依赖于攻击者可以“使用JSONP”向不支持JSONP的API发出请求的想法。JSONP是一个服务器和客户端都必须支持的协议:它要求服务器返回类似myFunction({"t":"continue"})的东西,以便将结果传递给本地函数。您不能只是偶然地“使用JSONP”。

第二类人引用了一个非常真实的漏洞,该漏洞被描述为允许跨站请求伪造,通过标记到使用JSONP的api(比如这个),允许一种形式的“JSON劫持”。这是通过更改Array/Object构造函数来实现的,该构造函数允许用户访问从服务器返回的信息,而不需要包装函数。

然而,在这种情况下这是不可能的:它工作的原因是一个裸数组(许多JSON api的一个可能结果,例如著名的Gmail示例)是一个有效的表达式语句,这对于裸对象是不正确的。

事实上,由JSON定义的对象的语法(在字段名周围包括引号,如本例所示)与块的语法冲突,因此不能在脚本的顶层使用。

js> {"t":"continue"}
typein:2: SyntaxError: invalid label:
typein:2: {"t":"continue"}
typein:2: ....^

为了让这个例子可以通过Object()构造函数的重映射来利用,它需要API将对象返回到一组括号内,使其成为有效的JavaScript(但不是有效的JSON)。

js> ({"t":"continue"})
[object Object]

现在,它可以是这个for(;;);前缀技巧只是“偶然”出现在这个例子中,并且实际上是由其他返回数组的Facebook内部api返回的;但在这种情况下,确实应该注意这一点,因为这将是for(;;);出现在这个特定代码片段中的“真正”原因。