CVE-2019-9787: Unauthenticated CSRF to XSS

由于在Web应用程序中未验证的错误影响最大,因此我们将重点放在未验证功能的漏洞挖掘上。最明显的功能是WordPress的评论功能。任何用户都可以在博客文章中添加评论,甚至可以在评论字符串中包含一些非常基本的HTML标签和属性设置。

抽象划分评论功能

我们首先将评论功能分解为一系列组件,在WordPress网站上创建评论时,用户输入将经过
多个组件处理。

  1. 首先针对XSS攻击进行过滤(XSS过滤组件)
  2. 然后针对SEO进行优化(SEO组件)
  3. 然后存储在数据库中(数据库组件)
  4. 用户查看评论时,从数据库中获取并再次修改(优化组件)
  5. 嵌入到模板渲染出HTML页面(主题组件)

通过将评论功能抽象细分为一系列组件,我们能够快速确定应该花时间在哪些地方来尝试挖掘弱点。我们假设经过多年改进后的【XSS过滤组件】已经足够安全了,所以我们最简单的挖掘漏洞方法是在过滤后的评论字符串中找到一个【修改评论组件】的错误点。由于修改是在【评论创建功能】第二步中针对SEO进行优化才会执行的,且在第四步嵌入HTML标记之前已经被修改。因此我们决定研究这两个相关组件。我们很快注意到第四个组件把评论嵌入到HTML页面之前,并未对评论字符串进行很大的改动以确保不会出现XSS缺陷。因此,我们决定在上游的【SEO优化组件】中寻找弱点。

SEO优化组件中过滤bypass

过滤后的评论传入组件,其将字符串中的<a>标签都进行了SEO进行优化,通过将<a>标签的属性字符串(href="#" title="some link" rel="nofollow")解析为关联数组(以下代码段的3004行)来完成的,此处的key是属性的名称value是属性值。

然后,WordPress检查是否设置了rel属性。如果有就进行处理,并将<a>标签与新的rel属性拼接到一起。

缺陷出现在上述代码片段的第3017和3018行中,这些属性值在没有处理的情况下被拼接在一起。

攻击者可以创建一个包含精心制作的<a>标签的评论,并将锚点的title属性设置为title='XSS" onmouseover=alert(1) id="'。这是有效的HTML属性,并原样走出了过滤步骤。但是,这能够作用仅仅因为精心制作的标题标签使用了单引号。当属性被拼接到一起时,title属性的值是用双引号包裹的(第3018行)。这意味着攻击者可以通过注入额外的双引号来提前关闭title属性然后注入其他HTML属性。

让我们看下面的示例:传入<a title='XSS" onmouseover=evilCode() id="'>过滤后将还是<a title='XSS" onmouseover=evilCode() id="'>。由于已经通过了过滤步骤,因此注入的onmouseover事件会原样存储在数据库中并没删除。这个切入点使我们可以将任意HTML属性注入评论字符串中,而我们只需要弄清楚如何触它就行了。

局限性和漏洞链

我们发现WordPress的【SEO优化组件】存在一个弱点,它是评论创建功能的一部分。但我们意识到仅当可以在的HTML标签中设置rel属性时才会触发这个组件处理的错误。大家认为这有个毛用,因为WordPress的【过滤组件】中实际上不允许设置rel属性,而会将其从用户提交的评论中删除,所以在【SEO优化组件】中发现的弱点这辈子可能都不会触发。因此这可能是这个弱点从来没有报出来过的原因。

利用此弱点的唯一方法是找到另一个漏洞,该漏洞要能让我们设置标签的rel属性。我们的假设这个洞是存在的,因此我们可能要在相同的功能中查找类似错误,这样看,我们就可以将需要审计的组件范围再次缩小。

最终我们认为,成功几率最大的是在WordPress的复杂的XSS过滤组件中找到一个弱点。由于我们只要能注入看起来无害的rel属性,因此不需要针对WordPress的XSS过滤器进行完全绕过。此外我们确切地知道了我们在尝试什么内容的绕过。如果其他研究人员没有专门寻找因允许注入rel属性造成的错误,那么我们就绝不会撞洞了。

评论中的CSRF漏洞

当寻找设置rel属性的bypass的方式时,我们分析了何时以及如何触发针对特定属性的XSS过滤器进行bypass。之后却发现,对于特定的评论其实可以绕过rel属性的过滤器。我们可以通过CSRF漏洞(恶意利用WordPress的引用功能)创建一个过滤器不处理的评论。

