我有一个脚本,打算由第三方网站包括一个创建iframe(基于我们的网站)的脚本。像这样:
<video width="320" height="240" controls autoplay>
该脚本公开了一个API,该API通过// this script exists on the *host site*
const iframe = document.createElement("iframe");
iframe.src = "https://us.com/iframe";
parent.appendChild(iframe);
与iframe内部进行通信,例如:
postMessage
这一切都很好,我的问题是关于iframe的相应“消息”侦听器的。具体来说,我想仅尊重创建窗口/来源中的请求。换句话说,如果某个平行的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);
}
});
}
,我们当然想忽略它。我的问题是仅检查发送的postMessage
是否为window
是否足够?
window.parent
据我了解, 不是足够的检查的唯一方法是window.parent是否有可能更改原点,同时保持我们周围。我可以想象这样一种场景:可以将iframe从一台主机上删除并将appendChild'ed到另一台主机上,但是我相信只有在DOM机械手位于同一来源(从而可以访问所述DOM)并将我们放入另一个起源相同的窗口。
当前,我们采用了额外的偏执狂防御措施,例如通过查询字符串将原始起点传递给iframe:
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...
}
因此,我们可以检查const iframe = document.createElement("iframe");
iframe.src = `https://us.com/iframe?location=${window.location.href}`;
和window === window.parent
。但是,我们真的想脱离此模型,因为它必然会中断跨不同站点的缓存(由于每个查询字符串不同,每个站点都会生成不同的src URL)。因此,对我们来说,仅检查origin === originalOrigin
是否安全?
答案 0 :(得分:1)
使用postMessage
API时,确保消息来自他们所说的地方的唯一真正安全的方法是使用严格的targetOrigin
。这样,您可以确保邮件来自您控制的窗口。
您说的很对,这种情况会阻止传入的消息,而不是来自创建消息的窗口的消息。但是,仍可以在任何来源上创建带有src="https://us.com/iframe";
的iFrame。如果它是在恶意页面上创建的,该怎么办?这仍将满足window.parent === parent
为true
的条件。