国密 TLS 降级攻击原理与防御:从协商机制到 KCI/FREAK 漏洞的深度解析

密码学 · 2026-07-13 · 14 阅读

前言

在 TLS 握手阶段,客户端与服务端协商协议版本和密码套件。这个"协商"过程的开放性正是降级攻击的根源:中间人可以篡改握手消息,迫使双方选择弱密码套件或低版本协议。

国际 TLS 的降级攻击已有数十年历史(POODLE、FREAK、Logjam、DROWN 等),TLS 1.3 通过移除可逆协商机制大幅缓解了这一问题。但国密 TLS仍然基于 TLS 1.2 协商模式(GM/T 0024-2014),且采用双证书自适应协商机制,引入了额外的降级面。

本文将从攻击者视角系统讲解降级攻击原理,然后从建设者视角给出防御方案。

一、TLS 协商机制回顾

1.1 标准 TLS 1.2 握手

1.2 攻击窗口:ClientHello 明文传输

ClientHello 和 ServerHello 在 TLS 握手阶段是明文传输的。这意味着中间人可以:

  • 篡改 supported_versions:替换高版本为低版本
  • 重排 cipher_suites:将弱密码套件移到前面
  • 删除强密码套件:从列表中移除所有强选项
  • 回退请求:在正常的握手请求中附加降级标志

二、版本降级攻击 (Version Downgrade)

2.1 攻击原理

版本降级攻击迫使客户端和服务端回退到存在已知漏洞的早期协议版本(SSL 3.0、TLS 1.0、TLS 1.1)。

攻击步骤

  • 受害者客户端发送 ClientHello,声明支持 TLS 1.3 + TLS 1.2
  • 中间人将 ClientHello 中的 legacy_version 字段改为 0x0301(TLS 1.0)
  • 如果不安全的服务器也支持 TLS 1.0,则响应 TLS 1.0 握手
  • 客户端发现版本回退时,标准兼容的客户端应发送 unexpected_message alert,但部分客户端为了兼容性会默默接受
  • 双方使用 TLS 1.0 完成握手,利用已知漏洞(BEAST、Lucky13、POODLE)解密流量

2.2 SSLv3 POODLE 降级实例

POODLE (Padding Oracle On Downgraded Legacy Encryption) 是版本降级攻击的经典案例:

CODE
1. 客户端尝试 TLS 1.3
2. 中间人拦截,迫使降级到 SSLv3
3. SSLv3 使用 CBC 模式,MAC-then-Encrypt 结构
4. 利用 padding 验证的差异,逐字节解密密文
5. 平均 256 次请求可解密 1 字节

2.3 TLS 1.3 的防降级机制

TLS 1.3 在 ServerHello 中加入了防降级保护:

C
// TLS 1.2 ServerHello.random 的最后 8 字节
// 如果服务器实际选择的 TLS 1.2:
static const char TLS_1_2_DOWNGRADE_GUARD[8] = {
    0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x01
};

// 如果 TLS 1.1 或更低:
static const char TLS_1_1_DOWNGRADE_GUARD[8] = {
    0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x00
};

客户端在收到 ServerHello 时会检查这 8 个字节,如果发现固定值 DOWNGRD,则判定为降级攻击并终止连接。

三、密码套件降级攻击

3.1 FREAK (Factoring RSA Export Keys)

FREAK 利用的是 1990 年代美国出口管制遗留的导出级密码套件(密钥长度限制在 512 位)。

攻击流程

CODE
1. 客户端发送 ClientHello,密码套件列表包含 EXPORT-RSA(为兼容旧服务器)
2. 中间人将完整的密码套件列表替换为仅含 EXPORT-RSA 的列表
3. 服务端选择 EXPORT-RSA,生成 512 位临时 RSA 密钥
4. 中间人截获服务端证书,分解 512 位模数 N
   (成本:约 100 美元 AWS 计算费,7 小时计算时间,来源:CII-2015-0079 漏洞研究报告)
5. 用分解出的私钥解密 pre-master secret

修复服务端配置

PYTHON
# 禁用所有导出密码套件
import ssl

ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.set_ciphers("DEFAULT:!EXPORT:!aNULL:!eNULL:!LOW:!DES:!RC4:!MD5")
ctx.minimum_version = ssl.TLSVersion.TLSv1_2

3.2 Logjam (DH 降级)

与 FREAK 原理相同,但针对 Diffie-Hellman 密钥交换:

  • 迫使服务端使用 512 位导出级 DH 参数
  • 预计算阶段:对特定 512 位 DH 群做约 768 次计算(成本:约数万美元一次性)
  • 在线阶段:对每个握手秒级破解
  • 几乎所有支持 DHE_EXPORT 的服务器都受影响
关键配置

NGINX
# 禁用所有导出级 DH 参数
openssl dhparam -out /etc/ssl/dhparam.pem 2048
ssl_dhparam /etc/ssl/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;

四、KCI 攻击 (Key Compromise Impersonation)

4.1 KCI 攻击原理

KCI 是一种利用签名密钥泄露进行跨协议身份伪造的攻击。如果攻击者获取了服务端的签名私钥(RSA/SM2/EdDSA),则可以:

CODE
1. 已有:服务端 RSA 私钥 d
2. 攻击者冒充任意客户端向服务端证明自己是"合法客户端"
3. 原理:在不提供客户端证书的密码套件中,RSA 密钥交换允许
   客户端用服务端公钥加密 pre-master secret
