鸿亮妈 發表於 2021-12-1 10:53:00

JavaScript Sanitizer API:原生WEB安全API出现啦

<p>10月18号, W3C中网络平台孵化器小组(Web Platform Incubator Community Group)公布了HTML Sanitizer API的规范草案。这份草案用来解决浏览器如何解决XSS攻击问题。</p>
<p><img src="https://img2020.cnblogs.com/blog/139239/202112/139239-20211201104533890-2045801830.png" alt="" loading="lazy"></p>
<p>网络安全中比较让开发者们头疼的一类是XSS跨站点脚本攻击。这种攻击通常指的是通过利用网页开发时留下的漏洞,即将恶意指令代码注入到网页,使用户加载并执行攻击者恶意制造的网页程序。</p>
<p>这些恶意代码没有经过过滤,与网站的正常代码混在一起,浏览器无法分辨哪些内容是可信的,恶意脚本就会被执行。而XSS攻击的核心有两个步骤:1、处理攻击者提交恶意代码;2、浏览器执行恶意代码。</p>
<p>为了解决在这两步恶意攻击中解决这个问题,通常有以下手段,</p>
<ol>
<li>增加过滤条件</li>
<li>只进行纯前端行渲染,将数据和代码内容分开</li>
<li>对HTML充分转义</li>
</ol>
<p>以上手段这些步骤繁琐,需要注意的内容也很多。为了让开发者更加便捷地解决XSS攻击的问题,浏览器现提供了原生的XSS攻击消毒能力。</p>
<p>HTML Sanitizer API——这份由谷歌、Mozilla和Cure53联手发起提供的API即将最终完成,通过这个浏览器原生API我们可以更加轻松地保护Web应用程序免受XSS的攻击。</p>
<p>接下来我们一起来了解一下这个安全API吧。</p>
<h3 id="sanitizer-api简介">Sanitizer API简介</h3>
<p>Sanitizer API可以让浏览器直接从网站动态更新的标记中删除恶意代码。当有恶意HTML字符串、和文档或文档片段对象想插入现有DOM之中,我们可以使用HTML Sanitizer API直接将这些内容清理。有点像电脑的安全卫士应用,可以清除风险内容。</p>
<p>使用Sanitizer API有以下三个优点:</p>
<ul>
<li>减少Web应用程序中跨站点脚本的攻击次数</li>
<li>保证HTML输出内容在当前用户代理中安全使用</li>
<li>Sanitizer API 的可用性很强</li>
</ul>
<p><img src="https://img2020.cnblogs.com/blog/139239/202112/139239-20211201104543290-321131408.png" alt="" loading="lazy"></p>
<h3 id="sanitizer-api的特性">Sanitizer API的特性</h3>
<p>Sanitizer API为HTML字符串安全打开新世界大门,将所有的功能大致分类,可以分为以下三个主要特性:</p>
<p>1.对用户输入进行杀毒</p>
<p>Sanitizer API的主要功能是接受字符串并将其转换为更安全的字符串。这些转换后的字符串不会执行额外的JavaScript,并确保应用程序受到XSS攻击的保护。</p>
<p>2.浏览器内置</p>
<p>该库在浏览器安装的时候一同预装,并在发现bug或出现新的攻击时进行更新。相当于我们的浏览器有了内置的杀毒措施,无需导入任何外部库。</p>
<p>3.使用简洁安全</p>
<p>在使用了Sanitizer API之后,浏览器此时就有了一个强大又安全的解析器,作为一个成熟的浏览器,它知道如何处理DOM中每个元素的活动。相比之下,用JavaScript开发的外部解析器不仅成本高昂,同时很容易跟不上前端大环境的更新速度。</p>
<p>说完了这些使用上的亮点特性,让我们一起来看看这个API的具体用法。</p>
<p><img src="https://img2020.cnblogs.com/blog/139239/202112/139239-20211201104553091-1928239322.png" alt="" loading="lazy"></p>
<h3 id="sanitizer-api的使用">Sanitizer API的使用</h3>
<p>Sanitizer API使用Sanitizer()方法构造函数,Sanitizer类进行配置。</p>
<p>官方提供了三种基础清理方式:</p>
<p>1、清理隐藏上下文的字符串</p>
<p>Element.setHTML() 用于解析和清理字符串,并立即将其插入DOM,这个方法适用于目标DOM元素已知且HTML内容为字符串的情况。</p>
<pre><code>const $div = document.querySelector('div')
const user_input = `&lt;em&gt;Hello There&lt;/em&gt;&lt;img src="" onerror=alert(0)&gt;` // The user string.
const sanitizer = new Sanitizer() // Our Sanitizer
// We want to insert the HTML in user_string into a target element with id
// target. That is, we want the equivalent of target.innerHTML = value, except
// without the XSS risks.
$div.setHTML(user_input, sanitizer) // &lt;div&gt;&lt;em&gt;Hello There&lt;/em&gt;&lt;img src=""&gt;&lt;/div&gt;



