《第三方JavaScript编程》——7.2 跨站脚本

简介: 对代码进行潜在的XSS安全漏洞检查似乎很令人沮丧,但最好不要忘记和低估XSS攻击的影响。不过,相比失去发布者和用户的信任而言,花费几个小时的时间进行安全检查是很值得的。在下一节中,我们将谈论另外一种占比很大的攻击方式,一个名为跨站请求伪造的漏洞,利用该漏洞,攻击者可以使用用户的身份悄悄地发送恶意请求。

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

7.2 跨站脚本

或许Web应用开发者都会遇到的一个尴尬问题,就是跨站脚本(俗称XSS)。许多不同的成功攻击案例都是利用了这个安全漏洞,小到将Facebook装扮成MySpace风格的恶作剧[2],大到像金融诈骗这样的严重后果。攻击者利用跨站脚本漏洞可以将自己的代码注入到用户浏览的Web页面中。迄今为止,这是包括第三方JavaScript应用在内的现代Web应用最常见的攻击形式。根据赛门铁克(Symantec)2007年的互联网安全威胁报告[3],在其中所描述所有安全漏洞中,XSS占到了80%的比例。

在本节中,我们会介绍什么是XSS攻击,并解释其工作原理,同时会告诉你如何在自己的应用中防御这种攻击。

