我有一个表单,用户可以使用TinyMCE输入描述,以进行样式设置。因此,我的用户可以插入HTML。我已经使用strip_tags
剥离了几乎所有HTML元素,但用户仍然可以输入恶意值,例如:
<strong onclick="window.location='http://example.com'">Evil</strong>
我希望通过剥离所有标记的所有属性来阻止用户执行此操作,但style
属性除外。
我只能找到剥离所有属性的解决方案,或者只删除指定的属性。我只想保留style
属性。
我尝试过DOMDocument,但它似乎自己添加了DOCTYPE
和html
标记,并将其作为整个HTML文档输出。此外,它有时似乎随机添加HTML实体,如颠倒的问号。
这是我的DOMDocument实现:
//Example "evil" input
$description = "<p><strong onclick=\"alert('evil');\">Evil</strong></p>";
//Strip all tags from description except these
$description = strip_tags($description, '<p><br><a><b><i><u><strong><em><span><sup><sub>');
//Strip attributes from tags (to prevent inline Javascript)
$dom = new DOMDocument();
$dom->loadHTML($description);
foreach($dom->getElementsByTagName('*') as $element)
{
//Attributes cannot be removed directly because DOMNamedNodeMap implements Traversable incorrectly
//Atributes are first saved to an array and then looped over later
$attributes_to_remove = array();
foreach($element->attributes as $name => $value)
{
if($name != 'style')
{
$attributes_to_remove[] = $name;
}
}
//Loop over saved attributes and remove them
foreach($attributes_to_remove as $attribute)
{
$element->removeAttribute($attribute);
}
}
echo $dom->saveHTML();
答案 0 :(得分:1)
以下是DOMDocument :: loadHtml()的两个选项,可以解决问题。
$dom->loadHTML($description, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
但它们仅在libxml&gt; = 2.7.8中可用。如果您有旧版本,可以尝试不同的方法:
如果您知道您希望使用该片段,则可以使用该片段并仅保存body
元素的子元素。
$description = <<<'HTML'
<strong onclick="alert('evil');" style="text-align:center;">Evil</strong>
HTML;
$dom = new DOMDocument();
$dom->loadHTML($description);
foreach($dom->getElementsByTagName('*') as $element) {
$attributes_to_remove = iterator_to_array($element->attributes);
unset($attributes_to_remove['style']);
foreach($attributes_to_remove as $attribute => $value) {
$element->removeAttribute($attribute);
}
}
foreach ($dom->getElementsByTagName('body')->item(0)->childNodes as $node) {
echo $dom->saveHTML($node);
}
输出:
<strong style="text-align:center;">Evil</strong>
答案 1 :(得分:0)
我不知道这或多或少是你的意思......
$description = "<p><strong onclick=\"alert('evil');\">Evil</strong></p>";
$description = strip_tags( $description, '<p><br><a><b><i><u><strong><em><span><sup><sub>' );
$dom=new DOMDocument;
$dom->loadHTML( $description );
$tags=$dom->getElementsByTagName('*');
foreach( $tags as $tag ){
if( $tag->hasAttributes() ){
$attributes=$tag->attributes;
foreach( $attributes as $name => $attrib ) $tag->removeAttribute( $name );
}
}
echo $dom->saveHTML();
/* Will echo out `Evil` in bold but without the `onclick` */