【问题标题】:XSS vulnerabilities still exist even after using HTML Purifier使用 HTML Purifier 后仍然存在 XSS 漏洞
【发布时间】:2017-11-15 20:59:54
【问题描述】:

我正在使用Acunetix 测试我的一个网络应用程序。为了保护这个项目免受 XSS 攻击,我使用了HTML Purifier。大多数 PHP 开发人员为此目的推荐该库,但我的扫描结果显示 HTML Purifier 无法完全保护我们免受 XSS 攻击。扫描器通过发送不同的有害输入发现了两种攻击方式:

  1. 1<img sRc='http://attacker-9437/log.php?(见 HTML Purifier 结果here
  2. 1"onmouseover=vVF3(9185)"(见 HTML Purifier 结果here

如您所见,HTML Purifier 无法检测到此类攻击。不知道 HTML Purifier 是否有专门的选项来解决此类问题,还是真的无法检测到这些 XSS 攻击方法。
你有什么主意吗?还是其他解决方案?

【问题讨论】:

  • 1 不是 XSS。 2 是安全的,除非你滥用净化器(你不应该将用户内容放在属性中)。
  • 1没错,其实就是HTML注入。 2 用于在文本框中打印用户搜索词。你对这两个问题有什么想法吗?
  • 2 应该用htmlspecialchars() 完全缓解(这将转义引号)。它通常不是您应该提供的 HTML Purifier - HTML Purifier 用于完整的 HTML,而不是用于 HTML 属性中的文本。 (不过,您可以在没有htmlspecialchars() 的情况下构建您的 HTML,然后 然后 在输出之前通过 HTML Purifier 运行整个文档。然后 HTML Purifier 将从它恰好位于的任何标签中删除“onmouseover” .)
  • 查看htmlpurifier.org/… 以获取2在其HTML 上下文中 纯化时的示例。

标签: php security xss code-injection htmlpurifier


【解决方案1】:

(这是一个较晚的答案,因为这个问题正在成为重复问题所链接的地方,而以前一些重要信息仅在 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找到更多关于清理/转义的信息。

【讨论】:

    【解决方案2】:

    所有的 HTML 净化器似乎都在做,从我给出的简短外观来看,是 HTML 编码某些字符,例如 &lt;&gt; 等等。但是,还有其他方法可以在不使用普通 HTML 字符的情况下调用 JS:

    javascript:prompt(1)  // In image tags
    src="http://evil.com/xss.html"  // In iFrame tags
    

    请查看下面的 cmets(@pinkgothic)。


    以下几点:

    1. 这将是有效导致 XSS 的 HTML 注入。在这种情况下,您打开一个&lt;img&gt; 标签,将src 指向一些不存在的文件,这反过来会引发错误。然后可以由 onerror 处理程序处理以运行一些 JavaScript 代码。举个例子:

    &lt;img src=x onerror=alert(document.domain)&gt;

    它的入口点通常伴随着过早关闭输入上的另一个标签。例如(为清楚起见,对 URL 进行了解码):

    GET /products.php?type="><img src=x onerror=prompt(1)> HTTP/1.1
    

    然而,这很容易通过 HTML 转义元字符(即&lt;&gt;)来缓解。

    1. 与上面相同,除了这可能是关闭 HTML 属性而不是标记并插入其自己的属性。假设您有一个页面,您可以在其中上传图片的 URL:

    &lt;img src="$USER_DEFINED"&gt;

    一个正常的例子是:

    &lt;img src="http://example.com/img.jpg"&gt;

    但是,在插入上述有效负载时,我们切断指向不存在文件的src 属性并注入onerror 处理程序:

    &lt;img src="1"onerror=alert(document.domain)"&gt;

    这将执行上述相同的有效负载。


    补救

    这在多个地方都有大量文档和测试,因此我不会详细介绍。但是,以下两篇文章非常适合该主题,可以满足您的所有需求:

    1. https://www.acunetix.com/websitesecurity/cross-site-scripting/
    2. https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

    【讨论】:

    • 实际上,onerror 属性已被 HTML Purifier 剥离(事实上,任何未列入白名单的属性都默认被剥离),因此您的 #1 已被 HTML Purifier 缓解。 OP 中描述的攻击是 CSRF(相关)攻击,HTML Purifier 不能防止这些攻击(也不能,因为除了启发式和/或检查之外,没有办法区分好 URL 和坏 URL针对数据库的 URL,这可能是一个令人望而却步的开销,并且如果添加到处理中则允许 DoSing - 尽管 HTML Purifier 允许自定义,因此您可以添加它。
    • 一般来说,HTML Purifier是一个HTML解析器,它使用白名单来保护用户。它实际上是一个非常强大的工具,可以配置为比默认设置更宽松或更安全,具体取决于您的需要(请参阅htmlpurifier.org/live/configdoc/plain.html)。这通常也不是人们所需要的 -->
    • 如果您需要净化 HTML 文档或需要安全显示为 HTML 的 HTML 文档 sn-ps,HTML Purifier 是适合该工作的工具。如果您只想保留数据(htmlspecialchars 或 SQL 注入缓解在这里更有用,具体取决于上下文),或者只想保护属性的内容但不通过 HTML Purifier 运行整个文档,那么这是错误的工具。
    • @pinkgothic - 如果是这样的话,HTML Purifier 就可以了。再一次,这是在 HTML Purifier 之外的更高层次上解释它,因为我不知道它是如何工作的以及它做了什么。用户收到了 XSS 漏洞警报,上面大致说明了如何处理它以及它是如何发生的。
    • @pinkgothic 为延迟道歉——很快更新我的答案。
    猜你喜欢
    • 2021-09-03
    • 2023-04-07
    • 1970-01-01
    • 2012-03-10
    • 2017-01-02
    • 2011-12-03
    • 2012-06-21
    • 2022-01-12
    • 1970-01-01
    相关资源
    最近更新 更多