作者 | Antony Garand

译者 | 无明

如果你有在浏览器中查看过发给大公司 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!

使用以下脚本替换 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 为例的项目开发流程和工程师的绩效管理机制文章。

为什么Facebook的API以一个循环作为开头?相关推荐

  1. 你知道为什么Facebook的API以一个循环作为开头吗?

    如果你有在浏览器中查看过发给大公司API的请求,你可能会注意到,JSON前面会有一些奇怪的JavaScript: 为什么他们会用这几个字节来让JSON失效? 为了保护你的数据 如果没有这些字节,那么有 ...

  2. Facebook Auth API文档中没说清楚的事情 (2011-02-28更新)

    facebook api的文档写的不清不楚,很多都要靠自己碰壁之后猜测和琢磨问题的原因. 下面是几个文档中没说清楚的地方: The URL:Facebook api首先要使用app的一些id什么的,通 ...

  3. Facebook Graph API(2)--读取数据之picture

    Picture(图片) 在Graph API中提到图片不是照片的.此处的picture是指用户的头像,组,事件或应用和相册的图片.所以使用avatar也不是很好,毕竟不仅仅是用户头像. 1.概览 可以 ...

  4. Facebook数据被滥用?8个视频案例教你用好Facebook Graph API

    大数据文摘作品 编译:Aileen 过去的一个周末,社交网络Facebook因为用户数据被第三方API滥用帮助美国大选的事情上了热搜.直到现在,Facebook CEO小扎也没有发出任何官方回应,以及 ...

  5. 如何用青云客聊天bot的API创建一个聊天脚本

    导入***requests***和***json***库 import requests import json 创建一个***循环***,使其能一直运作下去 用文本***text***来替代聊天框 ...

  6. 实践操作:六步教你如何用开源框架Tensorflow对象检测API构建一个玩具检测器

    TensorFlow对象检测API是一个建立在TensorFlow之上的开源框架,可以轻松构建,训练和部署对象检测模型. 到目前为止,API的性能给我留下了深刻的印象.在这篇文章中,我将API的对象设 ...

  7. Java技巧:用一个循环语句输出九九乘法表!

    同学们在进行编程学习的时候,输出九九乘法表应该是基础中的基础了,只要我们使用几个循环语句即可轻松实现,那么你有没有想过如果只用一个循环语句应该怎么实现呢? 分析:注意是使用一个循环语句来写,增加了逻辑 ...

  8. 巨头垄断,Facebook直接封杀了一个国家!

    天下熙熙攘攘皆为利来! 1 封杀澳大利亚! 一夜之间,facebook把澳洲新闻"封杀了". 消息一出,瞬间登上了各大新闻媒体的头版头条 BBC ABC 卫报 想一下,自己天天使用 ...

  9. Java黑皮书课后题第9章:*9.5(使用GregorianCalendar类)Java API中有一个位于包java.util中的类GregorianCalendar

    Java黑皮书课后题第9章:*9.5(使用GregorianCalendar类)Java API中有一个位于包java.util中的类GregorianCalendar 题目 代码 题目 代码 imp ...

最新文章

  1. Java实现pdf和Excel的生成及数据动态插入、导出
  2. The 2014 ACM-ICPC Asia Mudanjiang Regional Contest(2014牡丹江区域赛)
  3. 新思科技助力IBM将AI计算性能提升1000倍
  4. LIVE555再学习 -- testRTSPClient 实例
  5. 牛客 - 牛半仙的妹子图(并查集+bitset/克鲁斯卡尔重构树+主席树)
  6. 用HttpClientFactory来实现简单的熔断降级
  7. P2580-于是他错误的点名开始了【Trie,字符串】
  8. Spring Boot文档阅读笔记-构建Restful风格的WebService客户端
  9. 神经网络隐藏层个数怎么确定_含有一个隐藏层的神经网络对平面数据分类python实现(吴恩达深度学习课程1第3周作业)...
  10. python解析json传入变量_Python 使用 docopt 解析json参数文件过程讲解
  11. 关于vim复制剪贴粘贴命令的总结-转
  12. sql server 2008 r2 序列号密钥实测可用20210906
  13. 网络运维工程师常见的面试题及需掌握的知识点
  14. CCSK认证,提升云安全专业技能,助力职业生涯发展
  15. 前端开发实习面试题(Vue篇)
  16. 计算机技术和教育,计算机技术和现代数学教育
  17. [spfa] Jzoj P4722 跳楼机
  18. 第十三周作业-必做3
  19. 计算机编程课程顺序_您可以在5月开始学习530项免费的在线编程和计算机科学课程
  20. 宇视摄像头安装水晶头防护套步骤

热门文章

  1. LeetCode 167. 两数之和 II - 输入有序数组 思考分析
  2. 计算机指令格式_计算机科学组织| 指令格式
  3. python中二进制整数_Python程序查找表示二进制整数的必要位数
  4. 面向对象(封装对象private关键字)
  5. 2019年的wps计算机考试题,2019年3月计算机一级WPS模拟题及答案(2.21)
  6. ropgadgets与ret2syscall技术原理
  7. HTML5 学习笔记
  8. linux操作系统信号捕捉函数之sigaction用法小结
  9. Linux系统编程---11(会话,守护进程,创建守护进程)
  10. CodeForces - 786BLegacy——线段树建图+最短路