目标
对于端到端加密,HTTPS ,我们经常听到一些都市传说,如 HR 们圆桌分析员工的 WX 聊天记录,或者"员工离职倾向分析"这种软件,大家当然都好奇这些是怎么实现的,prying eyes 知道我的访问网站,但知道我账号密码吗(聊天记录)?它的能力边界是怎样的?公司让我手机电脑装 Root CA,是不是能审查我所有流量了?带着这些问题,我们来更深入的了解 HTTPS 和中间人攻击。
HTTPS 请求完整流程及中间人切入点
请求 github.com
- DNS 查询,nslookup github.com => 20.205.243.166
- 对 20.205.243.166 建立 TCP 会话(三握)
- TLS 会话,客户端验证 CA 得到可信服务端公钥,非对称加密,交换 Client random + Server random + Premaster => session key
- HTTP 通信,使用 session key 对称加密=>端到端加密=>传输内容安全
中间人想审查客户端的网络请求,有以下方式
- DNS 污染,传统 DNS 查询为明文 ,中间人记录(审查)特定域名的 DNS 查询行为,如 github.com
- 手抄 IP , 中间人知道特定域名对应的 IP 地址,如 20.205.243.166,放入黑名单阻断 TCP 连接
- TLS 漏洞,低版本的握手过程会明文暴露访问的域名 ,中间人从而记录或阻断 HTTPS 连接
- 抓包软件,即破除 TLS 的信任链,从而破除端到端加密,直接审查 HTTP 传输内容
123是现实世界最常用的方式,4是被很多人误解的方式。
2 手抄 IP 这里简单总结下。针对 IP 黑名单,开发时我们知道反代隐藏服务端 IP,正代隐藏客户端 IP,无论正代反代,客户端都对中间人隐藏了真正目标的 IP ,从而突破了黑名单;另外 IPv6 也可以突破 IP 黑名单,总之我们知道 IP 黑名单也是审查的重要实现方式之一,但它和端到端加密无关,所以本文不过多分析。
HTTPS 与端到端加密
什么是 E2EE
端到端加密 (E2EE) 是一种消息传递类型,它使消息对所有人保持私密,包括消息传递服务。使用 E2EE 时,消息仅在发送消息的人和接收消息的人面前以解密形式出现。发送者是对话的一个"端",而接收者是另一个"端";因此得名"端到端"。
除了客户端和服务端,通信的信息对所有中间人加密,为端到端加密。理想中的端到端加密可以防止任何中间人攻击,对中间人而言请求的所有信息都被加密。
理论与现状
理论和现状的差距总会带给人迷思,墙就不说了,我们也知道公司有办法审计我们的网络行为。这种现状容易使人想当然认为端到端加密就是扯淡,从而对其中一些细节产生错误认知,比如 "公司让我手机信任了自签的 Root CA ,是不是中间人就能窥探我全部 TLS 流量了" 。希望下文能渐进式回答这个问题。
TLS 握手
DNS 查询完成,TCP 连接建立后,进行 TLS 握手:

- Clent hello (明文): 客户端支持 TLS 版本(中间人可能由此降级攻击)、密码套件(加密方法)、Client random 值、拓展字段 RFC 6066 (包括 SNI :访问网站的域名,由于明文,会被中间人获取)
- Server hello : CA 证书(内容包含服务端公钥)、服务端选中的加密方法、Server random 值
- 客户端 CA 证书验证,确认公钥未被篡改
- 客户端生成 Premaster secret(预主秘钥),用公钥加密,传送给服务端,服务端私钥解密
- 两端此时同有 Client random + Server random + Premaster => 生成 session key ,客户端发送 "finished" 消息,服务端也发 "finished", 消息用 session key 加密
- 握手完成,后续 HTTP 用 session key 对称加密
为什么有 SNI (Server Name Indication)
可见,TSL 握手中 Client hello 发送的 SNI ,和明文的 DNS 查询一样暴露了访问域名,是中间人最常用的两个抓手,它为什么存在?
IP 为网络层协议,对应一台机器,可以部署多个域名服务。因而客户端需要先告诉机器访问哪个域名(SNI 字段),从而服务端 Server hello 返回正确的 CA 证书。否则无法返回正确证书,连接中断。
回到对中间人攻击的分析,所有联网的内容都可能被中间人伪造,因此最重要的点在于 CA 证书验证。
CA 证书链验证

当前网站 CA 有待签名内容 Content ,包含服务端公钥及其他字段,有数字签名 Signature。签发此 CA 的机构称为 Issuer ,一般为二级 CA :
- Content 明文不变 => 对 Content 生成内容摘要 Hash , hashContent 明文不变
- Issuer 用私钥对 hashContent 加密生成 Signature 明文赋予子 CA
- 客户端验证网站 CA,从 issuer 字段找到父级 CA (Issuer),用二级 CA 明文公钥 解密 Signature 得到 hashContent, 和自己计算的 hashContent 对比,若一致,则信任链:如果 Issuer CA 可信 => 当前网站 CA 可信 => Content 未被篡改,公钥可信

- Issuer CA 是否可信,要问父 Issuer,依然使用 Issuer 字段找父 CA,递归执行上述流程,直到找到 Root CA ( 系统或APP内置于本地并信任 ),如图:

