Skip to content

四火的唠叨

一个纯正程序员的啰嗦

Menu
  • 所有文章
  • About Me
  • 关于四火
  • 旅行映像
  • 独立游戏
  • 资源链接
Menu

HTTP 劫持

Posted on 04/30/201310/19/2019 by 四火

想谈一谈这个话题是因为最近有一位朋友抱怨他的博客在某些用户某些时候访问的时候,被莫名其妙地加上了广告,他检查来检查去,始终发现不了网站本身有什么问题,后来他才了解到了 HTTP 劫持一说。

HTTP 劫持

其实这不是一个新概念了,在几年前,中国一些不讲道德的运营商,尤其是地方运营商就开始捕捉用户浏览器的访问记录,然后根据不同用户的访问行为,有选择地往用户访问的网页里面推送广告。他们可以为所欲为地强制改写网站 HTML 页面,采用往返回页面里写入 JavaScript 等方式,来注入广告:

image

这是访问 55BBS 网站时某些用户会在屏幕右下角看到一个京东商城的广告。这样的广告,不但可以在一些中小网站上见到,在国内大型网站上也屡见不鲜。很多网民会立即怀疑自己的机器有没有中病毒或者木马,或者是什么恶意的浏览器插件又在作祟。其实,这都是运营商搞的鬼。

有的用户会坚决地投诉,运营商有自己的白名单,用户在投诉成功以后会账号被加入白名单,不再投放广告。显然他们也不想惹过多的麻烦,这样恶心的事情需要偷偷地干。

另一方面,很多地方运营商会把这样的 HTTP 劫持后注入广告的行为加入到用户协议中去,让用户无话可说。比如北京联通就曾经提供了不同的收费服务,一种是无广告的,一种是包含注入广告的,价格当然是无广告的更高。

在 2010 年的时候,因为这样的劫持行为,青岛联通还在一场引起轩然大波的索赔案件中败诉,被罚 20 万元给百度。索赔从金额来看显然是小事,但是对于中国互联网的成熟还是有积极意义的。在中国,你可以选择的运营商就那么几个,就好比从一堆烂苹果中挑选一个自己能忍受的。而且这个行业本身就缺乏道德和完善的法律约束,单单靠用户个体抱怨和投诉,无法从根本上解决流氓行为。这也许是互联网发展不够成熟的一个不可回避的阵痛。

技术实现

理论上说,运营商掌握了 HTML 页面的全部代码,它可以做任何的事情,真正无缝地植入广告,然后返还给用户。但是,这种广告的植入是批量的行为,如果要针对不同的网站页面分别去设置广告代码,代价未免太高了一点。另一方面,植入的 JavaScript 代码片段很容易受到不同 DOM 环境和 JavaScript 代码环境本身的影响,而植入广告,不能影响到原有网站页面的展示和行为。为了尽可能地减少植入广告对原有网站页面的影响,运营商通常会通过把原有网站页面放置到一个和原页面相同大小的 iFrame 里面去,通过 iFrame 来隔离广告代码对原有页面的影响。由于这样的劫持行为会针对不同用户的某些访问发生,我举例不够方便,为了让大家能够 100% 地观察到这个效果,我找了这样联通的提示页面来举例:

在访问不存在的网站的时候,比如 www.adfasdfasdfasdf.cn 这样乱填写的域名,以北京联通为例,它并不会直接返回错误码,而是重定向到这样一个错误提示页面:

image

这个重定向后的 URL 为:http://bjdnserror1.wo.com.cn:8080/issueunziped/bj130404/self0.jsp?UserUrl=www.adfasdfasdfasdf.cn

这样的行为招来非议的人可能不多,毕竟这样的域名确实不存在,对用户和站长带来的影响不大。但是,请注意它左下角和右侧的广告,在这里它注入广告的方式,采用的 iFrame 嵌套的方式,和上面我提到的劫持行为,是完全一致的。

现在请将上述 URL 的 self0.jsp 改成 index.htm,也就是:

http://bjdnserror1.wo.com.cn:8080/issueunziped/bj130404/index.htm?UserUrl=www.adfasdfasdfasdf.cn

你可以看到这样的页面:

image

刚才提到的广告没有了,对不对?

你可以把 index.htm 这个页面想象成一个网站的原始页面,然后,运营商创建了这样一个新页面,而把原始页面以 iFrame 的形式嵌入到其中:

