如果你有在浏览器中查看过发给大公司 API 的请求,你可能会注意到,JSON 前面会有一些奇怪的 JavaScript:
为什么他们会用这几个字节来让 JSON 失效?
为了保护你的数据
如果没有这些字节,那么有可能任何网站都可以访问这些数据。
这个漏洞被称为JSON 劫持,也就是网站可以从这些 API 中提取 JSON 数据。
起源
在 JavaScript 1.5 及更早版本中,可以覆盖原始类型对象的构造函数,并使用括号调用覆盖的版本。
你可以这样:
这样就会弹出 alert!
使用以下脚本替换 var x,攻击者就可以阅读你的电子邮件!
这是通过在加载外部脚本之前覆盖 Array 构造函数来实现的。
数据提取
即使你重载了构造函数,仍然可以通过 this 来访问它。
这是一个代码片段,它将 alert 数组的所有数据:
在创建数组后,它们的值将被 alert 出来!
ECMAScript 4 提案中已修复了这个问题,我们现在无法再覆盖大多数原始类型的原型,例如 Object 和 Array。
尽管 ES4 从未发布,但主要浏览器在发现后很快就修复了这个漏洞。
在今天的 JavaScript 中,你仍然可以使用类似的行为,但它受限于你创建的变量,或者不使用括号创建的对象。
这是之前的一个修订版本:
这是一个使用 Array 关键字创建数组的版本:
如你所见,你添加到数组中的数据被记录下来,但功能保持不变!
修复方案并没有阻止使用 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 变量 =)。
使用这个脚本:
通过使用这个脚本中的一些受控数据和移位脚本,我们就可以再次渗透数据!
这是 Gareth 最后的 POC,摘自他的博文:
我不会深入解释这个方法,而是建议你阅读他的帖子,以获取更多信息。
预防
这是 OWASP 的官方建议:
使用 CSRF 保护,如果不存在安全标头或 csrf 令牌,就不返回数据,以防止被利用。 始终将 JSON 作为对象返回。 最后的解决方案很有趣。
在 Firefox 和 IE 中,这个是有效的:
但这样不行:它之所以无效是因为 Firefox 和 IE 认为括号是块语句的开头,而不是创建对象。
没有引号的符号{key:“value”}被视为标签,值被视为一个语句。
结论
虽然这些东西在今天可能是无效的,但我们永远不会知道明天将会带来什么新的错误,因此我们仍应尽力阻止 API 被利用。
如果我们把这个StackOverflow 答案视为理所当然,我们就很容易受到现代变体的影响,因此仍然可能被黑客入侵。
谷歌和 Facebook 在 JSON 数据之前添加无效的 JavaScript 或无限循环,OWASP 也列出了其他替代方案。
希望此文能帮到大家的同时,也听听大家的观点。欢迎留言讨论,加关注,分享你的高见!持续更新!
我本人邀约各大BATJ架构大牛共创Spring Cloud构建微服务架构的交流社区。 (群号:547793198)欢迎各路架构师、开发者,学习与交流使用Spring Cloud诸多强大组件的实战经验。
为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!
合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!
- To-陌霖Java架构
分享互联网最新文章 关注互联网最新发展