</code></pre>
<p>2、清理给定上下的文字符串</p>
<p>Sanitizer.sanitizeFor() 用于解析、清理和准备稍后准备添加到DOM中的字符串。</p>
<p>适用于HTML内容是字符串,并且目标DOM元素类型已知(例如div、span)的情况。</p>
<pre><code>const user_input = `&lt;em&gt;Hello There&lt;/em&gt;&lt;img src="" onerror=alert(0)&gt;`
const sanitizer = new Sanitizer()
// Later:
// The first parameter describes the node type this result is intended for.
sanitizer.sanitizeFor("div", user_input) // HTMLDivElement &lt;div&gt;


</code></pre>
<p>需要注意的是, HTMLElement中 .innerHTML 的清理输出结果是字符串格式。</p>
<pre><code>sanitizer.sanitizeFor("div", user_input).innerHTML // &lt;em&gt;Hello There&lt;/em&gt;&lt;img src=""&gt;
</code></pre>
<p>3、清理请理节点</p>
<p>对于已经有用户控制的DocumentFragment,Sanitizer.sanitize()可以直接对DOM树节点进行清理。</p>
<pre><code>// Case: The input data is available as a tree of DOM nodes.
const sanitizer = new Sanitizer()
const $userDiv = ...;
$div.replaceChildren(s.sanitize($userDiv));

</code></pre>
<p>除了以上提到的三种方式之外,SanitizerAPI通过删除和、过滤属性和标记来修改HTML字符串。</p>
<p>举个“栗子”。</p>
<p><img src="https://img2020.cnblogs.com/blog/139239/202112/139239-20211201104649024-1794368779.png" alt="" loading="lazy"></p>
<ul>
<li>删除某些标记(<em>script, marquee, head, frame, menu, object, etc.</em>)并保留content标签。</li>
<li>移除大多属性,只保留<code>&lt;a&gt;</code>标签和<code>colspanson&lt;td&gt;,&lt;th&gt;</code>标签上的HREF。</li>
<li>筛选出可能导致风险脚本执行的内容。</li>
</ul>
<p>默认设置中,这个安全API只用来防止XSS的出现。但是一些情况下我们也需要自定义自义设置,下面介绍一些常用的配置。</p>
<h3 id="自定义消毒">自定义消毒</h3>
<p>创建一个配置对象,并在初始化Sanitizer API时将其传递给构造函数。</p>
<pre><code>const config = {
allowElements: [],
blockElements: [],
dropElements: [],
allowAttributes: {},
dropAttributes: {},
allowCustomElements: true,
allowComments: true
};
// sanitized result is customized by configuration
new Sanitizer(config)


</code></pre>
<p>下面是一些常用方法:</p>
<ul>
<li>allowElements 对指定输入进行保留</li>
<li>blockElements blockElements 删除内容中需要保留的部分</li>
<li>dropElements dropElements 删除指定内容,包括输入的内容</li>
</ul>
<pre><code>const str = `hello &lt;b&gt;&lt;i&gt;there&lt;/i&gt;&lt;/b&gt;`

new Sanitizer().sanitizeFor("div", str)
// &lt;div&gt;hello &lt;b&gt;&lt;i&gt;there&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;

new Sanitizer({allowElements: [ "b" ]}).sanitizeFor("div", str)
// &lt;div&gt;hello &lt;b&gt;there&lt;/b&gt;&lt;/div&gt;