1
2
3
4
<IFRAME id="fulliframe" name="fulliframe" frameSpacing=0 noResize height=1350 marginHeight=0 border=0 src="" frameBorder=0 width="100%" scrolling=no vspale="0"></IFRAME>
<script language="JavaScript" type="text/javascript">
    frames['fulliframe'].location = window.location.href.replace('self0.jsp','index.htm');
</script>

这样一来,就可以继续往这个新页面里面写代码,引入广告了:

1
2
<script src="http://cpro.baidustatic.com/cpro/ui/f.js" type="text/javascript"></script>
<script language="JavaScript" type="text/javascript" src="bdfloat.js"></script>

怎么破?

既然已经知道了原理,那么自然就容易想到解决的办法。对于这一类劫持,有一个共同特点是,原有网站的页面,都是放在一个 iFrame 里面的,那么只要加上这样的脚本,判断如果页面是以一个 iFrame 加载的,就让父页面重定向到原页面去:

1
2
if(top!==self)
    top.location.href=this.location.href;

当然,你也可以重定向到一个你认为可靠的链接上去,甚至加上你需要的参数等等信息(比如运营商添加的广告代码 URL),以记录这一罪证。

多说几句

这种劫持方式还显得原始和粗放,而且这些采用 iFrame 方式实现 HTTP 劫持的运营商还算有一些良心,因为对原有页面的影响较小,但是还有一些地方运营商,只是往原始页面单纯地写入 javascript 代码,很多情况下都会影响到原始页面的展示和行为,这时候问题就显得麻烦得多了。

首先我们需要获取这种行为的具体信息,一种办法是你掌握一个页面原有的 JavaScript 方法、DOM 对象列表,或者是浏览器请求的域名列表(类似于一个白名单),如果发现列表之外的未知方法、DOM 对象的引入,或者是预期之外的 URL 的请求,把这样的信息发送到服务端去分析。

比如,页面被强制注入了这样的代码:

1
document.write("<script language='javascript' src='http://.../广告脚本链接'></script>");

我们可以用一点小技巧来对付,比如 JavaScript 劫持:

1
document.write = function(){};

让 document.write 方法变成一个空函数,让注入代码这一行为失效。当然,具体问题还是需要具体分析,重要的是掌握信息。但是话说回来,我们只是程序员,我们创造的是原始页面,在恶意的运营商手里,靠技术层面的技巧,我们的力量还是太小了。

此外,联通的这个广告系统做得太缺乏保护性了,只要随便改一改链接,Tomcat 版本号等等信息就暴露出来了,如果真要有人想做点什么的话……

image

[Update 2019-5-28] 更新:现在最好的防止无良的运营商用这种方式嵌入广告的办法是,把网站从 HTTP 改成 HTTPS 的,参见几天前更新的这篇文章 《HTTPS 升级》。

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

×Scan to share with WeChat

你可能也喜欢看:

  1. JavaScript 3D 图表
  2. 跨域方法汇总
  3. 从 JavaScript 的单线程执行说起
  4. JavaScript 并发下载
  5. Backbone.js

9 thoughts on “HTTP 劫持”

  1. Brother Sharp says:
    10/06/2015 at 9:49 AM

    不错的文章,让我对 DNS 劫持瞬间有了较深的理解

    Reply
  2. 肖欣 says:
    05/10/2013 at 4:05 PM

    请教楼主,Tomcat 版本号等等信息暴露出来,有什么坏处呢?不怀好意的人怎么利用这些暴露出来的信息呢?

    Reply
    1. Anonymous says:
      05/10/2013 at 7:52 PM

      知道用的什么容器,什么版本号,就有针对性了。比如上网搜一搜某个版本号下的漏洞,然后就可以做很多事了。

      Reply
      1. Anonymous says:
        01/21/2015 at 10:16 AM

        学习了~

        Reply
  3. Anonymous says:
    05/05/2013 at 7:45 AM

    楼住的是不是搞错了 ———————– DNS 是解析域名的 怎么可能将 html 代码更改呢 ————- 除非人家将你的 IP 解析到代理服务器上,然后在代理服务器上做 http 响应内容的更改,不然技术上说不通啊

    Reply
    1. 四火 says:
      05/05/2013 at 8:35 AM

      从原理上看,正如你所说。所以使用一些不受污染的 DNS 服务器地址可以解决这样的问题。

      Reply
    2. Anonymous says:
      01/21/2015 at 10:17 AM

      说的不错啊,我也正疑惑这个

      Reply
  4. 御宅暴君 says:
    04/30/2013 at 4:29 PM

    可以到工信部举报。
    不过我好久没见过 DNS 劫持了,大概被 Adblock 屏蔽了吧。

    Reply
  5. Yu says:
    04/30/2013 at 3:43 PM

    时效性真高,是为了昨天那个微薄吧

    Reply

