《第三方JavaScript编程》——7.4 发布者漏洞

简介: 对于第一方Web应用而言,这些解决方案足够了,但是对于第三方应用加载iframe的情况呢?在这样的情况下,使用X-Frame-Options头或者框架杀手脚本都不可行,因为你需要在发布者的页面上加载这些内容。可以采取一些替代措施来减少点击劫持。

本节书摘来自异步社区《第三方JavaScript编程》一书中的第7章,第7.4节,作者:[美] Ben Vinegar Anton Kovalyov著,更多章节内容可以访问云栖社区“异步社区”公众号查看

7.4 发布者漏洞

虽然大多数时间你都在处理由于跨站脚本和跨站请求伪造引起的安全漏洞,但还有一些其他漏洞。攻击者利用这些漏洞可以直接入侵你的Web应用。我们也希望能够覆盖到这些方面,它们应该归纳在Web应用安全的主题内容中单独介绍。

本章的剩余部分,我们将把重点放在涉及发布者的漏洞上。与传统的Web应用不同,第三方应用涉及多方,其中之一的发布者也并不能完全信任。因为你的应用代码(至少一部分)是在他们的页面上执行的,他们可以有意或者无意地对你的应用进行攻击。在本节中,将简要介绍最常见的几种漏洞:发布者模拟、点击劫持和拒绝服务。

7.4.1 发布者模拟
发布者模拟指的是恶意的发布者使用另外一个发布者的名义注册你的应用。这样一来,攻击者就可以获取被攻击发布者的展示数据,而且攻击者所执行的操作都将错误的指向被攻击者。

我们来看一个例子。如果你还记得第1章,就应该对发布者的脚本引入片段还有印象,发布者需要在他们的Web页面中嵌入脚本片段以加载你的应用。假设已经让发布者在使用应用之前事先注册,而且提供给他们的引入脚本(如程序清单7.6所示)中需要通过配置变量指定发布者的账户名(或者其他可识别令牌)。

程序清单7.6 标识发布者的脚本引入片段

screenshot

如果其他发布者失误或者出于恶意将这段代码安装到了他们的网站上会怎样呢?有些初级的发布者,可能不会阅读你的文档,而是直接从另外一个网站复制粘贴代码就开始安装,因此其中的配置参数并不是针对自己网站的。这种情况下,Camera Stork服务会误以为在当前页面执行的操作都来自原发布者。

对于Camera Stork微件而言,现在这种情况并没有那么严重。可能发生的最坏情况是顶替页面对原发布者造成影响。但是对于其他的第三方应用而言,这种结果可能更糟。例如,如果顶替页面加载了一个针对其他发布者的统计脚本(类似Google Analytics),可能会对原发布者的数据造成破坏,从而对业务产生重创。另外一个可能的情况是:如果发布者在使用你的收费服务,根据带来的服务器负载进行计费,顶替页面可能会对其他发布者造成影响,产生额外的费用。根据我们的经验来看,发布者肯定不喜欢这样的事情发生。

通过REFERER头对发布者进行验证
对发布者进行最强的防御措施就是使用Referer HTTP头对请求部分进行校验。你可能对它并不熟悉,浏览器在每个HTTP请求中都会发送Referer头,并且包含请求来源的文档URL。也就是说,通过验证该文档是否是属于发布者的有效URL即可。如果Referer头包含的URL是一个未知的域名,就可以拒绝该请求并返回一个错误响应。

要这么做之前,需要发布者提交一组可信任的域名,这可以通过在你的网站上维护一个表格来实现(如图7.3所示)。你需要将这些值存入数据库,并将它们关联并指向发布者的账号。

screenshot

然后可以在服务端代码中执行信任域名的验证。假设初始的脚本文件(widget.js)是通过服务端应用提供的。当该资源被请求时,你需要查找发布者的受信任域名并验证Referer中的URL是否在这些值的范围内。程序清单7.7是一个用Python实现的简单的Flask服务端接口,演示了如何执行该验证。

程序清单7.7 使用Referer HTTP头信息对发布者的域名进行验证

screenshot

该例子中只检查了初始的脚本文件,但是最好对第三方应用发起的所有动态HTTP资源请求(如AJAX调用)都执行检查。此外,请注意该例子并不包括在iframe内的页面发起的资源请求,因为这些请求都来自你的域名而非发布者。

