电信广告注入分析

起因

广告注入

晚上在调试页面的时候抬头一看,简直了…… 本地调试的页面都被电信强行插入了广告,这要是不防着点儿,等到用户手机上还不定以你的名义插进去了什么乱七八糟的东西。

分析

想要防住的话首先就是的弄清楚是在什么地方被给注入的,于是点开Network标签

网络请求

因为页面逻辑比较简单,有问题的请求很容易就能发现,就是从“ad_unified_access”开始的,按说这个请求不会平白无故发起,所以晚上应该还有某个文件被篡改了以便发起这个请求,继续网上翻

网络请求

看起来这个stat.js就是起点了,这里原有的文件内容被打包封装成了一个新的js文件,在发起原有请求的同时加入了对广告js的请求

网络请求

而这个http://pingjs.qq.com/h5/stats.js?v2.0.4事实上是腾讯统计的代码,首先想到的是DNS劫持,于是找了个在线nslookup工具

nslookup

发现ip并没有什么问题,确实是属于腾讯的机器,看起来使用了更高端的技术,似乎跟防治运营商HTTP劫持的终极技术手段里描述的比较接近

在用户的浏览器连上被访问的网站服务器,发送了HTTP请求后,运营商的路由器会首先收到此次HTTP请求,之后运营商路由器的旁路设备标记此TCP连接为HTTP协议,之后可以抢在网站服务器返回数据之前发送HTTP协议的302代码进行下载软件的劫持,浏览器收到302代码后就会跳转到错误的软件下载地址下载软件了,随后网站服务器的真正数据到达后反而会被丢弃。或者,旁路设备在标记此TCP连接为HTTP协议后,直接返回修改后的HTML代码,导致浏览器中被插入了运营商的广告,随后网站服务器的真正数据到达后最终也是被丢弃。

所以原理也就比较明显了,电信监控一些常用文件的路径请求,比如说腾讯统计、百度统计这类网站中使用频率比较高的,欺负你不是https请求,进行一定概率的文件内容替换返回,以达到插入非法广告的目的。

解决

既然原理清楚了,解决起来也就比较简单了,把对应请求的文件地址换为https即可,查看一下index.html的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>store</title>
</head>
<body>
<noscript>
<strong>We're sorry but store doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<script>
var _mtac = {};
(function() {
var mta = document.createElement("script");
mta.src = "//pingjs.qq.com/h5/stats.js?v2.0.4";
mta.setAttribute("name", "MTAH5");
mta.setAttribute("sid", "000000000");
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(mta, s);
})();
</script>

</body>
</html>

对于stat.js的请求并没有指定http或https,这种用法叫做Protocol-relative URL,简单来说就是使用http还是https来拉取资源文件取决于当前站点所使用的协议,这样可以保持站点所有资源文件请求协议的一致性,避免有的浏览器会提示的http/https内容混用的警告提示,所以,站在腾讯统计的角度上来说,这么提供样例代码确实是合理的。
因为生产环境上使用了https的协议,所以也就不会遇到开发环境类似的问题,当然,有强迫症的话这里显式的指定一下使用https来加载就好了。