一切网络获取的东西都可能被中间人篡改,所以信任链的起点在本地 ,即操作系统内置信任的 Root CA。因此所有抓包工具的第一步就是给目标设备安装 Root CA 并主动信任,之后才能作为中间人解密 HTTPS。
第一层:抓包工具完全解析 HTTPS
根据上文,想对 HTTPS 达成中间人攻击,必须成功篡改目标网站的公钥为自己的 => 篡改目标站点的 CA => 用自己的 Root CA 直接签发目标站点 CA,跟随 demo 代码实现 HTTPS 中间人
自签 Root CA 和域名 CA ,类似于生成秘钥对
系统安装 Root CA
运行 HTTPS proxy,访问 github, 中间人当场签发 github.com 的 CA 并替换页面内容,注意页面 url 前的绿锁未见异常,证明信任链的起点在本地 Root CA
点开小绿锁,可以看见 CA 被替换
可见它的局限性很明显:
- 一般只用于开发,抓包工具使用,审计需求实际上没必要完全解析 HTTPS
- 应用程序可以写死只信任内置的 CA (如 WX ),不信任系统 CA ,则此方法无效
- 即使真有公司用这种方式审计,当你访问 BOSS 直聘时能直接看到证书被替换了,想必也不会做什么操作了,丧失了审计的效果
应对方式:查看当前域名 CA 是否被替换即可,对于 WX 这种应用程序,往往写死只信任内置 CA,所以不用担心 HTTP 被解析。同时可以解答疑问,公司让手机信任的 CA,其实真的只是为了认证 WIFI 内网而已,无法窥探流量,因为真这么做立马会被发现。
HTTP 的中间人攻击
端到端加密对于互联网的正常运行是必要的 ,因为一旦 HTTP 内容被解析,最恶劣的内容插入式中间人攻击就一定会发生,HTTPS 未普及时运营商亲自中间人攻击的好日子就像昨天一样:
即使今天 HTTPS 普及了,这种中间人攻击仍然无处不在,这有个奇妙的案例,前端网页在某些边缘地区被随机劫持,在中心城市页面正常,在边远城市页面被中间人插脚本弹框广告了。它的真实原因是网站接入的 CDN 服务商在边缘节点为了节省成本,边缘地区 CDN 回源时用了 HTTP,没用 HTTPS, 从而导致了中间人攻击。
在应用层值得一提的是,即使全链路 HTTPS ,传输文件时也不一定有加密,可以搜索关键词" 国内多款云盘存在安全隐患上传文件并未真正加密":
为什么加密重要?因为即使 HTTPS,但应用在实现时传输文件未加密,假如连入存在审计设备的 WIFI ,则上传文件时会被中间人审计设备直接捕获。
为什么"离职倾向分析" 软件界面截图上有员工上传的简历?因为简历也是文件,上传时不一定加密,会被中间人窥探。WX 发图片语音视频时也有类似情况。
离职倾向分析如何实现
上图的产品我没有找到说明页,无从得知它是什么类型,它可能是个端的应用,定期扫描浏览器历史记录文件,定时屏幕截图并上传,那就完全没中间人攻击什么事了。所以这里挑一个网关类型的相似产品来分析下,下面内容来自审计设备 WCG380 说明页面
系列产品提供详细、清晰、易用的日志特性,可以全面记录审计用户上网行为、使用流量、访问网站、所用终端系统及设备类型平台等信息;日志支持定制化过滤器,可根据IP地址、认证用户、访问应用、访问URL、发帖内容等要素进行搜索,让事后审计省时省力;可支持对HTTPS、邮箱类解密策略的配置。
HTTPS 解密策略指的是真正的 TLS 审计,即上文提过的抓包工具模式,内置系统 Root CA 直接签发对应域名的伪造证书,获取完整 HTTP 内容的中间人攻击,较为少见,这种情况 HTTP 明文了,自然能审查"发帖内容"。
系列产品控制层面不再局限对网络应用的阻断,更能深入识别应用的内置动作。例如对QQ的控制力度不仅仅是登录动作,更可识别到收文件、发文件、语音、视频等动作,对微信也可识别控制多达11种行为动作。
指的是应用程序可能不信任系统 Root CA,上面招数不管用,但传输文件,图片时不一定加密,仍然可以识别特征动作。
总结
HTTPS 可以保证传输内容的安全性。只要你看到目标网站 CA 没被替换,就至少能保证 HTTP 传输内容是安全的 ,不会被中间人窥探,是可靠的端到端加密,完全解析 HTTPS 的场景只常见于开发抓包,并不常见于审计。
因为审计功能,比如审计员工访问招聘网站这种其实并不需要解析 HTTP 内容:访问了多少次招聘网站?访问网站多长时间?只需要判断连接的目标域名就行,即 DNS 明文 + SNI 明文已经暴露了目标域名,加上 TCP 连接时间就能满足需求。
而假如我们堵上了上述漏洞呢? DNS 使用新的加密传输, TLS 升级版本堵住了 SNI 漏洞,中间人又将如何应对?真正的端到端加密实现了吗?本文已经过长,这些就留到下篇再分析了。
写文章本身也是一个学习的过程,也请读者能指出文章中的疏忽错漏之处。如果本文对你有所帮助,欢迎点赞收藏。