使用脚本隔离技术对抗XSS攻击

简介: 本文讲的是使用脚本隔离技术对抗XSS攻击,在圣诞节之后,我与@mikewest和@fgrx讨论了关于使用“隔离”的概念(将会在下面解释)作为对抗XSS漏洞攻击的安全缓解措施。这看起来似乎是一个很有趣的问题,因此,我花了一些时间研究了一下。
本文讲的是 使用脚本隔离技术对抗XSS攻击

概述

在圣诞节之后,我与@mikewest和@fgrx讨论了关于使用“隔离”的概念(将会在下面解释)作为对抗XSS漏洞攻击的安全缓解措施。这看起来似乎是一个很有趣的问题,因此,我花了一些时间研究了一下。

下面描述的设计方案将允许你(web开发人员)通过两个简单的步骤保护一些客户端免受XSS攻击:

设置新的cookie标志(isolatedScript = true)
设置一个HTTP标头(Isolated-Script:true)

就这样。有了这两个东西,你就可以保护你的应用程序防御XSS漏洞攻击。它有点类似于Suborigins,但是使用的是“隔离脚本”的思路防御XSS攻击,即使js文件是在同一个页面内!

除此之外,它还有另外一个优点,它也能够缓解第三方JavaScript代码(如广告,分析,etcetera)。

设计

隔离脚本包括以下三个要素,它们一起工作以提供隔离脚本的防御能力。

(译者注:为了让读者更易理解本文所提供的思路且保证原文纯正的feel,所以译者对这三个要素名词不作翻译)

Isolated Worlds
Isolated cookies
Secret HTML

我会在下面详细描述每一个要素,并给你一些演示。

Isolated Worlds是当前在Chrome扩展的用户脚本和Firefox中的Greasemonkey脚本中最突出使用的一个概念 —— 本质上,它允许JavaScript代码通过文档的DOM获得“view(视图)”,但是是在一个被隔离的JavaScript运行时环境中。 让我详细的来解释一下:

假设在一个网站上有如下代码:

使用脚本隔离技术对抗XSS攻击

Isolated World将有权访问document.getElementById(” text”),但它不能够访问window.variable这个变量。 也就是说,两个脚本共享的唯一的东西就是HTML的DOM的独立视图。 这种隔离非常重要,因为用户脚本可能会提升权限,例如,他们可以向任何网站发起XMLHttpRequests请求并读取其响应内容。

如果不使用Isolated World进行隔离,那么页面就可以在用户的脚本中执行代码,并最终攻击用户:

document.getElementById = function() {
     arguments.callee.caller.constructor("attack()")();
 };

通过这样的方式,Isolated World就允许我们从攻击者执行的上下文中保护我们的特权执行上下文。那么,问题来了:我们能否可以使用相同的设计来保护受信任的脚本防止XSS漏洞吗?

也就是说,我们与其专注于阻止脚本执行作为一种缓解措施(我们发现这种措施容易出问题)还不如将关注点放在将可信脚本与不可信脚本隔离开来。

在同一个DOM中运行具有特权和非特权脚本的想法并不新鲜,事实上,已经有一些这方面的具体实现(如Mario Heiderich的Iceshield和Antoine Delignat-Lavaud的Defensive JS),但是它们的实现都需要将代码重写。使用Isolated World,就没有那么麻烦。

因此,隔离脚本的思路就是—— 为Web开发人员提供一种机制,将特定脚本标记为受信任的,然后由浏览器将它们加载后在Isolated World中运行。

要在demo中实现这一点的一个简单方法就是通过在Chrome扩展中重用Isolated Worlds实现,通过在页面中插入一个用户脚本,为每个脚本设置正确的HTTP响应头。

(译者注:被隔离的脚本就是可信任的脚本,而不是恶意脚本文件。)

Isolated Cookies

现在我们有一个脚本运行在受信任的执行上下文中,现在我们需要一种方法能够让Web服务器识别来自这个脚本的请求。这个做法很有必要,因为服务器可能只想将一些敏感数据暴露给被隔离的脚本。