4. 攻击者有服务端私钥 d,可以解密握手过程中的 pre-master secret
5. 服务端不知道客户端是谁,但攻击者可以正确计算会话密钥,冒充服务端与任何客户端通信

影响范围:所有使用仅签名密钥不提供密钥建立的密码套件:

  • TLS_RSA_WITH_AES_256_GCM_SHA384:受 KCI 影响
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384不受影响(ECDHE 绑定临时密钥)
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384不受影响

4.2 KCI 防御:ECDHE 优先

防御原则:强制使用提供完美前向保密(PFS)的 ECDHE 密码套件。

预期输出

CODE
KCI 风险: HIGH
受影响套件: ['TLS_RSA_WITH_AES_256_GCM_SHA384', 'TLS_RSA_WITH_AES_128_CBC_SHA']
安全套件: ['TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384']

五、国密 TLS 的特殊降级风险

5.1 国密 SSL VPN 的技术路线

国密 TLS(GM/T 0024-2014 / GM/T 0024-2023)在国际 TLS 1.2 框架基础上,新增了:

  • 国密密码套件ECC-SM2-WITH-SM4-SM3 (= 0xE0,0x13)
  • 双证书机制:同时提供 SM2 签名证书 + SM2 加密证书
  • 自适应协商:根据客户端能力选择国密套件或国际套件
国密 TLS 握手的简化流程:

5.2 国密 TLS 特有的降级攻击面

#### 5.2.1 国密→国际降级 (GM2International)

攻击目标:迫使本可使用国密套件的通信回退到国际套件(RSA/AES),规避国密防护。

攻击步骤

  • 客户端支持国密(发送 ECC-SM2-WITH-SM4-SM3 + 国密 Server Name Extension)
  • 中间人在 ClientHello 中删除国密密码套件,仅保留国际套件
  • 服务端选择国际套件(如 ECDHE-RSA-AES256-SHA384)
  • 加密通道建立使用 RSA/AES,国密的 SM2/SM4 保护完全旁路
危害程度:严重。对于密评场景,国密算法的缺失直接导致合规不通过。

防御

#### 5.2.2 国际→国密反向降级攻击

攻击目标:迫使仅支持国际 TLS 的客户端降级到已被弃用的弱密码套件(如 DES-CBC3-SHA)。

攻击步骤

  • 客户端发送 ClientHello,密码列表包含 DES-CBC3-SHA
  • 服务端优先选择 TLS 1.2 + DES-CBC3-SHA
  • 攻击者利用 DES 弱密钥暴力破解
防御

#### 5.2.3 双证书架构下的降级盲区

国密 TLS 的双证书包含:

  • 签名证书(SM2):用于服务端身份认证(签名握手摘要)
  • 加密证书(SM2):用于加密 pre-master secret
降级场景

CODE
1. 客户端使用国密,发送 ClientHello(含国密扩展)
2. 服务端返回 ServerHello,选择 ECC-SM2-WITH-SM4-SM3
3. 服务端发送两张 SM2 证书(签名 + 加密)
4. ⛔ 攻击点:中间人篡改证书链
   - 替换 SM2 加密证书为 RSA 兼容证书
   - 客户端未严格校验加密证书的算法 OID
   - 用 RSA 公钥加密 pre-master → 被中间人 RSA 私钥解密
5. KCI 攻击生效:攻击者拥有 RSA 私钥 → 解密通信

防御:客户端必须验证加密证书的算法 OID 为国密 SM2(1.2.156.10197.1.301),而非 RSA。

六、实战:TLS 降级漏洞检测脚本

七、服务端降级防护配置

7.1 Nginx 国际+国密双证书防降级配置

7.2 Apache + mod_ssl 防降级配置

八、总结

攻击类型攻击原理影响协议防御措施
版本降级 (Version Downgrade)篡改 ClientHello 版本字段SSLv3-TLS 1.1强制 TLS 1.2+、HSTS
密码套件降级 (Cipher Suite Downgrade)重排/删除密码套件列表TLS 1.2 及以下ECDHE 优先、禁用弱算法
FREAK强制使用导出级 RSA 512 位TLS (有导出套件时)禁用所有 EXPORT 密码
Logjam强制使用导出级 DH 512 位TLS (有导出套件时)禁用 DHE_EXPORT,2048+ 位 DH
KCI签名私钥泄露导致身份冒充TLS(仅 RSA 密钥交换)强制 ECDHE,PFS 优先
POODLE利用 SSLv3 CBC padding 验证SSLv3禁用 SSLv3、TLS_FALLBACK_SCSV
CRIME/BREACH利用 TLS/HTTP 压缩 + 旁路TLS(启用压缩)禁用 TLS 压缩
国密 TLS 特别提示
  • 国密双证书架构下需额外校验加密证书的 SM2 OID
  • 设置国密套件优先级,防止被国际套件替换
  • GM/T 0024-2023 对密码套件的严格限定已涵盖部分降级防护
  • 密评检查会验证服务端是否禁用了弱密码套件和早期 TLS 版本

参考来源

  • RFC 7568《Deprecating Secure Sockets Layer Version 3.0》
  • RFC 8996《Deprecating TLS 1.0 and TLS 1.1》
  • RFC 8446《The Transport Layer Security (TLS) Protocol Version 1.3》
  • RFC 5746《Transport Layer Security (TLS) Renegotiation Indication Extension》
  • GM/T 0024-2014《SSL VPN 技术规范》
  • GM/T 0024-2023《SSL VPN 技术规范》(新版)
  • CVE-2015-0204(FREAK)
  • CVE-2015-4000(Logjam)
  • CVE-2014-3566(POODLE)