Leave a Reply to 肖欣 Cancel reply

Your email address will not be published. Required fields are marked *

订阅·联系

四火,啰嗦的程序员一枚,现居西雅图

Amazon Google Groovy Hadoop Haskell Java JavaScript LeetCode Oracle Spark 互联网 亚马逊 前端 华为 历史 同步 团队 图解笔记 基础设施 工作 工作流 工具 工程师 应用系统 异步 微博 思考 技术 数据库 曼联 测试 生活 眼界 程序员 管理 系统设计 缓存 编程范型 美股 英语 西雅图 设计 问题 面向对象 面试

分类

  • Algorithm and Data Structure (30)
  • Concurrency and Asynchronization (6)
  • System Architecture and Design (43)
  • Distributed System (18)
  • Tools Frameworks and Libs (13)
  • Storage and Data Access (8)
  • Front-end Development (33)
  • Programming Languages and Paradigms (55)
  • Testing and Quality Assurance (4)
  • Network and Communication (6)
  • Authentication and Authorization (6)
  • Automation and Operation Excellence (13)
  • Machine Learning and Artificial Intelligence (6)
  • Product Design (7)
  • Hiring and Interviews (14)
  • Project and Team Management (14)
  • Engineering Culture (17)
  • Critical Thinking (25)
  • Career Growth (57)
  • Life Experience and Thoughts (45)

推荐文章

  • 谈谈分布式锁
  • 常见分布式系统设计图解(汇总)
  • 系统设计中的快速估算技巧
  • 从链表存在环的问题说起
  • 技术面试中,什么样的问题才是好问题?
  • 从物理时钟到逻辑时钟
  • 近期面试观摩的一些思考
  • RSA 背后的算法
  • 谈谈 Ops(汇总 + 最终篇):工具和实践
  • 不要让业务牵着鼻子走
  • 倔强的程序员
  • 谈谈微信的信息流
  • 评审的艺术——谈谈现实中的代码评审
  • Blog 安全问题小记
  • 求第 K 个数的问题
  • 一些前端框架的比较(下)——Ember.js 和 React
  • 一些前端框架的比较(上)——GWT、AngularJS 和 Backbone.js
  • 工作流系统的设计
  • Spark 的性能调优
  • “残酷” 的事实
  • 七年工作,几个故事
  • 从 Java 和 JavaScript 来学习 Haskell 和 Groovy(汇总)
  • 一道随机数题目的求解
  • 层次
  • Dynamo 的实现技术和去中心化
  • 也谈谈全栈工程师
  • 多重继承的演变
  • 编程范型:工具的选择
  • GWT 初体验
  • java.util.concurrent 并发包诸类概览
  • 从 DCL 的对象安全发布谈起
  • 不同团队的困惑
  • 不适合 Hadoop 解决的问题
  • 留心那些潜在的系统设计问题
  • 再谈大楼扔鸡蛋的问题
  • 几种华丽无比的开发方式
  • 我眼中的工程师文化
  • 观点的碰撞
  • 谈谈盗版软件问题
  • 对几个软件开发传统观点的质疑和反驳
  • MVC 框架的映射和解耦
  • 编程的未来
  • DAO 的演进
  • 致那些自嘲码农的苦逼程序员
  • Java 多线程发展简史
  • 珍爱生命,远离微博
  • 网站性能优化的三重境界
  • OSCache 框架源码解析
  • “ 你不适合做程序员”
  • 画圆画方的故事

近期评论

  • panshenlian.com on 初涉 ML Workflow 系统:Kubeflow Pipelines、Flyte 和 Metaflow
  • panzhixiang on 关于近期求职的近况和思考
  • Anonymous on 闲聊投资:亲自体验和护城河
  • 四火 on 关于近期求职的近况和思考
  • YC on 关于近期求职的近况和思考
  • mafulong on 常见分布式基础设施系统设计图解(四):分布式工作流系统
  • 四火 on 常见分布式基础设施系统设计图解(八):分布式键值存储系统
  • Anonymous on 我裸辞了
  • https://umlcn.com on 资源链接
  • Anonymous on 我裸辞了
© 2025 四火的唠叨 | Powered by Minimalist Blog WordPress Theme
Menu
  • 所有文章
  • About Me
  • 关于四火
  • 旅行映像
  • 独立游戏
  • 资源链接