使用DOMPurify安全显示DOM!

aki发表于:2020年12月14日 14:25:31更新于:2021年01月26日 13:14:24

概要

kintone可以通过自定义来定制记录的显示方式,特别的方便。
可对记录中输入的标记文本以及markdown文本等进行解析并进行显示。

但是,如果不注意安全性问题,可能会遭受恶意攻击。
本次向大家介绍kintone应用可能遭受到的攻击以及如何使用DOMPurify来避免攻击。

DOMPurify由Cybozu CDN分发,请放心使用。

DOMPurify的好处

单纯地想转换成正则表达时,可能会发生绕过过滤注入XSS,
使用innerHTML以及jQueryのhtml()等输出前,先进行DOMPurify.sanitize()转义的话,
可以提高使用HTML标签的安全性。

※ 安全编码指南中也指出,推荐对要输出的所有元素进行转义处理。
如果是迫不得已需要使用innerHTML,像DOMPurify这样的对策是比较有效的选择。

网络攻击的例子

在此向大家介绍含有安全漏洞的应用以及对该应用进行网络攻击的例子。

含有安全漏洞的应用

作为范例,这里准备了如下应用,应用中含有Markdown字段,该字段的内容编译后显示在页面上。

・表单的设置

字段名称字段类型字段代码

Markdown

多行文本框

markdown


空白栏

preview

・表单截图

00160064b894d4fcc84a4bb0de99f65

JavaScript自定义

将下面的代码另存为sample.js,并上传到应用中。

/*
* DOMPurify-kintone
* Copyright (c) 2018 Cybozu
*
* Licensed under the MIT License
*/
(function() {
    'use strict';
    kintone.events.on(['app.record.detail.show'], function(event) {
        var space = kintone.app.record.getSpaceElement('preview');
        $(space).html(marked(event.record.markdown.value));
    });
})();

※用到了JavaScript库的jQuery以及Marked.js。如果您只是想试用一下,可以使用Cybozu CDN分发的库

确认运行结果

打开记录详细页面,可以看到通过编译后的Markdown字段的内容显示在preview空白栏里。

00160064bc197c3a632012a0897258b

网络攻击

假设带有恶意的用户对上述应用的多行文本框字段添加如下代码。

<script>
kintone.api('/k/v1/records', 'GET', {app: kintone.app.getId()}).then(function(response) {
        var ids = response.records.map(function(record) {
            return record.$id.value;
        });
        kintone.api(kintone.api.url('/k/v1/records', true), 'DELETE', {
            app: kintone.app.getId(),
            ids: ids
        });
    });
</script>

当有记录删除权限的用户打开详细页面时,

00160065d207a3077db4893e8f3a7e8

应用内的记录全部被删除了。

像这样带有安全漏洞的应用,即使攻击者没有记录删除权限,也可以间接地删除所有记录。

同样,也可以盗用没有查看权限的记录内容。

注意事项

・以上应用和代码是为了说明网络攻击而创建的,具有安全隐患,在没有诸如DOMPurify等安全对策的情况下,请不要使用。

・仅在测试环境下作为测试用。

如果万一导致数据泄露,才望子不予以负任何责。

cybozu developer network 使用协议

Cybozu CDN服务规章 

对策

我们使用DOMPurify作为上述问题的对策。

使用DOMPurify.sanitize()的话,可以帮我们去除代码内具有危险性的代码(<script>标签等)。

DOMPurify的使用范例

对嵌入HTML的地方进行DOMPurify.sanitize()。

var dirty = '<div><p>文本</p><script>alert('警告');</script></div>';
var clean = DOMPurify.sanitize(dirty);
console.log(clean); // => '<div><p>文本</p></div>'

 我们可以看到<script>alert("警告");</script>被删除了。

刚才的sample.js中加入DOMPurify.sanitize()后,代码如下。

(function() {
    'use strict';
    kintone.events.on(['app.record.detail.show'], function(event) {
        var space = kintone.app.record.getSpaceElement('preview');
        var content = DOMPurify.sanitize(marked(event.record.markdown.value));
        $(space).html(content);
    });
})();

動作確認

00160066441274ff573cd219cab1224

刚才记录全部被删除了,加了DOMPurify.sanitize()之后,
不但可以正常显示Markdown的内容,记录也不会被删除。

最后

在显示用户输入的代码时,如果不注意安全性问题,特别的危险。

本次为了举例说明网络攻击,故意写了具有安全性问题的代码,但是平时有可能一时疏忽而犯了同样错误。

为了防止类似问题的发生,预先使用DOMPurify进行转义的话,可以更加安全地使用DOM。

※当前主要浏览器,在使用innerHTML添加DOM时,不会执行<script>标签内的代码。
可是为了以防万一,还是推荐使用DOMPurify.sanitize()进行转义。

本Tips在2018年6月版的kintone中确认过。