允许用户向您的网站添加自己的 JavaScript 的安全问题?

IT技术 javascript security
2021-03-17 06:32:15

我计划创建一个开源教育网络应用程序,人们可以在其中添加和编辑内容(有点像维基百科)。

但是,我希望添加另一个功能,允许用户使用 JavaScript 添加他们自己的交互式内容。(类似于 JSFiddle 的做法)

这样做的安全问题是什么?可选问题:如何克服这些问题?

2个回答

是的,您可以使用HTML5 Sandbox仅在 IFrame 中加载用户脚本。

您应该只托管来自与主站点不同的域的用户内容。如果攻击者说服用户直接访问页面(在沙箱之外),这将防止任何XSS攻击。例如,如果您的站点是,www.example.com您可以使用以下代码来显示沙盒 IFrame(注意 .org 而不是 .com,这是一个完全不同的域):

<iframe src="https://www.example.org/show_user_script.aspx?id=123" sandbox="allow-scripts"></iframe>

这将允许脚本,但将阻止 IFrame 之外的表单和导航。请注意,这种方法仍然可能使用户托管网络钓鱼表单以获取凭据的风险您应该确保在用户界面中您的站点和用户内容之间的界限是清晰的。即使我们没有指定allow-forms,这只会阻止直接提交表单,它不会阻止表单元素和 JavaScript 事件处理程序向外部域发送任何数据。

OWASP 上HTML5 安全备忘单指南指出这是沙箱的目的:

对不受信任的内容使用 iframe 的沙箱属性

在渲染 IFrame 之前,您应该先测试是否支持沙箱:

<iframe src="/blank.htm" sandbox="allow-scripts" id="foo"></iframe>
var sandboxSupported = "sandbox" in document.createElement("iframe");

if (sandboxSupported) {
    document.getElementById('foo').setAttribute('src', 'https://www.example.org/show_user_script.aspx?id=123');
}
else
{
    // Not safe to display IFrame
}

它是安全通过动态地改变,以这样来做src,而不是重定向的路程,如果sandboxSupportedfalse因为这样的iframe不小心就会被如果重定向不及时发生呈现。

作为更简单的替代方案,无需检查是否支持沙箱,您可以使用srcdocIFrame 属性生成沙箱内容,确保所有内容都是 HTML 编码的:

例如 <html><head></head><body>This could be unsafe</body></html>

将被渲染为

<iframe srcdoc="&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;This could be unsafe&lt;/body&gt;&lt;/html&gt;" sandbox="allow-scripts"></iframe>

或者你可以构造一个数据 blob 对象,小心地再次进行 HTML 编码:

<body data-userdoc="&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;This could be unsafe&lt;/body&gt;&lt;/html&gt;">

<script>
var unsafeDoc = new Blob([document.body.dataset.userdoc], {type: 'text/html'});

var iframe = document.createElement('iframe');
iframe.src = window.URL.createObjectURL(unsafeDoc);
iframe.sandbox = 'allow-scripts';
</script>

当然,您也可以unsafeDoc从 JSON 数据源设置变量。不建议加载 HTML 文件,因为这与必须来自外部域的问题相同,因为攻击者可以诱使用户直接加载该文件。

另外,请不要试图将用户内容直接写入脚本块。如上所示,数据属性是执行此操作的安全方法,只要对用户数据执行正确的 HTML 编码,因为它是在服务器端输出的。

在这些情况下,您可以保留srcblank.html因为不支持的旧浏览器srcdoc只会加载该 URL。

正如@Snowburnt 提到的,没有什么可以阻止用户脚本将用户重定向到发生偷渡式下载的站点,但是这种方法,假设用户是最新的补丁,并且没有零日漏洞,这是一种安全的方法,因为它通过同源策略保护其最终用户及其在您网站上的数据

这仍然是一个可行的选择吗?我想开发一个平台,用户可以在其中使用 html、js 和 css 构建自己的“module”。
2021-05-01 06:32:15
@JCAguilera 是的,浏览器支持很好如前所述,我建议sandbox使用srcdoc选项或Blob方法,因为这些方法不需要购买另一个域。
2021-05-03 06:32:15
同源策略不是保护用户免受偷渡式下载吗?
2021-05-18 06:32:15
@whereswalden:不,路过式下载实际上是一种浏览器漏洞利用——而不是实际下载。同源策略无法防止浏览器中的错误。
2021-05-20 06:32:15

一个大问题是跨站点脚本,用户添加代码告诉浏览器打开和运行来自其他站点的代码。假设他们添加了一些创建 iFrame 或指向某个站点的隐藏 iFrame 并开始下载恶意代码的内容。

没有简单的方法来解决它(感谢评论中的 Bergi)来确保没有创建任何元素并且没有进行 ajax 调用。

我一直是提供此功能的网站的成员,但对于那些我为自己的空间付费的网站,因此我添加的任何漏洞都给我自己的客户带来了不便,在这种情况下,让它溜走会好一点,因为它不是每个人的安全漏洞。

解决此问题的一种方法是为用户创建可自定义的控件以用于添加交互性。优点是您可以控制正在添加的 javascript,缺点是您的用户群必须请求然后等待您创建它们。

@user3111466 jsfiddle 旨在成为一个沙箱,它的使用通常旨在作为用户群之间事实上的信任。就我个人而言,我不会推出任何允许在用户群中免费使用 javascript 的生产系统,除非是我描述的特定用户负责其命名空间的情况,并且他们只会通过感染自己的用户来欺骗他们的客户带有恶意软件的网站。
2021-04-24 06:32:15
对 javascript 的强烈解析这几乎行不通。您知道可以编写没有字母数字字符的所有 javascript吗?代码过滤器注定要失败。
2021-04-28 06:32:15
但是在这种情况下,JS Fiddle 是如何处理这个问题的,因为他们允许人们提交 JS。也可以像 iframe 中用于 HTML5 的沙箱功能一样工作吗?
2021-05-03 06:32:15
@user3111466:jsfiddle 确实允许脚本运行破坏——你只是从未打开过恶意链接,是吗?Afaik,嵌入的结果来自子域,因此由于同源策略,脚本无法对登录用户执行恶意操作。
2021-05-06 06:32:15