我在我的项目中使用HTML Purifier。
我的HTML是这样的。 (包含简单的html元素+脚本+ iframe)
<p>content...<p>
<iframe></iframe>
<script>alert('abc');</script>
<p>content2</p>
使用默认配置,它变成了这个
<p>content...</p>
<p></p>
<p>Content2</p>
但是如果我像这样设置配置......
$config->set('HTML.Trusted', true);
$config->set('HTML.SafeIframe', true);
我懂了
<p>content...</p>
<p>
<iframe></iframe>
<script type="text/javascript"><!--//--><![CDATA[//><!--
alert('abc');
//--><!]]></script>
</p>
<p>content2</p>
无论如何使用HTML Purifier来完全删除'script'标签但保留'iframe'标签?或HTML Purifier的其他替代方案?
我试过了
$config->set('Filter.YouTube', true);
$config->set('URI.SafeIframeRegexp', '%^https://(www.youtube.com/embed/|player.vimeo.com/video/)%');
但事实证明,“脚本”标签仍然存在。
[编辑]
完整的例子。
$config = HTMLPurifier_Config::createDefault();
$html = "<p>content...<p><iframe ...></iframe><script>alert('abc');</script><p>content2</p>";
$config->set(
'HTML.ForbiddenElements',
'script'
);
$purifier = new HTMLPurifier($config);
$clean_html = $purifier->purify($html);
结果
<p>content...</p><p></p><p>content2</p>
你是正确的一半。如果你将HTML.SafeIframe
设置为true
和URI.SafeIframeRegexp
到你想接受的URL(%^https://(www.youtube.com/embed/|player.vimeo.com/video/)%
工作正常),输入示例如下:
<p>content...<p>
<iframe src="https://www.youtube.com/embed/blep"></iframe>
<script>alert('abc');</script>
<p>content2</p>
...变成...
<p>content...</p><p>
<iframe src="https://www.youtube.com/embed/blep"></iframe>
</p><p>content2</p>
说明:HTML.SafeIframe
允许<iframe>
标记,但HTML Purifier仍然需要iframe可以包含的URL的白名单,否则<iframe>
会打开太多的恶意潜力。 URI.SafeIframeRegexp
提供白名单(以正则表达式的形式,需要匹配)。
看看它是否适合你!
这是我刚刚提到的转换的代码:
$dirty = '<p>content...<p>
<iframe src="https://www.youtube.com/embed/blep"></iframe>
<script>alert(\'abc\');</script>
<p>content2</p>';
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.SafeIframe', true);
$config->set('URI.SafeIframeRegexp', '%^https://(www.youtube.com/embed/|player.vimeo.com/video/)%');
$purifier = new HTMLPurifier($config);
$clean = $purifier->purify($dirty);
如果您不完全信任提交HTML的每个人,我恳请您永远不要将HTML.Trusted
设置为true
。
除此之外,它允许输入HTML中的表单在不受干扰的情况下继续存在,这(如果您正在净化网站,我认为您是这样)会使网络钓鱼攻击变得微不足道。它允许您的输入使用未受损害的样式标记。还有一些东西它仍会被剥离(HTML Purifier实际上并不知道任何HTML标签,即大多数HTML5标签都是其中的一部分,各种JavaScript属性处理程序也是如此),但是你有足够的攻击向量。如果您使用此指令,请不要进行净化。作为Ambush Commander once put it:
你不应该使用%HTML.Trusted;它真的应该被命名为%HTML.Unsafe或其他东西。
考虑使用像Masterminds html5-php这样的完整HTML解析器。然后解析HTML代码,而不会像在IFRAME
中包装P
那样进行不必要的更改,并且您将能够以您希望的方式操作生成的DOM树,包括删除一些元素,同时保留其他元素。
例如,以下代码可用于从文档中删除SCRIPT
元素:
foreach ($dom->getElementsByTagName('script') as $script) {
$script->parentNode->removeChild($script);
}
请注意这样的代码:
<script type="text/javascript"><!--//--><![CDATA[//><!--
alert('abc');
//--><!]]></script>`
已经过时了。现代HTML5等效代码是:
<script>alert('abc');</script>
与HTML Purifier处理之前完全一样。