当用户发布新评论时,WordPress不会执行CSRF验证。这是因为,进行输入验证时某些WordPress功能(如引用和pingback)将中断。那么攻击者就可以通过CSRF攻击方式,诱导管理员创建一个评论。由于管理员可以在评论中使用任意HTML标签,甚至<script>标签,这就成为了一个可利用的安全问题。理论上讲,攻击者可以简单地利用CSRF漏洞来使管理员创建一个包含恶意JavaScript代码的评论。

WordPress试图通过在评论表单中为管理员生成一个额外的nonce值来修复此问题。当管理员提交评论并提供有效的nonce随机数时,将在不进行任何清理的情况下创建评论。如果随机数无效,仍会创建注释只是注入内容会被清除。

以下代码段显示了如何在WordPress核心中进行处理:

自2009年就从没有为评论表单实施CSRF保护,并且我们发现管理员清理过程中存在逻辑缺陷。如上面的代码片段所示,评论始终使用wp_filter_kses()进行清理,除非创建的用户是具有unfiltered_html功能的管理员。此时如果并且没有提供有效的nonce随机数,则使用wp_filter_post_kses()清理评论(上述代码段的3242行)。

wp_filter_post_kses()wp_filter_kses()之间的区别在于它们的严格性。这两个函数都接受未过滤的评论,并且在字符串中仅保留固定的某些HTML标签和属性。通常评论使用wp_filter_kses()进行清理,该wp_filter_kses()仅允许使用非常基本的HTML标签和属性,例如<a>标记与href属性结合使用。

这使攻击者在创建评论,其中所包含的HTML标签和属性比通常评论中要多得多。尽管wp_filter_post_kses()的通融性要高得多,但它仍然删除了可能导致跨站点脚本漏洞的所有HTML标签和属性。 但是重要的区别是wp_filter_post_kses()允许设置rel标签。最终我们就可以通过CSRF缺陷,使用这个特性来注入rel属性。

影响和局限性

通过将在评论字符串中设置rel属性的CSRF缺陷,与导致任意HTML属性注入的SEO优化组件中的缺陷相结合,攻击者可以创建有效的存储型XSS评论。该漏洞要求在目标WordPress网站上启用评论功能,而默认情况下它就是启用的。

为了将exp升级到远程执行代码的层面,可以利用另一个缺陷。显示新创建的评论的页面未受X-Frame-Options头的保护。这意味着,当攻击者可以诱骗管理员访问触发CSRF漏洞的网站时,他可以在页面背景中创建隐藏的iframe页面来渲染评论并立即执行其中包含的JavaScript代码。

现在攻击者可以通过盗用admin用户的权限,在目标站点上执行任意JavaScript代码了。(开始牛批起来.jpg)

漏洞利用链构造

到目前为止,我们已经完整分析了四个漏洞,这些漏洞可以导致使用默认设置的WordPress中触发远程代码执行。我们以负责任的方式向WordPress安全团队报告了以上所有漏洞,并确保在公开技术细节之前有可用的补丁程序。一位老练的攻击者可以将其组合起来,并使用这些特性来定位目标,并拿下运行WordPress的任何高价值目标。在本节中,我们将探讨攻击者针对WordPress实例构造exp-chain的步骤。

(一)插件漏洞

到目前为止,拿下WordPress网站的最简单方法是爬取目标网站使用的插件列表,然后在每个插件中审计出关键漏洞。WordPress可以安装超过50.000个免费插件,其中许多容易受到某种攻击。例如,在我们的Advent Calendar 2018活动中展示了,即使是安装数量超过500万的最受欢迎插件也存在严重安全问题。这清楚地表明了第三方插件很可能对WordPress网站构成危险。考虑到诸如wpscan之类的工具,可以有效地枚举目标站点使用的所有插件的列表,攻击者的第一步就是简单地遍历该列表并尝试查找这种未验证的漏洞。在本文的上下文中,我们假定目标站点上的所有插件都是安全的,或者该漏洞需要某种类型的用户身份验证。

(二)通过CSRF攻击

如果没有发现易受攻击的插件,攻击者可以审计WordPress核心源码,如本文所述,比如他可以利用CSRF漏洞来导致持久XSS(CVE-2019-9787),攻击者所需要做的就是在博客文章后留下无害评论,该博客文章包含指向攻击者控制的网站的链接即可。

我很喜欢您的博客文章,并无情的转载到了:www.my-similar-blog.com

