如何安全地输出包含HTML标签的内容?

问题描述:

我有一个博客系统,用户必须输入html文本区域的内容,包括html标签,如<p>。这存储在数据库中。如果这个输入然后用php回显到一个网页,我怎么可以逃避输出来防止XSS,但保留html标签的含义,以便博客文章格式正确?如果我使用htmlentities($blog_content),它会将html标签打印到页面上,因此您会看到<p>hello this is a blog</p>如何安全地输出包含HTML标签的内容?

这可能吗?

+0

你测试过htmlentities()吗? – 2013-02-11 16:18:04

+1

[PHP XSS预防白名单](http://stackoverflow.com/questions/2992674/php-xss-prevention-whitelisting) – Quentin 2013-02-11 16:21:18

你想要的是选择性过滤或消毒。换句话说,您希望允许一些 HTML,但不允许其他恶意标记。这是非常棘手的事情,尤其是因为HTML语法非常复杂,过于简单的清理尝试容易出错,从而无论如何都可以通过格式错误的HTML注入标记。

如果可能,您应该远离让用户提交HTML。使用Wiki标记,Markdown,BBcode或类似的特殊标记语言。

如果您确定自己在做什么,您应该选择一个经过良好测试的,功能强大的库,以提供此类清理功能。 HTML Purifier是我认识的唯一适合此描述的人。

+0

最好的解决方案。对于自己回答这个问题犹豫不决,因为他们似乎已经接受了HTML,我不想提出改变建议。但是,如果使用其他标记语言是可行的 - 那就做吧。 – 2013-02-11 16:25:41

+0

谢谢,HTML Purifier在这种情况下似乎是最好的解决方案。由于输入数据的能力将在密码保护区内,并且仅限于极少数用户,因此我很高兴他们能够输入html。 – 2013-02-11 16:49:44

嗯,你可以只剥除<script>标签,使用strip_tags()这不是防弹的解决方案,但你可以通过只允许提高安全一些标签(基本上粗体,斜体,链接和一些更多)...

然后,您可以轻松打印您的内容并避免执行JavaScript。

$text = '<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>'; 
echo strip_tags($text); 
echo "\n"; 

// Allow <p>, <a> and some formatting 
echo strip_tags($text, '<p><a><i><em><b><strong>'); 
+0

'strip_tags'是不够的,因为它不会从元素中删除属性。考虑'' – 2013-02-11 16:19:43

+0

**这部分不是防弹解决方案**你错过了吗? :) – Napolux 2013-02-11 16:21:45

+0

你提到你可以“通过允许一些标签来提高安全性”,这是不真实的。通过实施允许标签的白名单,您根本没有提高安全性。你也提到你可以“避免JavaScript执行”,你不能用这种方法。只是为了一个旁注:downvote不是从我。别生气。我只是建议改进。 – 2013-02-11 16:22:42

你可以使用strip_tags(),并允许一些HTML元素:

echo strip_tags($text, '<p><a>'); 

然而,这仍是危险的,因为有人能像

<p onclick="doSomething();">...</p> 

插入代码,那么这将是最好的,如果您可以使用DOMDocumentloadHtml()方法从数据库加载数据。然后你必须遍历节点并检查是否有任何属性或节点可能需要删除,例如通过使用DOMNode::hasAttributesDOMNode::hasChildNodes

+0

这是正确答案,是'strip_tags'和'DOMDocument'的组合。我在这里唯一的建议是实施允许标记的白名单,而不是黑名单(以防万一您错过了某些内容)。这里的重要提示是如果HTML格式不正确,则不允许发布帖子。否则,任何逻辑都可能破坏格式错误的HTML。 – 2013-02-11 16:23:29