使用iframe作为跨站点的通信层是否存在任何安全漏洞?

时间:2017-01-27 09:25:26

标签: javascript security iframe cross-domain

此poc的目标:

  • 一种让用户通过webapps登录的方法
  • 在不同的域名
  • 做一次,随处导入

poc:

所以我想到了这个可能的解决方案。我称之为用户小部件。

假设我们有服务AUTH提供端点登录和注销,它还设置httpOnly cookie。

这应该是标题,分布在webapps上。标题下载iframe并使用postMessage向其发送调用,以了解用户是否已登录,否则显示登录:

<script>
    /**
     ****************************************
     * Code that should be inside the header
     ****************************************
     */
    window.onload = function() {
      (function(){
        if (window.addEventListener) {
            window.addEventListener("message", handleMessage, false);
        } else {
            window.attachEvent("onmessage", handleMessage);
        }

        //- This could be * meaning no preferences, or a URI,
        //- but SHOULD not be * but the correct origin
        var iframeOrigin = "*";
        var iframeId = 'IFRAME-PROXY';

        createIframe(checkStatusOfLogin);

        var doLoginButton = document.getElementById('do-login');
        doLoginButton.onclick = doLogin;

        function createIframe(onLoadCallback) {
          var iframe = document.createElement('iframe');
          iframe.id = iframeId;
          iframe.style.display = 'none';
          iframe.src = 'https://mysecureiframe.securedomain.com/file.html';
          document.body.appendChild(iframe);
          iframe.onload = function () {
            onLoadCallback(iframe);
          };
        }

        function checkStatusOfLogin(iframe) {
          var iframeWin = iframe.contentWindow;
          var payload = {
              action: 'status'
          };
          iframeWin.postMessage(JSON.stringify(payload), iframeOrigin);
        }

        function doLogin() {
            var iframeWin = document.getElementById(iframeId).contentWindow;
            var payload = {
                action: 'login',
                username: document.getElementById('username').value,
                password: document.getElementById('password').value
            };
            iframeWin.postMessage(JSON.stringify(payload), iframeOrigin);
        }

        function handleMessage(evt) {
            console.log('Inside client tab, received: ', evt);
            var userContainer = document.getElementById('user-container');
            try {
              var parsedResponse = JSON.parse(evt.data);
              if (parsedResponse.isCIA) { // checking it's a postmessage from us and not an extension
                if (parsedResponse.status == "LOGGED_IN") {
                    userContainer.classList.remove('not-logged-in');
                } else if (parsedResponse.status == 'NEED_LOGIN') {
                    userContainer.classList.add('not-logged-in');
                }
              } else {
                throw new Error('not CIA message');
              }
            } catch (e) {
              console.log('not CIA message');
            }
        }
      }());
    };
    /**
     *******************
     * End of header code
     * *****************
     */
</script>

iframe包含一个非常简单的正文:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://mysecureiframe.securedomain.com/loginProvider.js" type="text/javascript" ></script>
    </head>
    <body>
        <p>IFRAME NON VISIBILE</p>
    </body>
</html>

以下是loginProvider.js

的内容
(function() {
    if (window.addEventListener) {
        window.addEventListener("message", handleMessage, false);
    } else {
        window.attachEvent("onmessage", handleMessage);
    }

    // to read: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
    // Guardare HEADER Content-Security-Policy instead of X FRame Options
    function checkStatus(success, failure) {
        var http = new XMLHttpRequest();
        var url = "https://mysecureiframe.securedomain.com/status"; // AUTH endpoint
        http.open("GET", url, true);
        http.onreadystatechange = function() { //Call a function when the state changes.
            if (http.readyState == 4 && http.status == 200) {
                if (http.responseText == "true") {
                    success();
                } else {
                    failure();
                }
            }
        };
        http.send();
    }

    function doLoginIframe(user, pass) {
        var http = new XMLHttpRequest();
        var url = "https://mysecureiframe.securedomain.com/login"; // AUTH endpoint
        http.open("POST", url, true);
        http.onreadystatechange = function() { //Call a function when the state changes.
            if (http.readyState == 4 && http.status == 200) {
              if (user == 'username' && pass == 'password') {
                var payload = getPayload();
                payload.status = 'LOGGED_IN';
                parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
                alert(http.responseText);
              }
            }
        };
        http.send();
    }

    function getPayload() {
        return {
            isCIA: true
        };
    }

    function handleMessage(evt) {
        console.log('Inside iframe, got: ', evt); // TODO Check targetOrigin is from trusted sites
        var parsedRequest = JSON.parse(evt.data);
        if (parsedRequest.action == "status") {
            checkStatus(function() {
                var payload = getPayload();
                payload.status = 'LOGGED_IN';
                parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
            },
              function () {
                var payload = getPayload();
                payload.status = 'NEED_LOGIN';
                parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
            });
        } else if (parsedRequest.action == "login") {
            doLoginIframe(parsedRequest.username, parsedRequest.password);
        }
    }
}());

除了添加检查以查看origin是否是受信任的站点之外,您是否看到使用此策略的特定安全流?

0 个答案:

没有答案