Referrer检查并非完美的解决方案。Referrer头是由浏览器提交的,因此可以通过其他工具进行欺骗,如浏览器扩展或者网络代理。然而,通过检查referrer值可以消除最明显的发布者欺骗,更不用说是失误了。

7.4.2 点击劫持
点击劫持,也被称为界面伪装攻击,是一种在网页中将恶意代码等隐藏在看似无害的内容(如按钮)之下,并诱使用户点击的手段。这样使访问者在不知不觉的情况下执行其他网站的操作,其中包括已经验证的会话信息。

让我们看一个例子。假设有一个摄影器材公司CheapCo,通过Camera Stork在线商店销售自己的产品。该设备公司非常渴望在你的网站上能够有更好的评论,他们原本可以通过改善自己的产品来实现,但他们选择了欺骗。

要实现这一点,CheapCo在他们的主页上通过一个隐藏的iframe加载Camera Stork网站。当有人访问他们的主页时,他们通过JavaScript将iframe定位在访问者的鼠标光标下方。当用户单击CheapCo网站上一个看起来正常的UI元素时,实际上单击的是iframe中的Web页面。CheapCo可以将iframe内容定位在一个特定的UI元素上,比如定位在对自己产品提交五星评论的按钮上。

1.X-FRAME-OPTIONS和“框架杀手”脚本
防止点击劫持最直接的办法就是避免Web页面通过iframe加载,有多种方式都可以实现。第一种是在内容请求的响应中返回一个特殊的HTTP头X-Frame-Options。X-Frame-Options可以指定这两个值中的任意一个:sameorigin,只允许同源的iframe展示该内容;deny,阻止任何iframe展示该内容。

下面是一个使用X-Frame-Options的HTTP响应的示例。

screenshot

X-Frame-Options之所以以X开头,是因为该头信息并非HTTP规范的一部分。它是2009年微软针对伪装攻击在IE8中推出的,并一直被其他浏览器厂商沿用。因为该HTTP头最近才被采用,因此旧的浏览器并不支持。

幸运的是,还有另外一种方式可以防止页面通过iframe加载:使用被称为“框架杀手”的JavaScript代码片段。这些代码使用JavaScript检测当前文档是否在框架内展示,如果是的话便会阻止页面加载。可以通过执行无限循环、隐藏内容,或者将文档重定向到一个空白页面来阻止目标页面的渲染。

并非所有的框架杀手脚本都一样,有些很容易受到框架杀手克星的影响:父页面加载的脚本使框架杀手失效(我们提供的例子恰好不受影响)。

下面是一个框架杀手的例子,如果不是顶层窗口则隐藏文档正文。

screenshot

2.点击劫持和第三方脚本
对于第一方Web应用而言,这些解决方案足够了,但是对于第三方应用加载iframe的情况呢?在这样的情况下,使用X-Frame-Options头或者框架杀手脚本都不可行,因为你需要在发布者的页面上加载这些内容。可以采取一些替代措施来减少点击劫持。

所有由单击触发的数据修改操作都需要确认。如果iframe中的操作可能会对数据进行修改,需要用户通过某种无法进行点击劫持的方式进行操作的确认。最常见的做法是在新窗口中打开一个确认对话框。另外,也可以使用在输入框里输入验证码的方式。

需要发布者进行注册。如果需要发布者注册后才能安装你的应用,即便发布者滥用也会有据可查,从而可以封掉这些投机取巧的发布者。

点击劫持很可怕,因为它是Web和HTML的一个漏洞,并不是应用或者软件的缺陷。最糟糕的情况就是所有网站都受到点击劫持的攻击,除非他们采取措施进行避免。对于一个不是通过iframe加载的普通内容而言,使用我们先前提到的X-Frame-Options头或者框架杀手脚本可以很容易避免。对于第三方应用而言,解决方案没有那么直接,但依旧是可控的。

7.4.3 拒绝服务
拒绝服务(DoS)攻击是试图让一个Web应用无法被用户访问。这种攻击最常见的方式就是让目标服务器的HTTP请求数达到饱和,从而不再响应正常的请求,因此导致Web应用无法正常访问。DoS攻击是令人崩溃的攻击形式中的一种,如果服务器遭到DoS攻击的话,目前还没有针对它们的通用解决方案。

拒绝服务攻击会影响所有的Web应用程序,但是第三方应用的危险更大。因为第三方应用可以通过其他Web页面访问,任何一个页面的流量激增都可能导致你的服务出现问题。甚至不需要向发布者发起攻击,需要做的只是像Justin Bieber的粉丝一样向你的微件发送超大量级的流量。

