原文:https://labs.detectify.com/2018/09/04/xss-using-quirky-implementations-of-acme-http-01/

摘要


对于有些托管服务提供商来说,他们实现的http-01验证方法会将部分challenge密钥放到响应中去,从而导致大量实现了http-01 ACME-challenge的网站很容易受到XSS的攻击。

半年以前,Frans对不同的Let's Encrypt验证方法进行了研究,并将结果放到了一篇关于如何利用TLS SNI为共享主机上的其他域颁发证书的文章中。

在这篇报告,还考察了其他验证方法,例如http-01。该验证方法的工作原理是,让Let’s Encrypt 的请求位于/.well-known/acme-challenge/KEY1中的文件,并期望获得具有KEY1.KEY2的格式的响应。

由于KEY1同时出现在响应和请求中,所以,一些托管服务提供商使用支持ACME的证书颁发者(Let's Encrypt只是其中之一)创建了一种解决方案,其中第一个密钥KEY1将从URL中取得,然后,使其与响应中使用的固定的KEY2相结合。

发送请求:

/.well-known/acme-challenge/ABC123

响应如下所示:

ABC123.XYZ567

很明显,这里很容易受到XSS攻击,不过,还需要考虑是否采用了相应的缓解措施:

  • Content-type未设置为HTML。
  • Web浏览器对请求进行URL编码,因此,如果返回原始请求,则无法注入特殊字符,因为它们已经进行了URL编码(<例如,最终会以%3c结尾)。
  • 某些Web浏览器中的XSS审核程序可能会捕获返回的值并阻止触发JavaScript。

实际上,这三种缓解措施都有相应的绕过方法,于是,我们向两家主要的网络托管公司报告了这些问题,因为这使得他们的所有客户都容易受到攻击。其中,一家是大型国际服务提供商,另一家是瑞典最大的托管服务提供商之一。但是,自从将其应用到Detectify监控中后,我们仍然会在客户的网站上发现这个问题,这表明,还有很多服务提供商也容易受到该漏洞的影响。

下面,我们深入介绍如何绕过上述缓解措施。

内容类型非HTML


对于国际托管服务提供商来说,由于内容默认为text/plain,因此,只能将响应呈现为纯文本。但是,Apache有一个名为Magic MIME的旧模式,它将根据响应的第一个字节来确定内容类型。如果启用了该模式,则可以根据响应包含的字符类型来控制内容类型。例如,<b>会导致内容类型为text/html,<?xml会导致内容类型为text/xml。在进行测试时,对于请求/.well-known/acme-challenge/<b>,响应实际上以text/html的形式返回的。

虽然我们的报告中也提到了Magic MIME,然而,相关托管服务提供商婉转表示,他们并没有使用Apache,而是通过某种形式的中间件来完成内容类型的嗅探工作。

当然,我们无法修改Swedish主机提供商的内容类型。然而,正如Jan Kopecky在去年四月发表的文章所展示的那样,我们可以设法让Internet Explorer将纯文本作为HTML执行,到目前为止,这一技巧仍适用于Windows 8.1,不过在Windows 10平台上面已经失效了。

实际上,这种方法是通过创建.eml文件,并将content-type设置为message/rfc822来完成的。它代表Microsoft Outlook Express邮件,用于将电子邮件内容保存到文件中。当加载这类文件时,Internet Explorer会对其余内容执行mime-sniffing(猜测其内容类型)。因此,我们只要将iFrame放到易受攻击的端点中,其内容就会被视为HTML。

对请求内容进行URL编码


当向Swedish托管服务提供商发送请求时,响应中的KEY1的内容总是会进行URL编码。

我们可以再次使用Internet Explorer来解决此问题。关于Internet Explorer的一个不太为人所知的事情是,实际上搜索部分(在URL中的?之后的部分)默认情况下是不进行URL编码。在这种情况下,/.well-known/acme-challenge/之后的所有内容都直接写入页面,这意味着/.well-known/acme-challenge/?<h1>hi将生成一个具有正常HTML标签的响应。

值得一提的是,即使只有路径名会被写入页面的话,也可以这样做。如果它确实会重定向,则Internet Explorer也会将该部分以非URL编码的形式保留下来,这意味着PoC会非常简单:

<?php
    header(“Location: https://vulnerable/.well-known/acme-challenge/<h1>test”);
?>

XSS auditor


在我们忙活半天之后,在发送漏洞报告之前,最后一件事是确保JavaScript确实在Web浏览器中执行。虽然Firefox缺乏XSS-auditor,但随着Chrome的广泛使用,最好让它实现一个XSS-auditor,因为这样可以发挥出最大的效力。

请记住,我们可以控制内容类型。虽然Chrome XSS-auditor不会触发XML,但是,可以提供一个XHTML命名空间,将XML作为HTML来进行安全评估。

POC


针对该国际提供商的完整PoC如下所示:

/.well-known/acme-challenge/%3C%3fxml%20version=%221.0%22%3f%3E%3Cx:script%20xmlns:x=%22http://www.w3.org/1999/xhtml%22%3Ealert%28document.domain%26%23x29%3B%3C/x:script%3E

对于Swedish供应商来说,对应的PoC则是这样的:

TESTEML
Content-Type: text/html
Content-Transfer-Encoding: quoted-printable

<iframe src=3D"http://[redacted]/.well-known/acme-challenge/?<HTML><h1>meh</h1>"></iframe>

缓解措施


这里的关键在于,反模式有时会导致意想不到的副作用,我们的建议是根本不要让acme-challenge请求中的内容泄露出来。相反,如果KEY1恰好需要用于challenge中的话,则使用建议的方法,并仅提供KEY1.KEY2的响应。

点击收藏 | 0 关注 | 1
登录 后跟帖