【技术探索】什么是中间人攻击&使用Whistle监听移动端App的连接
0 引入
朋友最近在京东上抢国补优惠券,但僧多粥少,一连好几天也抢不到。一气之下,他在网上搜罗到了一邪修方法,问我是否有效。
初步判断,这一方法和大多数的抢票脚本一致,通过截获客户端的请求,并多次重发该请求,从而规避图形界面和手速带来的延迟。但令我耳目一新的是,这个方法使用名为 Whistle 的 Web 调试工具,实现了对手机App请求的截获与重放(国补券在这些电商App上发放)。而我之前所实践的抢课、抢票方法都是基于浏览器网页的,可以简单地使用 Burp Suite 甚至是 F12 控制台进行操作。
因此,我决定花一篇文章系统探索一下这类抢票&抢券方法背后的原理:中间人攻击(Man-in-the-Middle, MITM)。在这之后,我将初步尝试 Whistle 这款Web调试工具,并探索使用 Whistle 监听移动应用Web请求乃至抢票的可行性。
本文仅作为学习网络安全与通信原理的技术探索,并非“抢票教程”,也不建议也不鼓励用于任何违反法律或平台规则的行为。
1 原理解析:什么是中间人攻击?
在介绍具体的方法实现之前,我们不妨先来了解一下它们背后的原理。
核心思路:“中间商赚差价”
对于中间人攻击的基础概念,维基百科是这样说的:
中间人攻击是指攻击者与通讯的两端分别建立独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。
换句话说,你(Alice)以为你在和 Bob 通信,实际上你的数据先经过了攻击者 Attacker,再由 Attacker 转发给 Bob。而 Attacker 在这个过程中可以监听到你们的通信内容,甚至篡改其中的某一部分。
所幸,得益于TLS、HTTPS等安全技术,我们可以最大程度地避免窃听,同时确保通信的另一方真实可信,从而抵御绝大多数的中间人攻击。若未能成功建立安全连接,浏览器也会用醒目的提示警告用户,最大程度地避免危害。
破解加密连接:“李鬼扮李逵”
然而,再密不透风的城墙也总会有其疏漏。对于这类加密通信,攻击者往往可以通过伪造证书的方式对其进行解密——但是,“证书”和这又有什么关系?
在那之前,我们不妨明确一下,我们在网络通信中所追求的安全,究竟意味着什么。
简单来说,可以概括为以下三个方面:
- 机密性:确保通信内容不会被泄露给第三方,防止通信内容被窃听。如果通信不加密,任何能截获流量的人都能直接看到明文,如密码或信用卡号。
- 完整性:确保信息不会被不恰当篡改。若无法保证数据的完整性,网络攻击者(中间人)可能会截获数据包,对其进行修改、删除或重放,从而导致接收方收到错误的信息。例如,将“向A转账100元”修改为“向B转账10000元”。
- 身份识别和认证:确保你正在通信的对象就是你想要通信的真实服务器,而不是一个冒充的恶意服务器,从而保证数据真实可信。
以最常见的加密连接技术—— TLS 为例(HTTPS 就是 TLS 基础上的 HTTP),为了解决机密性的问题,引入了非对称加密和对称加密结合的方式对传输数据进行加密;同时,TLS采用了HMAC(基于密钥的哈希认证码)来保障数据的完整性。
具体的协议和连接机制比较复杂,这里就不再赘述了。可以肯定的是,这些措施保证了通信不会在传输过程中被第三方破译和篡改。
既然第三方窃听的方法行不通,那能不能干脆把中间人伪装成“第二方”?
为了防止这样的情况,身份认证机制应运而生,大幅降低了中间人进行伪装的可能性。通常而言,在建立连接时,只有服务器的身份需要认证——客户端(我们)是否真实可信对服务器来说不重要。
为了解决这一问题,TLS 使用了公钥基础设施(PKI) 和 数字证书 来实现服务器的身份认证:
- 在试图建立 TLS 连接时,服务器会向客户端出示一个由可信的证书颁发机构(CA) 签发的数字证书。
- 该证书包含了服务器的公钥、域名、签发机构等信息,并由CA的私钥进行了数字签名。
- 客户端操作系统中内置了可信CA的根证书列表,客户端会使用对应的CA公钥来验证服务器证书签名的真实性。
- 验证成功之后,客户端会使用证书中的公钥参与密钥交换过程,从而确保只有持有对应私钥的服务器才能完成握手。这样就能有效防止证书被盗用。
打个比方,这就好像服务器在建立连接之前,必须向客户端出示“营业执照”。而客户端会检查颁发营业执照的“市场监督管理局”是不是正牌的(记录在册,且公章能对应上)。这里的营业执照就是服务器的数字证书,而市场监督管理局就是 CA。
不仅如此,客户端会利用营业执照上的信息“考验”服务器——如果这份执照是服务器冒用别人的,它就会露馅。
至此,TLS 已经成功堵住了绝大多数安全风险点。也就是说,要想成功实现中间人攻击,只剩下了一个方法:派遣内鬼。
中间人没办法伪装成服务器通过认证,遂另辟蹊径——冒充受信任的证书颁发机构(CA):通过在目标客户端上安装其伪造的CA证书,使客户端信任所有由这个伪造CA签发的所有证书。这样一来,中间人只需要现场为自己签发一个证书,就能够轻而易举地骗过客户端,和它建立加密连接,如图所示:
总之,攻击者通过自签名的根证书,成功伪造目标网站的证书并取得了访问者 Alice 的信任。在这之后,攻击者就能够分别与通信双方建立安全连接,并在两者之间进行解密→再加密的转发,从而达到不动声色的监听与篡改。我们本次所用的Web调试工具,也采用了这样的原理。
值得一提的是,在企业网络或者部分校园网络中,IT部门也会在员工/用户电脑中强制安装此类根证书,从而对上网行为加以监管。因此使用公司电脑浏览奇怪的小网站是非常不明智的行为。
总结
综上所述,中间人攻击的本质,是攻击者利用“受害者信任的通信链路”,偷偷把自己变成“传话人”,从而获取或篡改数据。它一般需要实施这四个步骤:
- 拦截:攻击者通过网络劫持、ARP 欺骗、DNS 欺骗、恶意代理等方式,让通信流量经过自己。
- 解密:如果通信是明文(HTTP、Telnet),攻击者可以直接读取;如果是加密通信(HTTPS、TLS),攻击者可能会伪造证书进行解密(常见于调试代理工具的做法)。
- 篡改/伪造:攻击者可以在中间修改数据,比如替换网页内容、注入恶意代码、甚至伪造对方的身份。
- 转发:被篡改后的数据继续传递给目标,使得双方通常察觉不到异常。
那么身为普通用户的我们,要如何防御这种中间人攻击呢?
- 上网时使用 HTTPS/TLS,并严格校验证书——不要轻易点击“无视风险并继续”。
- 一定不要随意安装未知来源的根证书!!
- 尽量避免使用公共 Wi-Fi,必要时使用 虚拟专用网络 加密所有流量。
2 实战演练:搭建环境并启动监听
工具安装与配置
Whistle 是一款基于 Node.js 实现的跨平台网络抓包调试工具,代码开源、功能强大且轻量化,同时具有丰富的中文文档,完全不用担心上手困难的问题。
关于安装,网上推荐的方法是先安装 Node.js 环境,然后在命令行使用 npm 安装对应的包。安装完成后,可以直接在命令行使用对应的命令启动和停止。
# 在全局安装 whistle
npm install -g whistle
# 若安装很慢,也可以使用淘宝镜像进行安装
npm install -g whistle --registry=https://registry.npm.taobao.org
# 安装完成后,使用 w2 命令进行启动,然后使用浏览器访问
w2 start
# 也可以指定 whistle 的监听端口
w2 start -p 8081
# 使用完毕后,使用 w2 命令停止实例
w2 stop
然而,官方提供了开箱即用的安装包,我们可以直接在 Github 上下载对应系统的安装程序。安装完成并启动后,程序界面如图所示(与在浏览器中运行的GUI一致)。
在搜集资料过程中,我注意到同样还有一些同类型的 Web 调试工具非常优秀,例如最经典的 Fiddler。同样,Burp Suite 也支持导出证书并设置代理进行监听。如果感兴趣的话,不妨接着探索这些工具的使用方法。
网络环境与代理配置
启动 Whistle 后,若想成功捕获到移动设备的流量,需要修改网络环境,使得流量先发送到计算机,然后再由计算机进行转发。
实现该目标的方法有很多,其中最快捷的是:使得电脑和手机处在同一 Wi-Fi 下,然后配置手机的代理设置,使其指向 Whistle 内置的代理。
我使用的监听端口为 18080
,电脑所在的地址为 192.168.31.30
,因此代理配置如图所示。
在配置完成后,使用手机访问网站,即可在 Whistle 界面观察到获取到的数据包。然而由于没有安装 CA 证书,此时无法获取加密的 HTTPS 连接。使用学校的教务系统(使用HTTP连接,现基本被弃用)进行测试,能够成功查看到连接的详细内容。
手机能够正常访问网络,则说明代理配置成功。
安装证书
在 Whistle 顶部栏单击 HTTPS
选项,启用 HTTPS 捕获功能,并使用手机扫描界面中的二维码,下载根证书。
证书安装过程如下所示。在安装过程中,时刻可见系统弹出的风险提示。
安装完毕后,使用 Whistle 即可捕获到 HTTPS 流量。
抓包并分析
使用手机浏览器访问豆瓣,并在 Whistle 中监听流量。如图所示,可以发现软件成功截获了豆瓣服务器的HTTP响应。同样,我们也可以在 Whistle 中设置特定的规则,从而篡改响应或进行重放攻击。具体操作方式可以参阅 Whistle 官方文档。
值得一提的是,笔者一开始使用的是移动版的 Firefox 浏览器,却在测试网页浏览时遭遇了失败:
大多数记录显示 captureError,并且火狐浏览器也弹出了风险提示——后来切换到夸克浏览器时才测试成功。
这说明火狐浏览器的确有更加完善的安全策略,可以避免该类中间人攻击。
尝试监听应用流量
在上述步骤中,我们成功捕获了 Web 请求的内容。在手机上运行各类应用,我们也可以尝试对各类应用的流量进行监听。
但此时出现了问题:大多数的应用浏览都无法捕获,显示 captureError
。
而最开始的“抢国补教程”中所展示的电商平台,是为数不多能捕获到具体信息的平台。
至于为什么会出现“捕获失败”的问题,下一小节将进行集中讨论。
3 讨论与总结
为什么会捕获失败?
即使我们添加了自签名的根证书,为什么仍然捕获不到多数应用的流量呢?
——事实上,我们现在能想到的方法,之前的安全人员都考虑过:安卓在 7.0 之后的版本中,引入了新的证书信任机制,默认不再信任用户添加的CA。
如果需要允许用户自安装证书,需要额外在应用配置文件中设置。因此在默认情况下,手机应用将不会信任我们添加的证书,从而拒绝连接。
想要打破这一局面,就需要对应用甚至系统做更深层次的改动。常见的方案有:
- 反编译应用 APK,修改对应参数后重新打包并安装,使其信任用户证书。
- 把我们的证书移动到系统 CA 证书目录。需要拥有系统 Root 权限。
当然,每个方案都不简单,单拎出来能开一篇新的文章了。更何况各大手机厂商都在收紧 Bootloader 的解锁权限,能够获取到 root 的手机本身就相当不易。
就算有的同学绞尽脑汁,打破了这一限制,有时会发现仍无法捕获到——部分对安全要求更高的应用使用了 SSL Pinning 技术。这一技术是专门用来防范中间人攻击的:服务器的证书和公钥直接存储到了客户端中,这保证了客户端只信任特定的服务器。
在这种情况下,就不得不对应用进行逆向操作,将其破解了。
这个方法能否用来抢票?
先说结论:非常困难。
即使我们使用自签名证书绕过了 TLS,监听到了各个应用的连接,在大多数情况下,这只是最原始的一层安全保护。在此基础上,各大厂商分别设置了自己的保护机制和策略,来阻止这类扰乱公平性、甚至可能对软件造成损害的非法操作。
在上一节中,我们的确抓到了目标电商平台的数据包,但稍作观察就能发现,它的请求内容都是经过混淆的,以 R4iSKKKK...
作为开头,并以 KKK...
和若干等号为结尾。这样就能有效避免用户篡改请求参数。以上述特征为关键词,可以搜索到相关混淆算法的解析过程,此处不再赘述。
除此之外,现今的大多数请求接口都会添加 Sign 签名标识,相当于对其他参数的校验字段。服务器在接收到请求后,会根据参数再计算一次 Sign 值,若校对错误,将会拒绝请求。因此若想修改参数,还需要对签名校验算法进行分析。
Sign 一般用于参数签名,用来验证数据的完整性和真实性,防止用户篡改参数、伪装、重放以及数据泄露。Sign 标识生成方法一般是是将密钥、时间戳、特殊字符、随机数等参数经过特定排序后使用某种加密算法进行加密,作为接口中的一个参数sign
来传递,也可以将sign
放到请求头中。
即使不对参数进行修改,直接进行捕获请求并重发,也很有可能因为时间戳和随机数无法对应上而导致请求失败。
在文章开头所提到的抢国补教程中,作者的成功案例,很可能是因为活动临时上线,没有设置复杂的校验逻辑。很多外卖优惠券和直播福利的派送活动也是同理。但在成熟的购票软件中(如铁路12306、大麦等),想要通过这类方式提升抢票成功几率几乎不可能。要真的能找到他们的漏洞并加以利用,光靠这个发展黑灰产都能大赚一笔了。这样的行为也具有很大的法律风险,希望大家遵纪守法,莫动歪念头。
结语
在这篇文章中,我们通过抢券的引子,介绍了“中间人攻击”这一常见的攻击手段,并对其背后的原理进行了解读。它的本质其实是对通信中数据的截获与篡改,而我们要想防御此类攻击,也不妨从基本的安全原理进行剖析——数据的机密性、完整性以及身份的识别与认证。从这些角度对症下药,就能够有效且高效地对攻击进行防范。
道高一尺,魔高一丈。从最初的明文传输,到 SSL 的问世以及后续的 TLS,安全技术就是在这样的不断对抗中逐渐发展,形成一道牢固的城墙,保护我们的通信安全和隐私安全。这种对抗与发展,在我看来正是信息安全的无穷魅力之处。
4 参考资料
- 传输层安全性协议 - 维基百科
- 一文读懂https中密钥交换协议的原理及流程
- 超好用的抓包工具——whistle的安装及使用
- 揭秘安卓应用抓包技术:绕过SSL Pinning和抓取HTTPS包的方法
- 实战:Frida 绕过 ssl pinning
- 安卓高版本安装系统证书 HTTPS 抓包 - 终极解决方案
- 某电商App sign 签名算法解析(六)- 奋飞安全
- 技术分享|微信小程序绕过sign签名思路
很少写知识科普向的博客文章,一不小心写太长了……非专业的朋友可能觉得太长且看不懂,懂行的大佬可能又觉得太啰嗦。

总之先致歉orz……之后我会好好考虑受众并控制篇幅再下笔的。