用postMessage检查window.parent的起源有啥意义吗?

Posted

技术标签:

【中文标题】用postMessage检查window.parent的起源有啥意义吗?【英文标题】:Any point in checking origin of window.parent with postMessage?用postMessage检查window.parent的起源有什么意义吗? 【发布时间】:2018-12-29 19:12:45 【问题描述】:

我有一个脚本打算包含在创建 iframe 的第三方网站中(在我们的来源上)。像这样的:

// this script exists on the *host site*
const iframe = document.createElement("iframe");
iframe.src = "https://us.com/iframe";
parent.appendChild(iframe);

该脚本公开了一个 API,该 API 通过postMessage 与 iframe 进行内部通信,类似于:

// This script exists on the *host site*
function getSomeProperty()

    return new Promise(function (resolve, reject)
    
        theIFrame.postMessage("getSomeProperty", "us.com")
        window.addEventListener("message", function (event)
        
            // ... get the response, making sure its from us.com, etc.
            // This is just pseudo code, we don't create a new listener
            // on every call in our real code.
            resolve(answer);
        
    );

这一切都很好,我的问题是关于 iframe 的相应“消息”侦听器。具体来说,我想尊重来自创建窗口/来源的请求。换句话说,如果某个独立来源(例如广告)上的某个并行 iframe 为我们构造了一个postMessage,我们当然希望忽略它。我的问题是是否足够简单地检查发送window是否是window.parent

const parent = window.parent;

// This event handler is in the *embedded iframe*
window.addEventListener("message", function (event)

    // This is being sent from a window other than 
    // the one that created us, bail!
    if (event.window !== parent)
         return;

    // it is safe to respond...

据我了解, 不是充分检查的唯一方法是 window.parent 是否有可能 更改来源 同时保持我们周围。我可以想象可以从一个主机中删除 iframe 并将其附加到另一台主机上的场景,但我相信这只有在 DOM 操纵器位于同一来源(因此可以访问所述 DOM)并将我们置于另一个同源窗口。

目前,我们采用了一种额外的偏执防御,即通过查询字符串将原始来源传递给 iframe:

const iframe = document.createElement("iframe");
iframe.src = `https://us.com/iframe?location=$window.location.href`;

因此允许我们检查window === window.parentorigin === originalOrigin。但是,我们真的很想摆脱这种模型,因为它必然会破坏不同站点之间的缓存(因为每个站点都会由于不同的查询字符串而生成不同的 src URL)。那么,我们只检查window === window.parent 是否安全?

【问题讨论】:

【参考方案1】:

使用postMessage API 时,确保消息来自他们所说的地方的唯一真正安全的方法是使用严格的targetOrigin。这样您就可以确保消息来自您控制的窗口。

您说得对,这种情况会阻止来自创建它们的窗口以外的传入消息。但是,仍然可以在任何来源上创建带有src="https://us.com/iframe"; 的 iFrame。如果它是在恶意页面上创建的怎么办?这仍然满足window.parent === parenttrue 的条件。

【讨论】:

以上是关于用postMessage检查window.parent的起源有啥意义吗?的主要内容,如果未能解决你的问题,请参考以下文章

怎样用postMessage向一个窗口发送Alt+D组合键

SendMessage, postmessage模拟鼠标左键

MFC中使用PostMessage和SendMessage函数

Postmessage模拟键盘

iframe向父级传递参数(用postMessage来解决跨域)

服务工作者 - 等待client.openWindow在postMessage之前完成