针对这种攻击的常见防御措施都围绕网络硬件,但是不在本书的讨论范围内。我们有一个建议:如果你的服务需要发布者进行注册,考虑为每个发布者创建一个唯一的子域名来提供文件(例如,publisher.camerastork.com)。这样一来,如果某个发布者对应用造成了大量的请求,你便可以封禁或者限制该发布者的请求。这有助于你的服务对于DoS攻击和随机流量的控制。

相关文章
|
9月前
|
JavaScript 前端开发 Java
JavaScript:编程宇宙的多面闪耀之星-揭秘 JavaScript,编程界的全能霸主如何炼成?-优雅草卓伊凡
JavaScript:编程宇宙的多面闪耀之星-揭秘 JavaScript,编程界的全能霸主如何炼成?-优雅草卓伊凡
297 24
JavaScript:编程宇宙的多面闪耀之星-揭秘 JavaScript,编程界的全能霸主如何炼成?-优雅草卓伊凡
|
JavaScript 前端开发 编译器
解锁JavaScript模块化编程新纪元:从CommonJS的基石到ES Modules的飞跃,探索代码组织的艺术与科学
【8月更文挑战第27天】随着Web应用复杂度的提升,JavaScript模块化编程变得至关重要,它能有效降低代码耦合度并提高项目可维护性及扩展性。从CommonJS到ES Modules,模块化标准经历了显著的发展。CommonJS最初专为服务器端设计,通过`require()`同步加载模块。而ES Modules作为官方标准,支持异步加载,更适合浏览器环境,并且能够进行静态分析以优化性能。这两种标准各有特色,但ES Modules凭借其更广泛的跨平台兼容性和现代语法逐渐成为主流。这一演进不仅标志着JavaScript模块化的成熟,也反映了整个JavaScript生态系统的不断完善。
187 3
|
存储 JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果+1
JavaScript编程实现tab选项卡切换的效果+1
|
10月前
|
JavaScript Ubuntu Linux
如何在阿里云的linux上搭建Node.js编程环境?
本指南介绍如何在阿里云Linux服务器(Ubuntu/CentOS)上搭建Node.js环境,包含两种安装方式:包管理器快速安装和NVM多版本管理。同时覆盖全局npm工具配置、应用部署示例(如Express服务)、PM2持久化运行、阿里云安全组设置及外部访问验证等步骤,助你完成开发与生产环境的搭建。
|
11月前
|
JavaScript 前端开发 IDE
【编程向导】Js与Ts差异详解:选择与权衡
JavaScript 一直是 Web 开发的基石,以其灵活性和动态性著称,但其松散类型可能导致大型项目中出现难以调试的错误。TypeScript 作为 JavaScript 的超集,通过引入静态类型系统,提供了更高的类型安全性和更好的工具支持,尤其适合大型团队和复杂项目。本文详细对比了 JavaScript 和 TypeScript 的优缺点,并提供了实际代码示例,帮助开发者根据项目需求选择合适的工具。
1541 2
|
前端开发 JavaScript 持续交付
提高JavaScript编程效率
提高JavaScript编程效率
168 3
|
自然语言处理 JavaScript 前端开发
JavaScript闭包:解锁编程潜能,释放你的创造力
【10月更文挑战第25天】本文深入探讨了JavaScript中的闭包,包括其基本概念、创建方法和实践应用。闭包允许函数访问其定义时的作用域链,常用于数据封装、函数柯里化和模块化编程。文章还提供了闭包的最佳实践,帮助读者更好地理解和使用这一强大特性。
116 2
|
JavaScript 前端开发 安全
JavaScript编程实现字符和字符串翻转
JavaScript编程实现字符和字符串翻转
|
JavaScript 前端开发 安全
揭秘TypeScript的魔力:它是如何华丽变身为JavaScript的超能英雄,让您的代码飞入全新的编程维度!
【8月更文挑战第22天】在Web开发领域,JavaScript是最主流的编程语言之一。但随着应用规模的增长,其类型安全和模块化的不足逐渐显现。为解决这些问题,微软推出了TypeScript,这是JavaScript的一个超集,通过添加静态类型检查来提升开发效率。TypeScript兼容所有JavaScript代码,并引入类型注解功能。
137 2
|
JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果
JavaScript编程实现tab选项卡切换的效果