防范JavaScript中的DOM XSS安全漏洞
你听说过DOM XSS攻击吗?对于那些没有听说过的人来说。
DOM XSS攻击是指黑客攻击的有效载荷因修改浏览器中的DOM环境而被执行。
这使得客户端的代码意外地运行。因此,该漏洞存在于客户端代码中。攻击者利用他们可以向你的代码中注入有害的有效载荷的实例,使这些攻击成为可能。这是一种注入攻击。
DOM XSS注入可以通过各种方式发生。其中一些如下。
- 接受要加载的代码的URL的元素属性的设置器,如HTMLScriptElement.src
- 接受要执行的代码的元素属性设置器,如HTMLScriptElement.text
- 直接执行代码的函数,如eval
- 对 “javascript: “URL的导航
因此,我们需要采取必要的措施,不惜一切代价避免这些问题。
可信的类型API来拯救
Google Chrome的团队宣布了一个名为Trusted Types API的API,以控制这些DOM XSS的安全漏洞。他们主要是由于基于DOM的XSS漏洞与服务器端XSS漏洞相比在不断增加而推出的。
这是因为DOM XSS很容易引入,但更难检测。
可信类型API如何防止DOM XSS攻击?
可信类型API能够从根源上解决XSS问题本身。让我们来了解一下。
DOM API在默认情况下是不安全的。下面是一些例子。
eval('foo()');
复制代码
很容易向这些注入恶意脚本或恶意HTML。
为了避免这种情况,可信的类型API能够将内容安全策略(CSP)的HTTP响应头设置为Content-Security-Policy: trusted-types *,以只利用可信的类型。这将使开发人员能够阻止危险的注入,使他们默认得到安全。
这可以按以下方式启用。
Content-Security-Policy: trusted-types;
复制代码
Trusted-types指令指示浏览器建立不可欺骗的、类型化的值,以代替字符串传递给DOM XSS汇。
这里的主要想法是将对象传递给DOM汇,而不是字符串。DOM支持对象的传递。
elem.innerHTML = { toString: function() { return 'Hello World' }};
复制代码
Trusted Types API推荐的是传递类型化的对象而不是普通的JS对象。
这将使DOM汇拒绝字符串,只接受匹配的类型。
在实践中使用可信的类型API
如果你打算在你的项目中实施Trusted Types API,首先,你需要找出Trusted Types被违反的地方。这可以非常容易地完成。
检查是否有违反信任类型的情况
将以下HTTP响应头添加到你需要检查违规的文件中。
Content-Security-Policy-Report-Only: require-trusted-types-for 'script'; report-uri //mysite.com/cspViolations
复制代码
然后,所有的违规行为将被报告给//mysite.com/cspViolations 。这不会妨碍你网站的任何功能。
受信任的类型违规报告
当检测到可信类型违规时,它将被发送到一个使用报告-uri配置的报告。例如,如果你向innerHTML传递了一个字符串,将生成类似于下面的报告。
{
复制代码
这将帮助你确定哪些文件中的哪行代码会导致你的网站出现DOM XSS漏洞。
解决违规问题
我们可以用一些方法来消除可信类型的违规。让我们逐一来看看这些方法。
1.重写违规的代码
例如,如果你有一段代码,如el.innerHTML = ‘‘;,这可以重新写成如下。
el.textContent = '';
复制代码
这就避免了直接给innerHTML分配一个字符串。
2.使用一个库
像DOMPurify这样的库可以用来净化HTML,它返回的HTML被包裹在一个TrustedHTML对象中。这就不允许浏览器产生违规。
3.创建一个可信的类型策略
你可以自己创建一个受信任的类型对象,而不是使用一个库或删除有漏洞的代码。可信的类型策略对其输入强制执行安全规则。
- 第1步 – 创建一个策略
if (window.trustedTypes && trustedTypes.createPolicy) {
复制代码
这个规则将省略<字符,以防止创建新的HTML元素。createPolicy()返回一个策略对象,将返回值包裹在一个正确的类型中;在这个例子中是TrustedHTML 。
- 第2步 – 使用策略
const escaped = escapeHTMLPolicy.createHTML('<img src=x onerror=alert(1)>');
复制代码
console.log(escaped instanceof TrustedHTML); // true
复制代码
如果你不能改变代码(例如,当你从CDN采购第三方库时),你可以使用一个默认的策略。
if (window.trustedTypes && trustedTypes.createPolicy) {
复制代码
这是一个政策和净化库的结合。
一旦你解决了所有的违规问题,你就可以在你的代码中强制执行信任类型。这是按以下方式进行的。
Content-Security-Policy
复制代码
你可能注意到,与我们以前的实现相比,这里没有包括-Report-Only后缀。
在这一节中,我们只看了解决HTML违规的问题。然而,Trusted Types API有能力检测违规行为,并在以下方面执行规则。
- HTML
- 脚本
- 脚本URL
- 脚本URL
关于这些不同类型的更多信息,请参考本文档。
强制执行受信任类型的好处
在前面的章节中,你可能已经掌握了在你的应用程序中执行可信类型的好处。我把它们列出来作为一个摘要供你参考。这些是使用这个API的高级好处。
- 减少你网站的攻击面 – 应用程序是安全的
- 在编译时和运行时进行安全验证
- 向后兼容–能够使用可信的类型来代替字符串
- 补充其他安全解决方案,如用于服务器端XSS的CSP
在我们结束之前,让我们也快速看一下浏览器的兼容性。
浏览器的兼容性
不幸的是,在最常见的浏览器中,Firefox和Internet Explorer并不支持Trusted Types。然而,如果你是一个铁杆的Chrome浏览器用户,你就很幸运了。
参考来源
总结
现在,DOM XSS攻击非常普遍,并且在急剧增加。检测这些攻击比我们想象的要难得多。因此,为了使我们的应用程序免受这些攻击,实现可信类型的API是最好的解决方案。
正如我们之前讨论的那样,这可以很容易和快速地完成。为构建安全的应用程序干杯。
谢谢你的阅读!
用比特构建和分享独立的组件
比特是一个超级可扩展的工具,它可以让你用_独立_编写、版本和维护的组件创建_真正的模块化_应用程序 。
用它来构建模块化的应用程序和设计系统,编写和交付微前端,或者简单地在应用程序之间共享组件。
了解更多
谈到JavaScript DOM安全的可信类型API,最初发表在Medium上的Bits and Pieces,人们通过强调和回应这个故事来继续对话。