默认情况下,所有评论都必须由管理员审核。由于需要对管理员进行身份验证才能进行审核,因此,当管理员单击被审核的评论中的恶意网站链接时,管理员绝壁已经登录了。管理员打开此恶意网站后,攻击者便可以利用CSRF漏洞并将新评论添加到管理面板中,从而触发跨XSS。例如,通过已登录管理员的浏览器呈现的JavaScript payload可能会触发以下所述的身份验证的漏洞,以执行任意代码。

(三)利用身份验证的漏洞

一旦攻击者成功攻破了目标网站上的帐户,他的下一步将取决于被劫持帐户的权限。默认WordPress中有五个不同角色:订阅者,贡献者,作者,编辑者和管理员。用户可以根据自己的角色执行不同的操作。

  • 订阅者只能读取内容。
  • 贡献者可以创建新的博客文章,但具有较高用户权限的用户审核后才能发布。
  • 作者可以发布自己的文章,并可以上传媒体文件。
  • 编辑者可以执行与作者相同的操作,但是可以使用任意HTML标签,甚至可以在博客文章和评论中使用<script>标签。
  • 管理员可以执行上述所有操作,并且可以安装新插件,甚至可以直接编辑主题和插件的php文件(出于安全优化考虑,可以禁用此功能)。

订户角色不太可能在WordPress网站上使用,因为它只是一个来宾帐户。贡献者角色无法上传文件,这将阻止拿到此角色帐户的攻击者利用之前所讨论的任何RCE漏洞,因为这些漏洞取决于对文件管理系统的权限。但是,我们发布了有关WordPress中第5个漏洞的详细信息。此漏洞是特权提升(CVE-2018-20152),它使得拿到贡献者权限,就可以在大多数WordPress网站上执行任意代码(技术细节)。

如果攻击者可以使用作者或编辑者的帐户,他就可以利用依赖于文件上传访问权限的上述两个远程执行代码漏洞。

最后,如果攻击者可以直接拿到了管理员帐户,那他可以利用任意WordPress功能,因为管理员可以直接编辑已安装插件的php文件的内容。(该功能可以被禁用)。攻击者可以利用前篇第2节中的RCE漏洞或任何其他RCE漏洞,以获得对底层Web服务器的完全访问权限。

但是,尽管我们提出了攻击者如何从几乎所有用户角色升级到代码执行,但他需要首先在目标站点上拿到帐户。尽管以前的野外的攻击团队已经显示出它们在获取帐户方面的各种手段,但仍然并非总是能成功的。WordPress是一个不需要大量管理帐户的平台。通常,公司只会创建一个或两个管理员帐户,而管理这些帐户的员工可以是具有安全意识的IT专业人员,因此不会轻易受到欺骗。现在怎么办?

头奖:WordPress.org上的可存储XSS

WordPress.org网站包含所有WordPress网站使用的插件和主题存储库。此外,它管理开发人员用来编辑其主题和插件代码的帐户。在2019年5月,我们已通知WordPress安全团队有关此网站上由我们的静态代码分析解决方案发现的严重存储型XSS漏洞。显示存储库中的插件版本号时触发了此漏洞。

WordPress.org网站也是使用WordPress构建的。插件存储库中显示的插件只是专用帖子类型的帖子,这些帖子与特殊模板一起显示。下面的清单显示了负责显示版本号的代码。

这里的get_post_meta()是与WordPress的【Meta组件】使用的同一函数,正如我们先前所展示的那样它并不可信的。任何用户都可以创建一个新插件并将任意JavaScript代码注入其插件的插件版本中。然后导致其他开发者浏览到插件库时,触发XSS而受到攻击。之后将允许攻击者作为劫持开发者操作,把蠕虫payload添加到其他插件中,从而使payload像蠕虫一样在插件之间传播。

把所有弱点组合到一起

现在,我们已经展示了攻击者能够进行以下操作的能力:

  1. 如果启用了评论,则在没有任何用户凭据的情况下也能攻击WordPress网站
  2. 从几乎所有用户角色升级,尽管所有强化机制都已启用到远程代码执行
  3. 如果以上方法均失败,攻击者可以采取最后手段,劫持插件维护者的帐户并植入后门

总结

巴拉巴拉巴拉,老外就是喜欢巴巴好长一段,不翻译了,自己体会一下就好了。

总之就是“好好学习,多多挖洞”

  • 翻译自《How we found 5 0days in WordPress》- RIPS Technologies

RIPSTECH-wordpress-security.pdf (1.702 MB) 下载附件
点击收藏 | 1 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