最简单的方法是添加一个类似于Origin头的新的HTTP请求头(我们可以使用Isolated-Script:foo.js)。另一种方法是创建一种新的cookie类型,它只在请求来自于一个被隔离的脚本时才会发送给服务器。此替代方法优于HTTP请求头有两个原因,如下:

向后兼容,没有实现这种方法的浏览器将只是像往常一样发送cookie。
它可以与同一网站的Cookie(同时也能防御CSRF)结合使用。

Web服务器需要设置Cookie信息:

Set-Cookie: SID=XXXX; httpOnly; secure; SameSite=Strict; isolatedScript

然后,浏览器会像往常一样处理cookie,只有当请求是由被隔离的脚本发出的才会在请求信息中包含该Cookie,另外,如果浏览器不能识别这个新的标志,将会在所有的请求信息中包含该Cookie。

要在demo中实现这一点的一个简单方法是,在cookie中使用特殊的名称,并且除非请求来自于被隔离的脚本否则拒绝发送cookie。

Devdatta提出了一个想法是使用cookie前缀,这同样也可以保护cookie免受窜改攻击。

Secret HTML

我们现在的这种针对脚本隔离的机制依旧让脚本有一些额外的特权,并让这些脚本在隔离的执行上下文中运行来阻止恶意代码执行,然而,该脚本如果将想要显示给用户的数据写入到 DOM后,那么恶意的脚本也能够立即读取到这些内容。所以,为此,我们需要为将被隔离的脚本读写的HTML 内容进行保护从而让恶意的脚本不能够读取到。

虽然此原语你可能从未听过,但它实际上在今天已经存在了!JavaScript代码本身已经可以编写用户可见的HTML内容,但如何让这些HTML内容对DOM不可用?有至少两种方法可以做到这一点︰

创建 iframe,然后导航到: data:text/html URL (在 Firefox 中不起作用,因为FF会把data: URL 作为同源来看待)。
创建带有沙盒属性但是没有allow-same-origin的iframe (在 Chrome 和 Firefox 都有效)。

所以,总结一下,我们已经可以创建父页面不可访问的HTML节点。唯一的问题是,如何使它易于向后兼容。所以,问题又来了:

CSS不会传递到iframe,是为了解决这个问题,我们可以将计算的样式传递到iframe的body中,注意,这将使得我们确保iframe中的文本看起来和在父页面中一样,但是元素选择器在iframe里面不起作用)。
事件不会传递到父页面,为了解决这个问题,我们可以向iframe中插入一个简单的脚本,将所有事件从iframe转发到父页面的document中。

这样的做法非常类似于隐藏的HTML,而且也没有明显的将信息泄漏给恶意的脚本的结果。

要在demo中实现这个思路的一个简单的方法是在innerHTML上创建一个setter函数,每当被隔离的脚本尝试设置innerHTML的值时,我们就改为创建一个带有沙盒属性的iframe并将内容写到这个iframe中,我们可以使用postMessage 将CSS和HTML传递到iframe。并创建一个可用于将事件传递到iframe的消息通道。为了避免混入其他代码依赖,我们可以在封闭的Shadow DOM中创建此iframe。

Malte提出的这个特性的一个潜在问题是,根据实现,这可能会将开发者的体验搞乱,因为一些脚本很可能认为DOM中的一些元素是可以正常访问到的(例如,通过querySelector,getElementsByTagName或其他代码)。考虑这点非常重要,也可能是最宝贵的教训,像我这样的安全人员在设计一些比较奇怪的限制性的API时,我们也应该问问web开发人员想要在页面做什么事情。

Demo

好了!现在我解释了“脚本隔离”的概念,以及它如何在demo中实现,现在是时候让你在行动中看到它了。

首先,要模拟浏览器的行为,你需要安装一个chrome扩展(不要担心,没有可怕的权限),然后去访问“存在漏洞的网站”,并试图窃取XHR响应的内容!如果你可以窃取成功,那么你将会赢得一个特别的 “Isolated Scripts” T恤 :D。

