为什么google会预先准备好while(1);的(私有)json响应?
例如,在Google日历中打开和关闭日历时,有一个响应:
1 2 3 4
| while(1);[['u',[['smsSentFlag','false'],['hideInvitations','false'],
['remindOnRespondedEventsOnly','true'],
['hideInvitations_remindOnRespondedEventsOnly','false_true'],
['Calendar ID stripped for privacy','false'],['smsVerifiedFlag','true']]]] |
我想这是为了防止人们在上面做eval(),但是你真正要做的就是更换while,然后你就可以被设置了。我假设eval预防是为了确保人们编写安全的JSON解析代码。
我也在其他一些地方看到过,但是在谷歌(邮件、日历、联系人等)中更是如此。奇怪的是,谷歌文档从&&&START&&&开始,而谷歌联系人似乎从while(1); &&&START&&&开始。
这是怎么回事?
- 我相信你的第一印象是正确的。如果您开始寻找代码,并尝试根据源代码调整输入流,那么您将重新考虑并以安全的方式(并且由于Google的操作,更简单)进行操作。
- 可能还有一个后续问题:为什么Google现在要预先发送)]}'而不是while(1);?答案是一样的吗?
- 将阻止eval,但不能使用无限循环。
- 这个)]}'还可以保存字节,就像facebook使用for(;;);保存一个字节一样。
- 为防止JSON的披露,即JSON hijacking。
它可以防止JSON劫持,这是一个主要的JSON安全问题,自2011年以来,所有主要浏览器都已通过EcmaScript 5正式解决了这一问题。
人为的例子:假设Google有一个类似于mail.google.com/json?action=inbox的URL,它以JSON格式返回收件箱的前50条消息。其他域上的邪恶网站由于相同的源站策略而无法发出Ajax请求来获取这些数据,但它们可以通过标记包含URL。使用cookie访问URL,通过重写全局数组构造函数或访问器方法,可以在设置对象(数组或哈希)属性时调用方法,从而允许它们读取JSON内容。
while(1);或&&&BLAH&&&防止了这种情况:mail.google.com上的Ajax请求将具有对文本内容的完全访问权,并且可以将其剥离。但是,标记插入会盲目地执行javascript而不进行任何处理,从而导致无限循环或语法错误。
这并不能解决跨站点请求伪造的问题。
- 为什么获取此数据的请求不需要CSRF令牌?
- 返回一个包含数组的对象,而不是直接返回数组,是否也能解决这个问题?
- for(;;);做同样的工作吗?我在Facebook的Ajax响应中看到了这一点。
- @Pedrofelix不,这并不能解决问题,因为帖子中提到的攻击仍然可以执行。重写访问器方法以检索信息。
- @ JakubP。以谷歌的规模存储和维护CSRF令牌需要大量的基础设施和成本。
- @ JakubP。反CSRF令牌会干扰缓存,并且需要一定数量的加密评估服务器端。在谷歌的规模上,这需要大量的CPU。这种方式将它卸载到客户机。
- salesforce.com还使用while(1);预处理Ajax响应。
- @Jakupp为什么要在不需要基础设施、复杂性或实现的简单解决方案中使用CSRF令牌?
- 为什么要无限循环而不是简单的语法错误(保存字符)?你可以用)启动文件。
- 那么,你是说,当谷歌从其合法的Ajax请求中得到返回的数据响应时,他们会找到/替换或使用regex删除while(1);?
- 我不喜欢耍花招。这不是总是通过返回一个对象来解决的吗?
- @不,请参见有关重写全局数组构造函数的链接;对全局对象构造函数也可以这样做。
- 这个解决方案似乎有点过于复杂……难道你不能通过不返回HTTP GET请求上的JSON来防止攻击吗?
- 这是为了防止XSSI而不是CSRF。
- 如果生成JSON的脚本需要一个POST而不是GET请求,那么这是否完全减轻了这种风险??
- 从安全的角度来看,开放块注释是否也可以工作?(即"/*")
- @Dave1010错误仍然不够好。您仍然可以读取脚本标记的内容。同时(1)将挂断译员。
- @我不相信。不能通过脚本标记加载对象文本。这就是为什么wcf和odata将数组包装在具有"d"属性的对象中。
- @布什利:不,因为这是一个语法错误(语句级的{启动一个块)。
- @RJH:因为顶级对象文字是语法错误;返回对象而不是数组也会解决这个问题吗?
- @0xsina无法读取脚本标记的内容
- 什么会阻止我刮除JSON响应,然后用脚本语言除去while();语句,然后再除去eval()语句?我通常不需要登录到一个站点来访问这种敏感的JSON吗?只是想知道。
- @Silkfire跨域XHR不起作用的事实。脚本标记纯粹用于发送请求。所以会发生的是,加载响应然后运行,但是您不能控制其中的任何内容。
- @我的意思是,我可以在浏览器中输入URL,然后看到结果,即JSON是完全可读的?
- @SilkFire如果您有一个gmail的登录cookie,您将看到完整的JSON以了解您的详细信息(联系人列表等)。但这里的诀窍是,你在受害者的客户机上运行页面。因此,脚本标记发送一个请求,用受害者的cookies获取其src属性中的任何内容。因此,响应将包含受害者的数据,但是您的脚本处于控制之中,因此您可以用它做任何您想做的事情。
- @Silkfire通过将数组构造函数替换为将数据发送到邪恶服务器的构造函数来获取数据。因为当(1)阻止eval到达数组时,hack不起作用,因为数组构造函数从不触发。来自下面的答案ejohn.org/blog/re-securing-json
- @Arnaud576875-我知道你在说什么,但是你可以阅读脚本标签的内容(这是大多数客户端模板化的方式,例如)。只是您只能读取脚本标记的本地内容,而不能读取远程内容(fiddle)。
- @Matthew我们讨论的是跨域数据公开;显然,如果脚本是本地的,那么这里讨论的所有内容都不相关。
- 对于POST请求,仍需要CSRF保护。
- 在我看来,更好的方法是让服务器仅在设置了正确的头之后发送JSON。在Ajax调用中可以这样做,但脚本标记不能这样做。这样,敏感信息就永远不会被发送,而且您不必依赖浏览器端的安全性。
- @ MCV。标题看起来确实是一个好的标准解决方案。但为什么"更好"?也许在谷歌的规模上,如果可能的话,甚至处理邮件头也是可以避免的。
- 我认为最好不要发送敏感数据,而不是在信任浏览器无法处理的情况下发送数据。尽管在这种情况下,对浏览器的信任是不可避免的。显然,在一个完全不安全的浏览器中,没有什么是安全的。
- @MCV如果内容被缓存到某个地方,那将是无效的。
- 埃多克斯1〔4〕怎么样?
- @valipour看到你警报的人不是黑客。
- 这在今天(2015年)是否仍然相关?我在这篇文章中找到的所有关于火狐3和Chrome2的博客文章,以及JS规范的漏洞将会/可能会改变。这种安全性在2015年的浏览器中仍然存在吗?
- @如果你在Chrome上试用function Array() { console.log('security breach!'); },你会得到答案的。
- 这也适用于标签,这些标签不属于同一来源政策。
- @MCV您仍然依赖于浏览器的安全性,实际上没有办法解决这个问题——最终,用户使用浏览器访问他们的数据:)例如,您的浏览器可能允许任意的Ajax请求,在这种情况下,您甚至不需要这个技巧。只要您继续使用cookie进行身份验证,就必须完全依赖浏览器以安全的方式处理cookie—这包括域隔离和相同的源站策略。不是服务器阻止了跨站点的Ajax请求——如果没有浏览器,它怎么知道它是跨站点的?
- @朱利安国王-是的,他们的优势是每个请求节省1字节!
- @MVC你忘了比例。对于一个小网站来说,这可能不会有什么不同。当你处理像谷歌这样的数百万请求时,你必须考虑将工作卸载到客户机上以节省成本。必须在服务器端评估头
- 如果有人将该URL加载到iframe中,然后复制iframe的内容呢????????????????
- @Ravinderpayal他们不能。XSS保护不允许JS从不同的域读取iframe的内容。
- 这也意味着旧的Comet技术应该在同一个领域中实现……好吧,就这样……浏览器是否也区分子域?
- 这还相关吗?因为这个问题依赖于这个漏洞,很久以前就已经解决了,就像我所评论的答案一样。
- 所以如果我访问一个被破坏的页面,谷歌会耗尽我的电池。我想这是必要的,因为JavaScript中缺少同步sleep()函数。即,当(1)睡眠时(number.max_safe_integer)
- @不,它会运行一段时间,并抛出一个无响应的脚本警报。由用户决定是否停止。
- 现在我很好奇一个img元素如何以及是否可以用于此目的:例如,是否可以将json调用作为img插入,然后呢?阅读其内容。@埃里克提到了同时保护自己免受IMG的伤害??
- @jo&227;oantunes查找数组构造函数劫持。
- @是的,这只是写循环的另一种方式。不确定哪一个更好,尽管我认为(1)更多地用于可读性方面。
它防止通过JSON劫持泄露响应。
理论上,HTTP响应的内容受同一源策略的保护:来自一个域的页面无法从另一个域的页面获取任何信息(除非明确允许)。
攻击者可以代表您请求其他域上的页面,例如,使用或标记,但无法获取有关结果的任何信息(头、内容)。
因此,如果您访问攻击者的页面,它就无法从gmail.com读取您的电子邮件。
除了使用脚本标记请求JSON内容时,JSON在攻击者控制的环境中作为javascript执行。如果攻击者可以替换数组或对象构造函数或对象构造过程中使用的其他方法,JSON中的任何内容都将通过攻击者的代码进行传递,并被公开。
注意,这发生在JSON作为JavaScript执行时,而不是在解析时。
有多种对策:
确保JSON从不执行
通过在JSON数据之前放置一条while(1);语句,Google确保JSON数据永远不会作为javascript执行。
只有合法的页面才能真正获取整个内容,去掉while(1);,并将其余部分解析为json。
例如,在Facebook上也看到过类似于for(;;);的东西,结果也一样。
确保JSON不是有效的javascript
同样,在JSON之前添加无效的令牌,比如&&&START&&&,可以确保它永远不会被执行。
始终返回外部有对象的JSON
这是OWASP推荐的防止JSON劫持的方法,并且入侵性较小。
与前面的反措施类似,它确保JSON永远不会作为JavaScript执行。
有效的JSON对象未被任何内容所包围时,在javascript中无效:
[cc lang="javascript"]eval('{"foo":"bar
- OWASP推荐很有趣,因为它很简单。有人知道谷歌的方法更安全的原因吗?
- 我相信它在任何方面都不安全。在这里提供owasp似乎是+1的充分理由。
- 2014年的哪些浏览器允许您替换数组或对象构造函数?
- OWASP方法如何防止人们简单地使用JSONP方法获取数据?在我看来,google的方法通过不提供有效的json对象来防止这种情况,而owasp方法则表示使用有效的json对象,因此它不能作为javascript执行。
- JSONP要求服务器参与,由于JSONP的目的是允许跨域访问所讨论的数据,我认为服务器不关心阻止跨域访问该数据。
- 我想如果您必须使用JSONP,您可以尝试以某种巧妙(可能不安全)的方式使用CSRF令牌。
- 值得注意的是,为什么返回对象文本会使script标记或eval函数失败。大括号{}可以解释为代码块或对象文本,而javascript本身更喜欢前者。当然,作为一个代码块,它是无效的。根据这种逻辑,我看不到未来浏览器行为中任何可预见的变化。
- 我很惊讶他们没有使用删除第一个字符的方法:"a":1,"b":2}或1,2,3]不是有效的JS,并且永远不会是,根据最后一个字符添加正确的字符非常容易。谷歌和Facebook将节省数百万TB的带宽。
- 错误的代码还不够,因为攻击者还可以劫持浏览器的脚本错误处理程序(window.onerror),我不确定onerror的行为是否有语法错误。我想谷歌也不确定。
- 如果它是一个需要授权的API,那么另一个度量(无论如何都应该使用)是CSRF令牌。如果没有有效的CSRF令牌,服务器可以直接拒绝攻击者的请求。
- "一个有效的JSON对象,当没有被任何东西包围时,在javascript中是无效的:"--除了一个空对象({})的小情况,它也是一个有效的空块。如果知道对象是空的,那么它本身可能是有价值的信息,这可能是可利用的。
- 媒体API始终返回一个非空对象,但仍带有前缀。例:])}while(1);</x>{'success': true, 'payload': {}}有人知道原因吗?
- @KMMBVNR:主要是出于同样的原因,这是一个偏执的安全措施:他们这样做只是为了防止返回一个对象不足以防止JSON劫持一些过去的未来浏览器版本,或一些尚未发现的上下文。
这是为了确保其他一些网站不能做一些卑鄙的把戏来窃取你的数据。例如,通过替换数组构造函数,然后通过标记包含此JSON URL,恶意的第三方站点可以从JSON响应中窃取数据。通过将while(1);放在开头,脚本将挂起。
另一方面,使用XHR和单独的JSON解析器的同一个站点请求很容易忽略while(1);前缀。
- 我想XHR只能通过身份验证颁发给同一个域服务器。"其他站点"如何拦截响应?你能提供更多关于"其他网站"如何窃取我们数据的细节吗?
- 从技术上讲,如果您有前缀,"普通"JSON解析器应该给出错误。
- 攻击者只会使用一个普通的旧元素,而不是xhr。
- @Matthew,当然可以,但是在将数据传递给JSON解析器之前可以删除它。你不能用标签
- @当然了。我只是学究,想确保没有人对JSON感到困惑。我更喜欢新措辞:)
- 谢谢-我们有合适的术语来描述这种安全措施吗?我见过Facebook在他们的电话中使用for(;;);。我想这也是同样的机制,但是更短的选择?
- 有没有这样的例子?替换数组构造函数会再次被引用,但这是一个修复了很久的错误。我不理解如何访问通过脚本标记接收的数据。我希望看到一个在最近的浏览器中工作的虚拟实现。
- 在JohnResig的博客中,他提到了非常老的浏览器。有人知道在当今的现代浏览器中,这种漏洞是否仍然是一个问题?
- @乔尔丁,不,不是。请参阅stackoverflow.com/questions/16289894/&hellip;。
- 如果是为了防止JSON劫持,那么/*[...]*/也会起作用吗?
这将使第三方很难将JSON响应插入带有标记的HTML文档中。请记住,标签不受同一来源政策的限制。
- 这只是半个答案。如果不是为了覆盖Object和Array构造函数,执行有效的JSON响应,就好像它是javascript一样,在任何情况下都是完全无害的。是的,如果标记针对的话,while(1);会阻止响应以javascript的形式执行,但您的回答并不能解释为什么需要这样做。
- 但它将如何防止伊夫拉姆斯
- @Ravinderpayal 标签并不免除同一原产地政策的限制…
- 脚本标记从不从同一源策略中免除。你能帮我弄清楚吗?
注:截至2019年,导致本问题中讨论的预防措施的许多旧漏洞在现代浏览器中不再是问题。我将把下面的答案作为一个历史性的好奇心,但实际上整个主题自2010年以来发生了根本性的变化(!!)当被问到这一点时。
它防止将它用作简单标记的目标。(好吧,这并不能阻止它,但它会让人不快。)这样,坏人就不能把脚本标签放在他们自己的站点上,依靠一个活动会话来获取你的内容。
编辑&mdash;注意注释(和其他答案)。这个问题与被颠覆的内置设施有关,特别是Object和Array的建设者。这些可以修改,否则无害的JSON在解析时可能触发攻击者代码。
- 这只是半个答案。如果不是为了覆盖Object和Array构造函数,执行有效的JSON响应,就好像它是javascript一样,在任何情况下都是完全无害的。是的,如果标记针对的话,while(1);会阻止响应以javascript的形式执行,但您的回答并不能解释为什么需要这样做。
Since the tag不受同一来源策略的限制,这在Web世界中是安全必要的,while(1)添加到JSON响应时,可防止在tag中误用它。