写点什么

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

  • 2018-11-26
  • 本文字数:2417 字

    阅读完需:约 8 分钟

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

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



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

为了保护你的数据

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


这个漏洞被称为JSON劫持,也就是网站可以从这些 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 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 在博客上介绍了这个漏洞的新变体,它仍然允许我们从 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 的官方建议


  • 使用 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 也列出了其他替代方案。

英文原文

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

活动推荐


12 月 7 日北京 ArchSummit 全球架构师峰会上,来自 Google、Netflix、BAT、滴滴、美团 等公司技术讲师齐聚一堂,共同分享“微服务、金融技术、前端黑科技、智能运维等相关经验与实践。详情点击 https://bj2018.archsummit.com/schedule


2018-11-26 14:433372
用户头像

发布了 731 篇内容, 共 447.1 次阅读, 收获喜欢 2001 次。

关注

评论 1 条评论

发布
暂无评论
发现更多内容

EasyRecovery破解版下载无需注册,easyrecovery数据恢复软件免费版激活码密钥

禁止废话

Easyrecovery破解 恢复软件 数据恢复软件 EasyRecovery16 破解软件

php中mcrypt_encrypt升级到openssl_encrypt

百度搜索:蓝易云

使用终端MobaXterm连接Centos

百度搜索:蓝易云

现在才投简历还来得及吗?

王磊

有人问我:过去一年用 AI 写了多少代码

阿里云云效

阿里云 云原生 通义灵码

VictoriaMetrics 中文教程(10)集群版介绍

秦晓辉

Victoriametrics VictoriaMetrics教程

技术解析丨加速高性能计算,RDMA 在分布式存储中的性能优化实践

焱融科技

AI 高性能存储 RDMA MLPerf

如何在mac上玩使命召唤手游?苹果电脑好玩的第一人称射击游戏推荐

禁止废话

游戏 兼容性 苹果电脑 使命召唤5 CrossOver Mac下载

技术分享 | 大语言模型增强灰盒模糊测试技术探索

云起无垠

高技能员工短缺对企业发展的影响

爱吃小舅的鱼

高技能员工

RabbitMQ的Overview Totals是空

codists

RabbitMQ 编程人 codists

有人问我:过去一年用 AI 写了多少代码

阿里巴巴云原生

阿里云 云原生 通义灵码

Docker启动失败报错Failed to start Docker Application Container Engine解决方案

百度搜索:蓝易云

豆包MarsCode AI 红人创造营启动,参与活动赢万元现金激励!

豆包MarsCode

企业选项目成本管理系统时应看哪些?9款工具介绍

爱吃小舅的鱼

项目成本管理系统

Google 类 Computer Use 项目:贾维斯计划;字节 PersonaTalk 视频配音框架能保持口型与风格同步

声网

《使用Gin框架构建分布式应用》阅读笔记:p234-p250

codists

golang gin 编程人 codists

MyBatis获取参数值的两种方式#{}和${} 以及 获取参数值的各种情况

百度搜索:蓝易云

实时监控商品信息api接口,加速迭代优化:助力商家产品持续精进之路

代码忍者

API 接口 pinduoduo API

寻找免费项目管理工具?2024年8款选择

爱吃小舅的鱼

项目管理工具

03MyBatis-Plus中的常用注解

百度搜索:蓝易云

Pixabay API集成:免费获取图片和视频的步骤详解

幂简集成

API 图片

提升团队动力和士气的实用方法

爱吃小舅的鱼

团队动力和士气

如何选择免费项目管理软件?8款值得试试

爱吃小舅的鱼

项目管理软件

OceanBase数据库结合ETLCloud快速实现数据集成

RestCloud

数据库 分布式存储 ETL 数据集成 oceanbase

华为校园鸿蒙公开课走进清华大学

最新动态

OPPO式出海,为全球化讲一个“落地生根”的故事

脑极体

AI

鸿蒙开发案例:巧算24点

zhongcx

新员工培训助力融入团队的实用方法

爱吃小舅的鱼

新员工培训

AI安全智能体,重塑网络安全新范式

云起无垠

10分钟搞定软件架构决策

俞凡

架构

你知道为什么Facebook的API以一个循环作为开头吗?_编程语言_Antony Garand_InfoQ精选文章