所以,让我们来做吧!

1. 安装Chrome扩展程序

2. 访问脚本隔离PoC网站

这个网站中有XSS的页面无处不在(DOM和反射),我禁用了XSS过滤器,使你的感到更轻松一些。我对于了解突破这个防御思路的不同方法超级有兴趣!

请注意,实现中可能导致的Bug在实际的浏览器实现上不会有问题的,但无论如何请让我知道这些bug,尽管它们不能完全否定这个设计思路,我会修复掉这些bug,使这个设计思路尽可能的接近现实。

如果你需要它,Chrome扩展的源代码在这里,需要更改禁用CSP和启用脚本隔离的代码在这里

分析

现在,我明显有点偏见,因为我已经在这个想法中投入了一些时间,而且我认为这至少有一些希望和潜力。也就是说,我想对它的价值和影响做一个分析,以避免期望过高。我将使用框架来衡量我在上一篇博文中描述到的Web安全缓解措施(如果你还没有阅读它,不用担心,我将在下面做一些解释)。

合理性

合理性标准:我们在多大程度上限制了问题的影响结果?

在这种情况下,影响结果非常容易衡量(模块在实现上有缺陷)。

使用隔离的Cookie保护的任何私密数据仅暴露给被隔离的脚本。而被隔离的脚本所能接触到的任何数据对于XSS来说都是隐藏的。因此,web开发人员可以决定他所需要的限制程度。

Mario提出了一个有趣的警告,在这种保护措施下,仍然有可能使用XSS进行网络钓鱼攻击,并且很可能会导致一小部分社会工程学攻击成功。

最小化

最小化标准:我们最小化问题的数量有多少?

我们也可以计算这个问题。大多数XSS漏洞利用,包括内容嗅探和基于插件的SOP绕过(甚至一些通用类型的XSS错误!)都可以使用脚本隔离进行缓解防御,但对一些DOM型的 XSS不起作用。

之所以无法通过“脚本隔离”缓解DOM XSS,如Angular模板注入和基于eval()的XSS —— 是因为它们仍然继承了被隔离的脚本的一些能力,这类XSS漏洞的触发点本身就包含在被隔离的脚本中也就是我们受信任的脚本中。

我很想知道还有哪些类型的bug,无法利用脚本隔离这种方法缓解。

替代

替代标准:我们用更安全的替代方法能解决的风险有多少?

我们还可以快速衡量我们用脚本隔离解决当前风险的程度。特别是,这个方法的实际采用操作似乎很简单,尽管它还有一些问题:

1. 托管在CDN中的JavaScript代码不能在 Isolated World中运行。这个是预期中的设计思路,不过可能会限制部署的便利性。解决这个问题的一个简单的方法是使用ES6 import语句。

2. 希望能够访问“Secret HTML”(例如广告)的代码将不能正常执行,并且可能会以意想不到的方式运行失败(注意,在浏览器实现中,实际上给予Secret HTML访问Isolated脚本的权限可能是有意义的,如果可能的话)。

我非常感兴趣听到任何其他问题,包括你认为web开发人员在采用这种方法时的一些想法。

简化

简化标准:我们要解决多少问题,而不是增加复杂性?

一般来说,我们在增加了复杂性的同时也消除了复杂性,决定它们是否能够彼此抵消的想法看起来有点主观。

一方面,我们让所有与Secret HTML的内容进行交互都通过单个渠道进行,从而消除了复杂性。

但另一方面,通过添加了另一个cookie标志和用于脚本执行的新条件,以及新的DOM隔离类型,我们这样做使得web平台更难以被理解。

老实说,我们这样做确实有点复杂了。不过在没有其他缓解措施的情况下,这只是稍微有点复杂,毕竟没有其他的防御办法了。我非常有兴趣听到任何关于这个思路应用于web平台的复杂性的任何争论。




