尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

08:HTTPS 抓包的八类盲区——中间人也有看不透的东西

08:HTTPS 抓包的八类盲区——中间人也有看不透的东西 大家好,我是毛衣哥。上一期我们把 HTTP 扒光了,这一期来看看加了锁的 HTTPS 又是怎么被一步步拧开的。准备好瓜子,七步拆完。前七篇几乎都在说"中间人什么都能看到"。但这不是事情的全貌。如果你是开发者,你可能遇到过这种情况:Charles 装好证书配好代理,浏览器里的 HTTPS 全都能看到。但一打开某个 App——全乱了。什么都看不到。这不是你配置错了。是你的对手比你多走了一步。盲区一:Certificate Pinning(证书固定)这是最常见的"抓不到包"的原因。原理:普通的 TLS 校验:浏览器检查证书是否由受信任的 CA 签发 + 域名是否匹配 SAN → 通过。Certificate Pinning:App 代码里写死了"我只接受这个特定的证书(或这个公钥的哈希)"。OkHttpClient client = new OkHttpClient.Builder() .certificatePinner(new CertificatePinner.Builder() .add("dumpany.cn", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") .build()) .build();这行代码的意思是:访问 dumpany.cn 时,服务器发来的证书的公钥哈希必须等于AAAA...。即使系统信任了中间人的 CA,App 也不信任——因为中间人发的假证书的公钥哈希不是我代码里写死的那个。绕过难度:极高。iOS 端:需要越狱手机,或者用 Frida/Cycript 做运行时 hook,禁用 pinning 检查Android 端:可以用 Xposed + JustTrustMe 模块,或者重打包 App 替换 pinning 的公钥两者的核心问题都是:你需要修改 App 本身,然后重新签名——这个过程在未越狱的 iPhone 上几乎不可能真实案例:各大银行 App(招行、工行等)几乎全做了 Certificate Pinning微信的部分接口做了 pinning支付宝几乎所有金融类 App所以你要是想去抓银行 App 的包,只装 Charles 证书是不够的。要么用越狱机 + hook 工具,要么就别想了。盲区二:双向 TLS(mTLS)原理:正常 HTTPS:只有服务器发证书,客户端不用。双向 TLS:客户端也要发证书给服务器验证。TLS 握手流程(mTLS): ① ClientHello ② ServerHello + Certificate(服务器证书)+ CertificateRequest(服务器要求客户端也发证书) ③ ClientKeyExchange + Certificate(客户端证书)+ CertificateVerify(客户端签名) ④ 服务器验证客户端证书 → 如果无效,拒绝连接中间人能做的是冒充服务器(发假证书给客户端),但它能不能冒充客户端?不能——因为它没有客户端的私钥。即使中间人装了自己的 CA 能签发假服务器证书,但服务器要求的客户端证书它拿不出来。绕过难度:极高。你需要拿到 App 里内置的客户端证书和私钥这些通常在 App 的资源文件里或代码里硬编码,但通常是加密存储的,需要逆向工程提取真实案例:微服务架构中 Service Mesh(Istio)的默认通信方式部分高安全等级的企业内部系统苹果 App Store 的部分后端盲区三:应用层再加密原理:HTTPS 帮你防的是"传输途中被偷看"——但它不防服务器。TLS 解密之后,服务器看到的是明文的请求内容。有些应用不信任这个。它们在 TLS 之上再做一层加密——即使中间人解密了 TLS,看到的也是密文。比如 Signal 协议(WhatsApp、Signal 用的端到端加密):传输过程中(中间人视角): TLS 层 → 能解密 → 看到的是 Signal 协议的加密 payload,而非明文消息内容 Signal 层 → 没有对方的私钥 → 无法解密绕过难度:不可能。除非你有通信双方的端到端加密密钥。真实案例:WhatsApp(端到端加密)SignalTelegram 的秘密聊天iMessage盲区四:非代理感知的客户端原理:Charles 是通过系统代理来拦截流量的。但很多 App 的实现方式是:// Android 下绕过系统代理URLurl=newURL("https://dumpany.cn");HttpURLConnectionconn=(HttpURLConnection)url.openConnection(Proxy.NO_PROXY);不读取系统代理设置,或者直接使用Proxy.NO_PROXY。操作系统配的代理对它无效。绕过方法:你没办法通过"配代理"来解决这个问题。需要使用更底层的拦截方式:使用 VPN 模式抓包(创建一个本地 VPN 服务,接管所有流量)使用透明代理在路由器层面做重定向很多移动抓包工具(比如 Packet Capture、HttpCanary)就是用的 VPN 模式来绕过非代理感知的问题。盲区五:QUIC / HTTP/3原理:HTTP/3 跑在UDP上,而不是 TCP。传统的基于 TCP 的抓包工具(Charles、Fiddler 的代理模式)对 UDP 流量无能为力。QUIC 协议栈:UDP(传输层) → QUIC(内置 TLS 1.3 加密,比单独的 TLS 层更难插手) → HTTP/3(应用层)QUIC 自带加密,而且是跟 TLS 1.3 深度集成的——没有单独的 TLS 握手层可以给你"插一脚"。绕过方法:在 QUIC 连接建立阶段(首次连接时),如果中间人拦截了 ClientHello,可以尝试降级到 HTTP/2或者在系统层面禁用 QUIC(Chrome 的chrome://flags/#enable-quic里可以关掉)关掉之后 HTTP/3 的网站会自动降级到 HTTP/2(走 TCP),就可以正常抓了盲区六:HPACK 压缩(HTTP/2 的头部压缩)严格来说这不是"抓不到",是"抓到了但看不懂"。HTTP/2 使用 HPACK 压缩请求头。你在抓包工具的界面上看到的可能是::method: GET :path: /api/users :scheme: https :authority: dumpany.cn但实际在 TCP 流里,这些头部经过了 HPACK 压缩——使用了静态 Huffman 编码和动态表。抓包工具需要完整实现 HPACK 解压缩才能展示 HTTP/2 请求头。如果工具不支持(比如老旧版本的 tcpdump),你看到的就是一堆压缩后的二进制内容。Wireshark 和 Charles 都已经支持 HPACK 解压缩,所以这不是个大问题。盲区七:WebSocket 的掩码(Masking)原理:WebSocket 协议规定:客户端发给服务器的帧必须加掩码(Mask)。掩码是一个 4 字节的随机值,对 payload 做 XOR 运算:客户端要发:hello 掩码(随机生成):0x37 0xfa 0x21 0x5d 加密(XOR):0x37⊕0x68=0x5f, 0xfa⊕0x65=0x9f, … 发送的实际数据:0x5f 0x9f 0x42 0x
返回列表