用于JavaScript DOM安全的可信类型API

防范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,人们通过强调和回应这个故事来继续对话。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享