在我的Web应用程序中,我允许发布用户生成的内容以供公共使用,类似于Stackoverflow。
处理此事的最佳做法是什么?
我目前处理用户生成内容的步骤是:
我使用MarkItUp来允许用户 格式化html的简便方法。
用户提交后 更改我通过HTML Sanitizer 运行它(滚动到 bottem)使用白名单 方法
如果消毒程序有 删除任何用户创建的内容我 不保存内容。然后我 用a返回修改后的内容 警告信息,“有些非法 检测到的内容标签和 删除双重检查你的工作和 再试一次。“
如果内容通过 清洁过程,我保存 原始的html内容到了 数据库中。
当我向客户端渲染时 将原始html传递出db 页面。
答案 0 :(得分:2)
这是一种完全合理的方法。对于典型应用,这将是完全足够的。
白名单原始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();
});
答案 1 :(得分:1)
白名单是一个很好的举动。任何黑名单解决方案都倾向于让它超出应有的范围,因为你无法想到一切。我已经看到了使用黑名单的一些注意事项(例如代码项目),如果他们设法捕获所有内容,通常它们仍然会导致其他问题,例如替换代码中的字符,以便在没有手动恢复它的情况下无法使用它
最安全的方法是:
HTML编码所有文本。
匹配一组允许的标签和属性并对其进行解码。
使用正则表达式甚至可以要求每个开始标记都有一个结束标记,这样未封闭的标记就不会弄乱页面。
你应该可以在十行代码中执行此操作,因此您链接的代码似乎过于复杂。