正确防止跨源iframe消息中的XSS

正确防止跨源iframe消息中的XSS,iframe,cross-domain,xss,Iframe,Cross Domain,Xss,我正在构建一个站点,任何人都可以通过postMessage命令与我的iFrame交互(即沙盒函数,而不是完全控制窗口)。在不通过XSS暴露访问者的cookies的情况下,我如何做到这一点 假设我有以下接收功能: var secret = localStorage.getItem("secret"); window.addEventListener(message,function(e){ // any e.origin is allowed if(e.func=="doX"

我正在构建一个站点,任何人都可以通过postMessage命令与我的iFrame交互(即沙盒函数,而不是完全控制窗口)。在不通过XSS暴露访问者的cookies的情况下,我如何做到这一点

假设我有以下接收功能:

var secret = localStorage.getItem("secret");

window.addEventListener(message,function(e){
     // any e.origin is allowed
     if(e.func=="doX"){
            var string = e.data.string1 * e.data.string2;

     }else if(e.func=="doY"){
            // another javascript function, no DOM interaction
            config[e.data.key] = e.data.value;

     }else if(e.func=="doZ"){
          document.getElementById("app")=e.data.title
          document.getElementById("description")=e.data.description
     }
})


我在Mozilla页面上看到,允许来自任何来源的请求都是非常危险的。如何正确地防止doX、doY和doZ场景中的每一个出现xs

我也试过了。这些功能安全吗

var secret = localStorage.getItem("secret");

window.addEventListener(message,function(e){
     // any e.origin is allowed
     if(typeof e.func!=Number) return;

     if( e.func < 0 || e.func > 2) return;

     if(e.func==0){ //  we will call this "Safe 0"

            if(e.data.num1 > 1000 || e.data.num2 > 1000) return;
            var num3 = e.data.num1 * e.data.num2;

     }else if(e.func==1){ // safe 1

            if(!isHex(e.data.value))return; // see below for isHex func

            config['something'] = e.data.value;

     }else if(e.func==2){ // safe 2

          if(e.data.title.length < 8) document.getElementById("app")=e.data.title;

          if(e.data.description.length < 15)document.getElementById("description")=e.data.description

     }
})
function isHex(h) {

    var a = parseInt(h,16);
    return (a.toString(16) === h)

}

var secret=localStorage.getItem(“secret”);
window.addEventListener(消息,函数(e){
//任何e.来源都是允许的
if(typeof e.func!=Number)返回;
如果(e.func<0 | | e.func>2)返回;
如果(e.func==0){//我们称之为“安全0”
如果(e.data.num1>1000 | e.data.num2>1000)返回;
var num3=e.data.num1*e.data.num2;
}如果(e.func==1){//safe 1
if(!isHex(e.data.value))返回;//有关isHex函数,请参见下文
config['something']=e.data.value;
}如果(e.func==2){//safe 2
如果(e.data.title.length<8)document.getElementById(“app”)=e.data.title;
如果(e.data.description.length<15)document.getElementById(“description”)=e.data.description
}
})
函数isHex(h){
var a=parseInt(h,16);
返回(a.toString(16)==h)
}
我了解到,HTML输入元素也将无法从托管站点访问,这意味着这些“postMessage”是漏洞的主要来源。最后一句话的来源:

只要我没有对使用postMessage函数发送到我的窗口的消息运行eval语句,是否有任何方法可以执行任意代码

任何常见的客户端JS XSS攻击向量都是开放的


因此,除了
eval
,您还具有各种代理eval功能(例如
new Function()
),以不安全的方式将消息中的数据插入DOM的效果,等等。

据我所知,XSS漏洞最好在特定情况下考虑。这不仅仅是通过postmessage将变量安全地放入您的窗口,而是一旦变量出现,您将如何处理它。比如,您不希望接受变量参数并下载脚本,因为变量可以更改为下载恶意脚本。你不会做评估报告的。我仍然不确定“
evalByProxy
”是否适用于纯javascript环境(没有HTML/输入元素操作;没有与数据库的通信)。由于我要求另一位回答者对此进行澄清,而我无法通过谷歌找到任何相关信息,因此我认为只要我不将iFrame消息传递给服务器数据库、DOM或运行eval语句,这就不是一个真正的问题。查看基本XSS聊天室示例,了解为什么将这些消息发送到服务器是个坏主意


在试图保持iFrame安全的情况下,我发现更大的安全威胁是存在浏览器扩展(例如AdBlocker)。它们获得访问网页每个部分的权限。这意味着他们可以访问网页中的任何全局变量和任何全局函数。我还不确定他们是否可以访问局部作用域变量(例如,对象内部)。我不确定他们是否可以访问本地存储,但我猜他们可以。因此,我在XSS消息的空间中继续温和地讨论,并且正在重新考虑任何涉及本地存储的方法。

您能否更详细地说明如何实现这一点?假设我有一个敏感变量包含在单词
var secretkey
中,和/或另一个敏感变量包含在
localStorage
中,名为
secretkey
。。。如何确保这些iframe消息不会调用
new Function()
并访问它们?或者,我想我更想问的是,如何确保不会发生这种情况?我需要列出有效的消息或输入类型吗?例如,如果可能的颜色为红色、蓝色、绿色,请使用这些字符串创建一个列表,并确保输入消息仅为这些颜色?第二个例子:如果输入应该是一个浮点数,确保有类型号。但是,如果我想允许其他源向div标记添加任意字符串,该怎么办?这是可能的还是有风险的?请参阅添加的示例它们可以使用代理对象替换所有内容。为了操纵正常执行和呼叫总部等,您也可以添加变异观察者来保护您的DOM(即更改post消息。也就是说,如果调用postmessage,则始终返回字符串“no no…”)。记住,如果您(或其他人)告诉浏览器您的请求头字段“host”=x或“origin”,浏览器是愚蠢的=y或任何其他字段,它会盲目相信它是事实…用户a访问用户B拥有的网站。用户B的网站有一个承载Facebook.com的iFrame,其中Facebook.com iFrame接受来自任何来源的消息。有了此权限,网站所有者用户B能否操纵嵌入其网站的Facebook iFrame,从本地存储访问用户A的Facebook登录令牌?假设facebook iframe允许从任何来源接收消息,用户B是否仍然可以注入
新函数()
,等等,以获取用户A特定的facebook专用变量?你将如何防止这种情况发生?是的,我曾亲自在一家合作伙伴公司的小部件中这样做。主站点(window.top.location)拥有这些权限,而您限制任何内容的能力很弱。但是,按照我说的做一个代理,让他们知道他们所做的任何事情。我这样做的方式是使用WebSocket(他们不受cors等的影响),你可以直接在不是你的网站上与客户沟通。因此,您不需要在localstorage/cookie中保存任何数据。