一、概念
1. window.name
- 在窗口还没被关闭之前,窗口载入的所有页面都共享同一个window.name。
这个窗口可理解为chrome的一个tab标签页面,在该页面中跳转打开另一个页面后,这些页面都共享同一个window.name。
- 每个页面都能读写window.name。
这个可能就是安全问题的来源。
- 可以存储不超过2M的数据。
大小没测试过,MDN上没说明,但有些文章有提到。
可参考:
https://developer.mozilla.org...
https://www.jianshu.com/p/43f...
2. postMessage
- 可以安全地实现跨源通信。
- 提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
语法:otherWindow.postMessage(message, targetOrigin, [transfer]);
事件:window.addEventListener("message", receiveMessage, false);
message的属性有:data, origin, source
详情可参考:https://developer.mozilla.org...
二、安全问题比较
简称:
攻击者页面:A
被攻击者页面:B
1. window.name
- 可通过在A中嵌入B,实现在A获取B的window.name的数据
- 如果B中存在eval执行window.name的代码,则存在xss安全问题,因为在1的基础上,A可修改window.name的数据,从而导致B出现xss问题
2. demo验证:
验证观点1
A:http://localhost:3000/window.name.html
B:http://localhost:3001/window.name.html
效果如下图:
代码如下:
// A页面:<head> <meta charset="utf-8"> <title>window.name</title></head><body> <script> function iframeOnload() { var iframe = document.getElementById('iframe'); iframe.onload = function () { console.log('攻击者页面log:被攻击者页面的数据已拿到:', iframe.contentWindow.name); } iframe.src = 'http://localhost:3000/xx.html' } </script> <iframe id="iframe" src="http://localhost:3001/window.name.html" onload="iframeOnload()"></iframe></body>// B页面:<head> <meta charset="utf-8"> <title>window.name</title></head><body> <script> window.name = '这是重要信息!!!' console.log('被攻击者页面log:', window.name) </script></body>
验证观点2
A:http://localhost:3000/window.name.html
B:http://localhost:3001/window.name.html
效果如下图:
先打开A页面,1秒钟后,跳转到B页面,并执行alert代码
代码如下:
// A页面<head> <meta charset="utf-8"> <title>window.name</title></head><body> <script> window.name = 'alert(/xss/)' console.log(window.name) setTimeout(() => { location.href = 'http://localhost:3001/window.name.html' }, 1000) </script></body>// B页面<head> <meta charset="utf-8"> <title>window.name</title></head><body> <script> console.log('被攻击者页面log:', window.name) eval(window.name) </script></body>
3. postMessage
不存在window.name的第一个问题,因为postMessage要指定源targetOrigin,只要不是该源的,都收不到消息。同时,在接收消息的时候,也可以指定来源origin,如果来源不对,则可不读取消息。
解决跨域问题,现在基本用postMessage。
但postMessage也存在不足,比如只能指定特定的源,相对正常的xhr请求,增加代码量。
所以如果能开cors,则基本是完美的跨域解决方案。
MDN上安全问题的建议:
如果您不希望从其他网站接收message,请不要为message事件添加任何事件侦听器。 这是一个完全万无一失的方式来避免安全问题。
如果您确实希望从其他网站接收message,请始终使用origin和source属性验证发件人的身份。 任何窗口(包括例如http://evil.example.com)都可以向任何其他窗口发送消息,并且您不能保证未知发件人不会发送恶意消息。 但是,验证身份后,您仍然应该始终验证接收到的消息的语法。 否则,您信任只发送受信任邮件的网站中的安全漏洞可能会在您的网站中打开跨网站脚本漏洞。
当您使用postMessage将数据发送到其他窗口时,始终指定精确的目标origin,而不是*。 恶意网站可以在您不知情的情况下更改窗口的位置,因此它可以拦截使用postMessage发送的数据。