题
在我的Web应用程序中,我允许发布用户生成的内容以供公共使用,类似于Stackoverflow。
处理此事的最佳做法是什么?
我目前处理用户生成内容的步骤是:
-
我使用 MarkItUp 来允许用户 格式化html的简便方法。
-
用户提交后 更改我通过 HTML运行它 消毒剂 (滚动到 bottem)使用白名单 方法
-
如果消毒程序有 删除任何用户创建的内容我 不保存内容。然后我 用a返回修改后的内容 警告信息,“有些非法 检测到的内容标签和 删除双重检查你的工作和 再试一次。“
-
如果内容通过 清洁过程,我保存 原始的html内容到了 数据库中。
-
当我向客户端渲染时 将原始html传递出db 页面。
醇>
解决方案
这是一种完全合理的方法。对于典型应用,这将是完全足够的。
白名单原始HTML中最棘手的部分是 style
属性和 embed
/ object
。有人可能想要将CSS样式放入不受信任的格式化文本块中,或者说嵌入的YouTube视频,这是有正当理由的。此问题最常见于Feed。您不能信任Feed条目中包含的任意文本块,但您不想删除,例如,突出显示CSS或Flash视频的语法,因为这会从根本上改变内容并可能使阅读它的人感到困惑。因为CSS可能包含IE中的行为等危险事物,所以如果您决定允许 style
属性保留,则可能必须解析CSS。并且使用 embed
/ object
你可能需要列出主机名。
<强>附录强>
在最糟糕的情况下,HTML逃避视线中的一切可能会导致非常糟糕的用户体验。使用像HTML5解析器之类的东西通过白名单来浏览DOM要好得多。就如何向用户呈现已清理的输出而言,这更加灵活。你甚至可以这样做:
<div class="sanitized">
<div class="notice">
This was sanitized for security reasons.
</div>
<div class="raw"><pre>
<script>alert("XSS!");</script>
</pre></div>
</div>
然后使用CSS隐藏 .raw
内容,并使用jQuery将单击处理程序绑定到 .sanitized
div
之间切换<代码> .raw 和 .notice
:
CSS:
.raw {
display: none;
}
jQuery的:
$('.sanitized').click(function() {
$(this).find('.notice').toggle();
$(this).find('.sanitized').toggle();
});
其他提示
白名单是一个很好的举动。任何黑名单解决方案都倾向于让它超出应有的范围,因为你无法想到一切。我已经看到了使用黑名单的一些注意事项(例如代码项目),如果他们设法捕获所有内容,通常它们仍会导致其他问题,例如替换代码中的字符,以便在没有手动恢复它的情况下无法使用它
最安全的方法是:
-
HTML编码所有文本。
-
匹配一组允许的标签和属性并对其进行解码。
醇>
使用正则表达式甚至可以要求每个开始标记都有一个结束标记,这样未封闭的标记就不会弄乱页面。
你应该可以在十行代码中执行此操作,因此您链接的代码似乎过于复杂。