什么是一个Ajax调用响应像“for(;;); {json data}“是什么意思?

可能重复:
为什么人们把代码如“扔1; 在json响应面前,“<dont be evil>”和“for(;;);”

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

这是呼吁和回应:

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

响应:

 for (;;);{"t":"continue"} 

Facebook在很多项目上都有很多开发人员在内部开展工作,而且有人犯了一个小错误是非常普遍的。 无论是简单而严肃的事物,都不能将数据插入到HTML或SQL模板中,或者使用eval (有时效率低下,可以说是不安全)或者JSON.parse (一个兼容但不是普遍实现的扩展)的复杂而微妙的东西一个“已知的”JSON解码器,重要的是要find方法来轻松实施这个开发人员的最佳实践。

为了面对这个挑战,Facebook最近一直在全力以赴地实施内部项目,以便优雅地实施这些最佳实践,而且说实话,对于这个特定案例来说,真正有意义的唯一解释就是:内部决定所有JSONparsing应该通过核心库中的一个实现,最好的方法是为每个API响应获取for(;;); 自动钉在前面。

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

提供的其他答案似乎都属于两类之一:

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

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

第二类的人引用了一个非常真实的漏洞,这个漏洞已经被描述为允许通过标签向使用JSONP(比如这个)的API的跨站点请求伪造,允许一种“JSON劫持”的forms。 这是通过更改Array / Object构造函数来完成的,该构造函数允许访问从服务器返回的信息,而不使用包装函数。

然而,在这种情况下根本就不可能:它的工作原理是,一个裸数组(例如着名的Gmail示例中的许多JSON API的一个可能结果)是一个有效的expression式语句,这不是真的裸露的物体。

事实上,由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(;;); 出现在这个特定的片段中。

我怀疑它存在的主要原因是控制。 它迫使你通过Ajax检索数据,而不是通过JSON-P或类似的(它使用script标记,因为for循环是无限的,所以会失败),从而确保相同的原始策略开始。哪些文档可以向API发出调用 – 具体而言,只有与该API调用具有相同来源的文档,或者Facebook专门授权通过CORS (支持CORS的浏览器)访问的文档。 所以你必须通过浏览器强制执行SOP的机制来请求数据,在反序列化数据之前,你必须知道前言并删除它。

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

那么for(;;); 是一个无限循环(如果需要,可以使用Chrome的JavaScript控制台在选项卡中运行该代码,然后观察任务pipe理器中的CPU使用情况,直到浏览器终止该选项卡)。

所以我怀疑,也许这是为了阻止任何试图使用eval或任何其他执行返回数据的技术来分析响应的人。

为了进一步解释,过去用JavaScript的eval()函数parsing一些JSON格式的数据是相当普遍的,比如:

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

然而,这被认为是不安全的,就像由于某种原因,你的JSON格式的数据包含可执行的JavaScript代码,而不是(或者除了)JSON格式的数据,那么代码将由eval()执行。 这意味着,如果您正在与不受信任的服务器交谈,或者某人泄露了受信任的服务器,则可以在您的页面上运行任意代码。

正因为如此,使用eval()来parsingJSON格式的数据通常会被忽视,而for(;;); Facebook中的JSON语句将阻止人们以这种方式parsing数据。 任何尝试的人都会得到无限循环。 所以基本上,就像Facebook正在试图强制人们使用API​​来处理,而不会让他们容易受到未来的劫持Facebook API作为媒介的攻击。

我有点晚了,TJ已经基本解决了这个谜,但是我想我会分享一个关于这个具有良好范例的特定主题的伟大论文,并提供对这个机制更深入的了解。

这些无限循环是针对“Javascript劫持”的一种对策,这是一种由Jeremiah Grossman发布的针对Gmail的攻击获得公众关注的攻击types。

这个想法和美丽一样简单:许多用户倾向于在Gmail或Facebook中永久login。 所以你要做的是build立一个网站,并在你的恶意网站的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对象的所有信息。

如承诺的那样,链接到报纸 。

这看起来像一个黑客,以防止CSRF攻击。 有特定于浏览器的方法可以挂钩到对象创build中,所以恶意网站可以首先使用它,然后执行以下操作:

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

如果在JSON之前没有无限循环,则会创build一个对象,因为JSON可以被eval() 编写为javascript,并且钩子将检测到它并嗅探对象成员。

现在,如果您从浏览器访问该网站,同时login到Facebook,它可以像您一样获取您的数据,然后通过例如AJAX或javascript发送回自己的服务器。