(这是一个较晚的答案,因为这个问题正在成为重复问题所链接的地方,而以前一些重要信息仅在 cmets 中可用。)
HTML Purifier 是一种上下文 HTML 净化器,这就是它似乎在这些任务上失败的原因。
让我们更详细地看看原因:
1<img sRc='http://attacker-9437/log.php?
您会注意到 HTML Purifier 为您关闭了此标签,只留下了图像注入。图像是一个完全有效且安全的标签(当然,当前的图像库漏洞除外)。如果您希望它完全丢弃图像,请考虑通过设置 HTML.Allowed 来调整 HTML Purifier 白名单。
示例中的图像现在正在加载属于攻击者的 URL,从而为攻击者提供加载页面的用户的 IP(仅此而已),这是一个棘手的问题,HTML Purifier 并非旨在解决解决。也就是说,您可以编写一个 HTML Purifier 属性检查器,该检查器在净化之后但在 HTML 重新组合之前运行,如下所示:
// a bit of context
$htmlDef = $this->configuration->getHTMLDefinition(true);
$image = $htmlDef->addBlankElement('img');
// HTMLPurifier_AttrTransform_CheckURL is a custom class you've supplied,
// and checks the URL against a white- or blacklist:
$image->attr_transform_post[] = new HTMLPurifier_AttrTransform_CheckURL();
HTMLPurifier_AttrTransform_CheckURL 类需要有这样的结构:
class HTMLPurifier_AttrTransform_CheckURL extends HTMLPurifier_AttrTransform
{
public function transform($attr, $config, $context) {
$destination = $attr['src'];
if (is_malicious($destination)) {
// ^ is_malicious() is something you'd have to write
$this->confiscateAttr($attr, 'src');
}
return $attr;
}
}
当然,要做到“正确”是很困难的:
- 如果这是对某些网络服务的实时检查,这将减慢净化速度到爬行
- 如果您保留本地缓存,则会面临信息过时的风险
- 如果您使用启发式方法(“根据指标 x、y 和 z,该 URL 看起来可能是恶意的”),您将面临丢失整类恶意 URL 的风险
1"onmouseover=vVF3(9185)"
HTML Purifier 假定您的 HTML 设置的上下文是 <div>(除非您通过设置 HTML.Parent 另有说明)。
如果你只是给它一个属性值,它会假设你要在某个地方输出它,所以最终结果看起来像这样:
...
<div>1"onmouseover=vVF3(9185)"</div>
...
这就是为什么它似乎对此输入没有做任何事情 - 在这种情况下它是无害的。您甚至可能不想在这种情况下剥离这些信息。我的意思是,我们在 stackoverflow 上讨论了这个 sn-p,它很有价值(并且不会导致安全问题)。
上下文很重要。现在,如果你改为使用 HTML Purifier this sn-p:
<div class="1"onmouseover=vVF3(9185)"">foo</div>
...突然你可以看到what it's made to do:
<div class="1">foo</div>
现在它已经移除了注入,因为在 this 上下文中,它会是恶意的。
HTML Purifier 的用途和用途
所以现在您会想知道应该使用 HTML Purifier 做什么,以及什么时候该工具不适合这项工作。以下是简要介绍:
- 如果您要输出到 HTML 文档并且对保留 HTML 完全不感兴趣,您应该使用
htmlspecialchars($input, ENT_QUOTES, 'utf-8')(或任何您的编码) - 这是不必要的开销,它会让一些事情过去
- 如果您想输出到 HTML 文档并允许格式化,您应该使用 HTML Purifier,例如如果您是留言板,并且希望人们能够使用 HTML 格式化他们的消息
- 如果要输出到 HTML 属性,则应使用
htmlspecialchars($input, ENT_QUOTES, 'utf-8')(HTML Purifier 不是 meant for this use-case)
您可以通过上下文in this question / answer找到更多关于清理/转义的信息。