第一章 TLS/SSL 协议基础:历史、栈结构与握手概览

好,我们开始第一课。不把基础打牢,后面讲降级攻击你肯定听得云里雾里。我个人习惯,讲任何协议之前,先拉一条时间线——看看这东西是怎么长成今天这样的。

1.1 历史沿革:从 SSL 到 TLS 的三次“整容”

TLS 的前身是 Netscape 公司在 90 年代中期定出的 SSL 协议。第一版 SSL 1.0 压根没公开,因为内部测试发现安全漏洞太多。真正登上舞台的是 SSL 2.0(1995),但说实话,那玩意儿现在看就是个筛子:握手不认证、缺少消息完整性保护、还能被中间人强行降级到弱套件。我在一个老系统的抓包里见过一次 SSL 2.0 的 ClientHello,那一瞬间头皮发麻——赶紧让开发升级库去了。

1996 年 SSL 3.0 发布,补了 2.0 的坑,加了 ChangeCipherSpec、握手 HMAC、还有那个著名的 POODLE 漏洞的温床——CBC 模式填充校验。嗯,讲历史不是为了怀旧,而是告诉你:每个版本的致命弱点,后来都成了降级攻击的“子弹”。

1999 年 IETF 把 SSL 3.0 改了个名,叫 TLS 1.0(RFC 2246)。这是个微调版,主要是把 HMAC 算法从 SSL 的自定义方案换成了标准 HMAC。你想想看,换个名字就能让很多人觉得“这是新协议”——其实底层差别没你想得那么大。后来 TLS 1.1(2006)修了 CBC 模式 IV 可预测的问题,TLS 1.2(2008)引入了真正的灵活密码套件协商,以及 SHA-256 做默认 PRF。记得那时候我正好在做 HTTPS 性能优化,看到 1.2 支持 AEAD(比如 GCM)简直拍大腿——终于不用再跟 CBC 的 padding oracle 斗智斗勇了。

最近的大版本是 TLS 1.3(RFC 8446,2018),砍掉了 RSA 密钥交换、CBC 模式、静态 DH、压缩等一堆遗留垃圾,握手次数也从 2-RTT 降到 1-RTT(甚至 0-RTT)。但是呢,1.3 的推广速度没那么快,服务器上还挂着 1.2、1.1、甚至 1.0 的老配置。这就是降级攻击的温床。

核心领悟:攻击者不是非得打爆你的密码学算法——在握手阶段让你“自愿”选一个更弱的版本或套件,比直接破解 AES-256 划算得多。

1.2 协议栈结构:看看这个“洋葱”怎么切

很多人以为 TLS 就是握手 + 加密,其实它的协议栈分了好几层。我用一张表和一段代码来解释。

层级 子协议 核心职责 典型攻击面
记录层(Record Layer) —— 分片、压缩(可选)、MAC/加密、解封装 记录长度混淆、分片重组溢出
握手层(Handshake) ClientHello / ServerHello / Certificate / … 协商版本、密码套件、密钥交换、认证 降级攻击、版本回退、套件洗牌
告警层(Alert) warning / fatal 错误通知、关闭状态 告警注入、关闭延迟
修改密码规范层(ChangeCipherSpec) —— 标记后续消息使用新密钥 0-RTT 混淆、乱序注入
应用数据层(Application Data) HTTP / FTP / SMTP 等 受保护的上层数据 压缩泄密(CRIME/BREACH)

注意,握手层是整场战役的核心。攻击者想让你用 TLS 1.0 + RSA + CBC + SHA-1,就得在握手层做手脚。举个例子,我在一次渗透测试中,客户端明明支持 TLS 1.2,但服务端只回 1.0——当时抓包一看,中间设备(比如企业防火墙)把 TLS 1.2 的 ClientHello 直接截断了。那不是漏洞,是愚蠢策略配置问题。

// 一个简化版 TLS 1.2 记录层格式(十六进制示例)
ContentType: 0x16 (Handshake)
Version: 0x0303 (TLS 1.2)
Length: 0x00A3
Fragment: [Handshake message bytes...]

这个 5 字节头部(类型+版本+长度)后面跟着握手消息体。版本字段——嗯,这里要特别留意——就是攻击者篡改的对象。他们把 0x0303 改成 0x0301(TLS 1.0)或者干脆改成 0x0300(SSL 3.0),就看接收方会不会傻乎乎地接受。

1.3 握手流程概述:一次“加密相亲”

我习惯把 TLS 握手比作相亲:双方先打招呼亮条件(Hello),然后交换证明材料(Certificate),最后商量个共同喜欢的加密方式(Pre-Master Secret),结婚(双方都算出一个 Session Key),然后宣誓(Finished)。

下面这个流程图,浓缩了最经典的 RSA 密钥交换 + 双向认证 的主干步骤。咱们课程后续所有降级手法,基本都能在这张图上找到落刀点。

TLS 握手主流程(简化) 客户端 (Client) 服务端 (Server) ① ClientHello ② ServerHello + Certificate ③ ClientKeyExchange (PreMasterSecret) 计算密钥 计算密钥 ④ ChangeCipherSpec (Client) ⑤ ChangeCipherSpec (Server) ⑥ Finished (双方验证) 安全通道建立 / 应用数据开始 ❗ 降级攻击最常出现在步骤①~③:修改版本号、套件列表或密钥交换方式
避坑经验:我曾经在调试一个 SSL VPN 网关时发现,它的 TLS 实现直接信任了 ServerHello 中的版本字段,没有跟自己发出去的 ClientHello 中的最高版本做校验。结果一个中间人只需要把 ServerHello 改成 0x0301,整个连接就在用 TLS 1.0 跑了,客户端却以为自己用的是 1.2。这就是典型的 版本回退攻击 的入口。

1.4 为什么这门课要你先看基础?

你看,握手阶段里藏着这么多可操作的点:版本协商、密码套件列表、公钥证书、随机数、密钥交换参数……每一个字段都可能被攻击者改写成“弱化版”。更可怕的是,很多安全产品自带的“协议降级兼容”功能,反而成了帮凶。

举个例子:TLS 1.3 规定 ServerHello 里不能再出现旧版本字段,但实际部署中,有些负载均衡器为了兼容老客户端,刻意在握手扩展里塞了一个“旧版本回退指示符”。这个指示符不影响正常连接,但攻击者可以利用它绕过客户端对 1.3 的要求,强制走 1.2 或者更低。

后面的章节,我们会一步步拆解这些降级手法的精确检测方法。但今天这章你心里要有个底:TLS 握手的每一个字节,都不该被盲目信任。