7.2.1 XSS攻击
攻击者是如何将他们的代码注入到你的Web应用中的呢?通常情况下,是因为你的应用没有对输入的内容做足够的过滤。例如,假设Camera Stork网站(http://camerastork.com)没有对用户提交的评论内容做过滤便展示在主页上,因为内容是输出到一个HTML页面上,所以攻击者只需要将它们自己的HTML代码嵌入在提交的内容中,便可以将其输出到页面上。例如,如果攻击者的评论内容中包含下述代码,所有浏览Camera Stork主页的用户都将会看到一个无聊的弹出提示“Hello, World”。
screenshot
这种“Hello, World”的提示消息并不可怕,但这种漏洞可以被多种不同的方式利用并攻击你的用户或者访问者。例如,利用该漏洞,攻击者可以注入JavaScript代码,从而获取用户cookies中的会话令牌,如图7.1所示。正如你已经了解的,攻击者通过劫持用户的会话可以在受影响的服务中访问用户存储的数据,并可以执行恶意的操作。
screenshot
通过代码注入访问用户的cookies很简单,攻击者只需要通过查询第6章中介绍的document.cookies属性即可。但只是访问用户的cookies还不够,攻击者还需要获得这些cookies。为了实现这一点,攻击者需要在浏览器中通过一个HTTP请求将用户的cookies发送到自己的服务器。有一种方式可以做到:在DOM中追加一个新的脚本元素,并发起一个兼容所有浏览器的CORS XmlHttpRequest。但最简单最便捷的方式是使用浏览器中自带的JavaScript Image对象。
下面是攻击者注入到一个商品评论内容中的代码片段示例。
screenshot
这段代码是什么作用?每次加载评论时,它都会创建一个新的Image DOM元素,但不会将其添加到文档中,因此用户并不可见。即便不可见,浏览器依旧会发起HTTP请求下载对应的图片文件[4],这正是攻击者所需要的。这里src中的URL(attacker.example.com)并不是一个图片地址,而是攻击者用来收集cookies信息的服务端地址。而cookie数据通过目标URL的查询字符串进行传递。当这段代码被插入到Camera Stork网站后,访问者就会发起该请求,攻击者只需要监控日志并存储接收到的会话信息即可。

通常情况下,会话标识符并不隶属于某台特定计算机,因此攻击者唯一需要做的就是将获得的标识符作为自己的cookie数据。之后,攻击者便可以成为已验证用户并使用用户拥有的任何权限。

你可能也已经注意到了,这种攻击实际上用户是感知不到的,不像之前“Hello, World”的例子,这种情况下用户的体验同普通的页面没有什么不同。也就是说,用户在意识到他们的会话被窃取之前不太可能会主动报告这个问题,一旦用户自己意识到就太晚了,攻击者就能够通过他们的身份登录,访问他们的私人数据,并且可以直接执行未经授权的操作。黑客的真正目标并不是执行任意脚本,他们的真正目的是获取用户的会话。
7.2.2 CSS中的XSS漏洞
另一个XSS攻击的成功案例是攻击微件的CSS自定义样式。有时候,你希望微件能够足够定制化,因此会允许发布者指定微件的自定义样式。即便是通过iframe的形式展现的微件,也可以使用我们在第3章中介绍的自适应的HTML和CSS技术来实现。

请看程序清单7.1。在这个例子中,发布者除了将Camera Stork微件嵌入在他们的Web页面中之外,还使用全局变量指定了两个自定义颜色:stork_bg_color包含背景颜色,stork_bg_color包含前景(文字)颜色。

程序清单7.1 发布者使用全局配置变量来自定义颜色
screenshot
假设这个版本的Camera Stork微件是通过外部iframe的形式引入。程序清单7.2中的代码是生成的iframe中的HTML代码。它从iframe的URL查询字符串中解析获取传递的自定义颜色参数[5],并将最终生成后的样式插入到页面中。

程序清单7.2 注入发布者指定颜色设置的漏洞代码
screenshot
现在假设攻击者在他们的网站中安装了你的微件,并利用背景色设置,将如下代码赋值给stork_bg_color变量。
screenshot

这段代码不仅会设置CSS的背景色,还会恶意声明一个额外的CSS表达式。该表达式执行的是一段似曾相识的JavaScript代码,使用隐藏的Image对象将用户当前的会话标识符发送到攻击者的网站。现在,攻击者只需要将你的用户吸引到一个包含微件的页面就完成了攻击[6],攻击者便会接收到用户的cookie内容,从而窃取他们的会话。因为攻击代码是在你的域名下的iframe页面中执行的,因此恶意代码可以访问到你的域名的所有cookie。

需要谨防不信任的发布者,但不是每个安装了应用的人都会这么做,因为他们确实有实际使用的需求。而有些人安装你的应用是为了作为攻击的切入点,在本章后面你会了解到,这种攻击不仅只是针对你的用户,也可能针对其他的发布者。与普通用户的情况相同,应当确保来自发布者的输入值没有潜在的危险。

该CSS表达式的例子只适用于Internet Explorer浏览器,但对于一个有经验的攻击者而言,它是众多可用的XSS切入点之一。在程序清单7.2中,攻击者也可以直接闭合< style >标签并注入代码到iframe的< head >部分。其他漏洞利用方式包括:将javascript:< expr >作为图片的URL,在Firefox的refresh meta标签中嵌入JavaScript异常等。
现在你已经了解了应用被攻击的不同方式,接着我们会针对XSS攻击介绍一些有用的保护方法。

7.2.3 防止XSS对应用的攻击
所有的Web应用程序,尤其是第三方微件,都有许多不可信的数据来源,这些入口都可能成为XSS攻击的切入点。不幸的是,避免这类攻击的唯一方法就是对所有的外部数据进行仔细的过滤,无论这些数据是来自最终用户还是发布者。

一般情况下,在将任何外部数据插入到DOM(包括发布者和你自己)中之前,应该对其中包含的任意字符进行转义如下。

  • 将<转换为&lt。
  • 将>转换为&gt。
  • 将&转换为&amp。
  • 将"转换为&quot。
  • 将 ' 转换为。

将这些字符转换为相应的HTML实体,可以确保攻击者无法在消息中插入< script >标签,攻击者也无法在微件中执行任意代码。这种方式称之为“数据消毒”,在接收一些不能确保安全的数据时经常用到。这种情况下,对数据进行处理并且对所有有潜在威胁的部分(如HTML标签)进行删除或者转义。有效地进行“数据消毒”是一个很难解决的问题,特别是当你希望用户能够使用一些HTML元素的时候,而这些元素并不会导致漏洞。有许多种“数据消毒”的方式,但最行之有效的是对数据进行过滤以确保输入源的安全性。

1.拒绝已知的错误
让我们假设有一个简单的用于评论微件的所见即所得(WYSIWYG)编辑器。你希望用户能够使用像这样简单的标签,但是不希望有人通过插入< script >标签来劫持其他用户的会话。我们想到的第一件事就是删除所有的< script >标签,这是一种简单粗暴的解决方案,或者套用美国著名记者Henry Louis Mencken的一句话:“这是一种简洁、合理并且错误的解决方案”。攻击者只需要绕过过滤器的过滤规则即可,比如将< script >标签替换为< scr< script >ipt >。由于过滤器会将< script >替换为空字符串,结果不小心便产生了另外一个< script >元素。如果你使用多个过滤器对用户的输入进行多次验证,攻击者也可能利用这些步骤的顺序来绕过它们。

我们刚刚描述的方式通常称之为“拒绝已知的威胁(reject known bad)”。你需要有某种黑名单,其中包含一系列对微件有潜在威胁的攻击模式,并且对每个输入都进行黑名单的匹配检查。这种方式有时是很有必要的,例如,当输入是一个格式不受限制的文本域,像产品评论或者邮件正文,它可能是防御应用遭受XSS攻击最安全的方式。但通过Web传输的数据可以通过许多种方式编码,因此有些情况极有可能从黑名单中漏掉。

2.接受已知正确的内容
一种更好的方式是尽可能接受已知安全的数据。同之前的做法正好相反,这种做法需要维护一个安全值的白名单,而不是像之前维护危险值的黑名单。例如,如果你从发布者页面将产品标识传递给iframe微件,取代之前对输入进行“数据消毒”的方式是验证输入数值是否是数字。
screenshot
还有另外一个不错的方法,就是尝试将输入数据限制为已知的安全值,从而缩小输入的范围。以程序清单7.2中的CSS跨站脚本攻击为例,代码中的值预期为有效的十六进制颜色值,但是攻击者提供的是一个CSS表达式,从而获取用户(碰巧使用了早期版本Internet Explorer的用户)的会话。程序清单7.3展示了通过缩小发布者页面提供的数据范围来防止这种攻击。

程序清单7.3 通过缩小输入数据的范围防止XSS攻击
screenshot
正如程序清单7.3所示,你甚至不需要再对代码进行“消毒”,因为在数据无效的情况下,攻击者最多无法看到正确的背景色。但是毕竟是攻击者,所以这种情况完全可以接受。

对代码进行潜在的XSS安全漏洞检查似乎很令人沮丧,但最好不要忘记和低估XSS攻击的影响。不过,相比失去发布者和用户的信任而言,花费几个小时的时间进行安全检查是很值得的。在下一节中,我们将谈论另外一种占比很大的攻击方式,一个名为跨站请求伪造的漏洞,利用该漏洞,攻击者可以使用用户的身份悄悄地发送恶意请求。

相关文章
|
2月前
|
JavaScript 前端开发 测试技术
使用Selenium执行JavaScript脚本:探索Web自动化的新领域
本文介绍了如何在Selenium中使用JavaScript解决自动化测试中的复杂问题。Selenium的`execute_script`函数用于同步执行JS,例如滑动页面、操作时间控件等。在滑动操作示例中,通过JS将页面滚动到底部,点击下一页并获取页面信息。对于只读时间控件,利用JS去除readonly属性并设置新日期。使用JS扩展了Selenium的功能,提高了测试效率和精准度,适用于各种自动化测试场景。
53 1
|
2月前
|
前端开发 JavaScript 开发者
探索JavaScript ES6的八种常见使用技巧:开启现代编程之旅
探索JavaScript ES6的八种常见使用技巧:开启现代编程之旅
|
2月前
|
JavaScript 前端开发 Java
liteflow规则引擎 执行Javascript脚本
liteflow规则引擎 执行Javascript脚本
50 1
|
2月前
|
JavaScript 前端开发 开发者
编程笔记 html5&css&js 071 JavaScript Symbol 数据类型
编程笔记 html5&css&js 071 JavaScript Symbol 数据类型
|
1天前
|
JavaScript 前端开发 测试技术
在JS编程中常见的编程“套路”或习惯汇总
在当前技术圈快速迭代发展的时代,JavaScript是一种广泛应用于Web开发和移动应用开发的脚本语言,其重要性愈发凸显,尤其是随着技术的不断发展和应用场景的不断扩展,JS编程已经成为了许多开发者必备的技能之一。但是仅仅掌握JS语法和基本知识并不足够,为了写出高质量、可靠性和可维护性的代码,开发者需要掌握一些常见的编程"套路"或习惯,这些套路和习惯能够帮助开发者更好地组织和管理代码,提高开发效率,并减少潜在的错误和问题。在JS编程开发中,有一些常见的编程“套路”或习惯,可以帮助开发者编写高效、可维护且易于理解的代码。让我们来看看其中一些常见的编程“套路”或习惯。那么本文就来分享探讨在JS编程中
20 6
在JS编程中常见的编程“套路”或习惯汇总
|
4天前
|
JavaScript 前端开发 C语言
JavaScript编程语法练习
本篇文章是对于javaScript中if ,switch,while ,do-while,,for语法的作业练习.对于我来说也是对自己知识掌握的一种检验.是对js的基础语法进行的一次练习,通过有趣的示例进行练习,使得对于代码能够增加印象,对于知识的掌握更加透彻.
|
18天前
|
XML 存储 JavaScript
JavaScript的基本语法是编程的基础
【4月更文挑战第20天】JavaScript的基本语法是编程的基础
17 5
|
27天前
|
Web App开发 缓存 JavaScript
|
2月前
|
存储 JavaScript 编译器
这款国产中文编程火了!通过文言文编译生成Python、JS、Ruby代码!
这款国产中文编程火了!通过文言文编译生成Python、JS、Ruby代码!
|
2月前
|
JSON JavaScript 前端开发
JS逆向快速定位关键点之9大通用hook脚本
JS逆向快速定位关键点之9大通用hook脚本