原文发布时间为:2017年2月23日
本文作者:丝绸之路
本文来自云栖社区合作伙伴嘶吼,了解相关信息可以关注嘶吼网站。
目录
相关文章
|
3月前
|
JavaScript 安全 前端开发
同源策略如何防止 XSS 攻击?
【10月更文挑战第31天】同源策略通过对 DOM 访问、Cookie 访问、脚本执行环境和跨源网络请求等多方面的严格限制,构建了一道坚实的安全防线,有效地防止了 XSS 攻击,保护了用户在网络浏览过程中的数据安全和隐私。
130 49
|
3月前
|
安全 前端开发 Java
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第26天】Web安全是现代软件开发的重要领域,本文深入探讨了XSS和CSRF两种常见攻击的原理及防御策略。针对XSS,介绍了输入验证与转义、使用CSP、WAF、HTTP-only Cookie和代码审查等方法。对于CSRF,提出了启用CSRF保护、设置CSRF Token、使用HTTPS、二次验证和用户教育等措施。通过这些策略,开发者可以构建更安全的Web应用。
136 4
|
3月前
|
安全 Go PHP
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第27天】本文深入解析了Web安全中的XSS和CSRF攻击防御策略。针对XSS,介绍了输入验证与净化、内容安全策略(CSP)和HTTP头部安全配置;针对CSRF,提出了使用CSRF令牌、验证HTTP请求头、限制同源策略和双重提交Cookie等方法,帮助开发者有效保护网站和用户数据安全。
115 2
|
3月前
|
存储 安全 Go
Web安全基础:防范XSS与CSRF攻击的方法
【10月更文挑战第25天】Web安全是互联网应用开发中的重要环节。本文通过具体案例分析了跨站脚本攻击(XSS)和跨站请求伪造(CSRF)的原理及防范方法,包括服务器端数据过滤、使用Content Security Policy (CSP)、添加CSRF令牌等措施,帮助开发者构建更安全的Web应用。
149 3
|
3月前
|
SQL 存储 安全
什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?
理解并防范XSS、SQL注入和CSRF攻击是Web应用安全的基础。通过采用严格的输入验证、使用安全编码实践以及实现适当的身份验证和授权机制,可以有效防止这些常见的Web攻击,保障应用程序和用户的数据安全。
66 0
|
5月前
|
存储 安全 JavaScript
XSS跨站脚本攻击详解(包括攻击方式和防御方式)
这篇文章详细解释了XSS跨站脚本攻击的概念、原理、特点、类型,并提供了攻击方式和防御方法。
880 1
|
4月前
|
存储 JavaScript 安全
|
4月前
|
存储 JavaScript 前端开发
Xss跨站脚本攻击(Cross Site Script)
Xss跨站脚本攻击(Cross Site Script)
|
7月前
|
存储 安全 JavaScript
手摸手带你进行XSS攻击与防御
当谈到网络安全和信息安全时,跨站脚本攻击(XSS)是一个不可忽视的威胁。现在大家使用邮箱进行用户认证比较多,如果黑客利用XSS攻陷了用户的邮箱,拿到了cookie那么就可以冒充你进行收发邮件,那真就太可怕了,通过邮箱验证进行其他各种网站的登录与高危操作。 那么今天,本文将带大家深入了解XSS攻击与对应的防御措施。
|
7月前
|
SQL 安全 数据库
Python Web开发者必学:SQL注入、XSS、CSRF攻击与防御实战演练!
【7月更文挑战第26天】在 Python Web 开发中, 安全性至关重要。本文聚焦 SQL 注入、XSS 和 CSRF 这三大安全威胁,提供实战防御策略。SQL 注入可通过参数化查询和 ORM 框架来防范;XSS 则需 HTML 转义用户输入与实施 CSP;CSRF 防御依赖 CSRF 令牌和双重提交 Cookie。掌握这些技巧,能有效加固 Web 应用的安全防线。安全是持续的过程,需贯穿开发始终。
117 1
Python Web开发者必学:SQL注入、XSS、CSRF攻击与防御实战演练!