new Sanitizer({blockElements: [ "b" ]}).sanitizeFor("div", str)
// &lt;div&gt;hello &lt;i&gt;there&lt;/i&gt;&lt;/div&gt;

new Sanitizer({allowElements: []}).sanitizeFor("div", str)
// &lt;div&gt;hello there&lt;/div&gt;

</code></pre>
<ul>
<li>allowAttributes和dropAttributes这两个参数可以自定义需要保留或者需要删除的部分。</li>
</ul>
<pre><code>const str = `&lt;span id=foo class=bar style="color: red"&gt;hello there&lt;/span&gt;`

new Sanitizer().sanitizeFor("div", str)
// &lt;div&gt;&lt;span id="foo" class="bar" style="color: red"&gt;hello there&lt;/span&gt;&lt;/div&gt;

new Sanitizer({allowAttributes: {"style": ["span"]}}).sanitizeFor("div", str)
// &lt;div&gt;&lt;span style="color: red"&gt;hello there&lt;/span&gt;&lt;/div&gt;

new Sanitizer({dropAttributes: {"id": ["span"]}}).sanitizeFor("div", str)
// &lt;div&gt;&lt;span class="bar" style="color: red"&gt;hello there&lt;/span&gt;&lt;/div&gt;

</code></pre>
<ul>
<li>AllowCustomElements开启是否使用自定义元素</li>
</ul>
<pre><code>const str = `&lt;elem&gt;hello there&lt;/elem&gt;`

new Sanitizer().sanitizeFor("div", str);
// &lt;div&gt;&lt;/div&gt;

new Sanitizer({ allowCustomElements: true,
                allowElements: ["div", "elem"]
            }).sanitizeFor("div", str);
// &lt;div&gt;&lt;elem&gt;hello there&lt;/elem&gt;&lt;/div&gt;


</code></pre>
<p>如果没有进行任何配置,会直接使用默认配置内容。</p>
<p>这个API看起来能为我们解决不小少的问题,但是现在浏览器对其的支持还有限,更多功能还在持续完善中。我们也很期待看到功能更加完善的SanitizerAPI</p>
<p><img src="https://img2020.cnblogs.com/blog/139239/202112/139239-20211201104622471-643831280.png" alt="" loading="lazy"></p>
<p>对它感兴趣的小伙伴在Chrome93+中可以通过<code>about://flags/#enable-experimental-web-platform-features</code>启用,Firefox中目前也在实验阶段,可以在<code>about:config将dom.security.sanitizer.enabled </code>设为true来启用。</p>
<p>了解更多内容可以查看:https://developer.mozilla.org/en-US/docs/Web/API/HTML_Sanitizer_API</p>
<h3 id="关于数据安全的担忧">关于数据安全的担忧</h3>
<p>根据 Verizon 2020 年数据泄露调查报告(Verizon Business,2020 年)显示,约90% 的数据泄露事件是由于跨站点脚本((XSS))和安全漏洞造成的。对于前端开发者而言,面对越发频繁的网络攻击,除了借助Sanitizer API等安全机制外,还可以考虑使用"数据与代码分离"的SpreadJS等前端表格控件。</p>


</div>
<div id="MySignature" role="contentinfo">
    <hr>
<br>
<p style="font-size: 16px; font-family: 微软雅黑, 黑体, Arial; color: #000">本文是由葡萄城技术开发团队发布,转载请注明出处:葡萄城官网</p>
<!--p style="font-size: 16px; font-family: 微软雅黑, 黑体, Arial; color: #000">了解企业级低代码开发平台,请前往活字格
</p><p style="font-size: 16px; font-family: 微软雅黑, 黑体, Arial; color: #000">了解可嵌入您系统的在线 Excel,请前往SpreadJS纯前端表格控件</p>
<p style="font-size: 16px; font-family: 微软雅黑, 黑体, Arial; color: #000">了解嵌入式的商业智能和报表软件,请前往Wyn Enterprise
</p-->

<br><br><br>
来源:https://www.cnblogs.com/powertoolsteam/p/15627916.html
頁: [1]
查看完整版本: JavaScript Sanitizer API:原生WEB安全API出现啦