我计划创建一个开源教育网络应用程序,让人们可以添加和编辑内容(类似维基百科)。
但是,我希望添加另一个功能,允许用户使用JavaScript添加自己的交互式内容(就像JSFiddle一样)。
这样做存在哪些安全问题? 可选问题:这些问题如何解决?
我计划创建一个开源教育网络应用程序,让人们可以添加和编辑内容(类似维基百科)。
但是,我希望添加另一个功能,允许用户使用JavaScript添加自己的交互式内容(就像JSFiddle一样)。
这样做存在哪些安全问题? 可选问题:这些问题如何解决?
您可以使用 HTML5沙盒 仅在IFrame中加载用户脚本。
您应该仅从与主站点不同的域托管用户内容。这将防止任何 XSS 攻击,如果攻击者说服用户直接访问页面(超出沙箱)。例如,如果您的网站是 www.example.com
,则可以使用以下代码显示沙箱IFrame(请注意.org而不是.com,这是完全不同的域):
<iframe src="https://www.example.org/show_user_script.aspx?id=123" sandbox="allow-scripts"></iframe>
allow-forms
,但这仅会阻止直接提交表单,而不会阻止表单元素和JavaScript事件处理程序向外部域发送任何数据。
OWASP HTML5安全备忘单建议指出这是沙箱的目的:
在呈现IFrame之前,您应首先测试是否支持沙箱。对于不受信任的内容,请使用iframe的sandbox属性
<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
而不是在sandboxSupported
为false
时重定向,可以更安全地进行操作,因为如果重定向没有及时发生,则不会意外呈现iframe。srcdoc
IFrame属性生成沙箱内容,确保所有内容都是HTML编码的:<html><head></head><body>This could be unsafe</body></html>
将呈现为
<iframe srcdoc="<html><head></head><body>This could be unsafe</body></html>" sandbox="allow-scripts"></iframe>
或者您可以构建一个数据Blob对象,再次小心地进行HTML编码:<body data-userdoc="<html><head></head><body>This could be unsafe</body></html>">
<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
变量。不建议加载HTML文件,因为这具有与外部域相同的问题,攻击者可能会诱使用户直接加载该文件。此外,请不要尝试直接将用户内容写入脚本块。如上所示,data attributes是安全的方法,只要在服务器端输出用户数据时进行正确的HTML编码即可。在这些情况下,您可以将src
保留为blank.html
,因为不支持srcdoc
的旧浏览器将简单地加载该URL。
正如@Snowburnt所提到的那样,没有什么可以阻止用户脚本将用户重定向到发生驱动下载的网站,但是这种方法假设用户已经更新了补丁,并且没有零日漏洞,这是一种安全的方法,因为它通过同源策略保护其最终用户及其在您网站上的数据。