前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Sanitizer:给你的DOM消消毒

Sanitizer:给你的DOM消消毒

作者头像
公众号@魔术师卡颂
发布2021-10-25 15:41:51
7570
发布2021-10-25 15:41:51
举报
文章被收录于专栏:魔术师卡颂魔术师卡颂

大家好,我卡颂。

业务中经常遇到需要处理「有风险的DOM」的场景,比如:

  • 各种工具的文本粘贴功能
  • 需要渲染服务端返回HTML的场景

为了阻止潜在的XSS攻击,有两个选择:

  • escape(转义)
  • sanitize(消毒)

本文会介绍这两者的区别以及为DOM消毒的API —— Sanitizer

本文内容来自Safe DOM manipulation with the Sanitizer API[1]

转义与消毒

假设,我们想将这样一段HTML字符串插入DOM

代码语言:javascript
复制
const str = "<img src='' onerror='alert(0)'>";

如果直接将其作为某个元素的innerHTMLimgonerror回调执行JS代码的能力会带来XSS风险。

一种常见解决方案是:转义字符串。

什么是escape

浏览器会将一些保留字符解析为HTML代码,比如:

  • <被解析为标签的开头
  • >被解析为标签的结尾
  • ''被解析为属性值的开头和结尾

为了将这些保留字符显示为文本(不被解析为HTML代码),可以将其替换为对应的entityHTML实体):

  • <的实体为&lt;
  • >的实体为&gt;
  • ''的实体为&quot;

这种将HTML字符替换为entity的方式被称为escape(转义)

什么是sanitize

对于上面的HTML字符串:

代码语言:javascript
复制
const str = "<img src='' onerror='alert(0)'>";

除了转义''来规避XSS风险,还有一种更直观的思路:直接过滤掉onerror属性。

这种直接移除HTML字符串中有害的代码(比如<script>)的方式被称为sanitize(消毒)

需要用到一个API——Sanitizer[2]。

首先我们通过Sanitizer构造实例:

代码语言:javascript
复制
const sanitizer = new Sanitizer();

调用实例的sanitizeFor方法,传入容器元素类型以及要消毒的HTML字符串:

代码语言:javascript
复制
sanitizer.sanitizeFor("div", str);

会得到一个HTMLDivElement(即我们传入的容器元素类型),其内部包含一个没有onerror属性的img

默认情况下Sanitizer会移除所有可能导致JS执行的代码。

丰富的配置

Sanitizer不仅开箱即用,还提供丰富的白名单、黑名单配置:

代码语言:javascript
复制
const config = {
  allowElements: [],
  blockElements: [],
  dropElements: [],
  allowAttributes: {},
  dropAttributes: {},
  allowCustomElements: true,
  allowComments: true
};

new Sanitizer(config)

比如,allowElements定义元素白名单,只有名单内的元素会被保留,与之对应的blockElements是元素黑名单:

代码语言:javascript
复制
const str = `hello <b><i>world</i></b>`

new Sanitizer().sanitizeFor("div", str)
// <div>hello <b><i>world</i></b></div>

new Sanitizer({allowElements: [ "b" ]}).sanitizeFor("div", str)
// <div>hello <b>world</b></div>

new Sanitizer({blockElements: [ "b" ]}).sanitizeFor("div", str)
// <div>hello <i>world</i></div>

new Sanitizer({allowElements: []}).sanitizeFor("div", str)
// <div>hello world</div>

allowAttributes是属性白名单,与之对应的dropAttributes是属性黑名单,对于如下配置:

代码语言:javascript
复制
{
  allowAttributes: {"style": ["span"]},
  dropAttributes: {"id": ["*"]}}
}

代表消毒后的HTML

  • 只允许span元素拥有style属性
  • 移除所有元素(*通配符代表所有元素)的id属性

兼容性

这么香的API兼容性怎么样呢:

当前只有在Chrome 93之后,开启试验标识后可使用:

代码语言:javascript
复制
about://flags/#enable-experimental-web-platform-features

虽然原生Sanitizer离稳定还遥遥无期,但你可以使用DOMPurify[3]库实现类似功能。

后记

日常你更倾向使用escape还是sanitize呢?

参考资料

[1]

Safe DOM manipulation with the Sanitizer API: https://web.dev/sanitizer/

[2]

Sanitizer: https://wicg.github.io/sanitizer-api/

[3]

DOMPurify: https://github.com/cure53/DOMPurify

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 魔术师卡颂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 转义与消毒
  • 什么是escape
  • 什么是sanitize
  • 丰富的配置
  • 兼容性
  • 后记
    • 参考资料
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档