国密 TLS 降级攻击原理与防御:从协商机制到 KCI/FREAK 漏洞的深度解析
前言
在 TLS 握手阶段,客户端与服务端协商协议版本和密码套件。这个"协商"过程的开放性正是降级攻击的根源:中间人可以篡改握手消息,迫使双方选择弱密码套件或低版本协议。
国际 TLS 的降级攻击已有数十年历史(POODLE、FREAK、Logjam、DROWN 等),TLS 1.3 通过移除可逆协商机制大幅缓解了这一问题。但国密 TLS仍然基于 TLS 1.2 协商模式(GM/T 0024-2014),且采用双证书自适应协商机制,引入了额外的降级面。
本文将从攻击者视角系统讲解降级攻击原理,然后从建设者视角给出防御方案。
一、TLS 协商机制回顾
1.1 标准 TLS 1.2 握手
Client Server
| |
| ClientHello |
| [supported_versions, cipher_suites] |
|------------------------->| |
| | 选择: TLS 1.2 |
| | 选择: ECDHE-RSA-AES256 |
| ServerHello | |
| [version, cipher_suite] | |
|<-------------------------| |
| Certificate |
| ServerKeyExchange |
| ServerHelloDone |
|<-------------------------| |
| ClientKeyExchange |
| [ChangeCipherSpec] |
| Finished |
|------------------------->| |
| [ChangeCipherSpec] |
| Finished |
|<-------------------------| |
| < Application Data > |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) 是版本降级攻击的经典案例:
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 中加入了防降级保护:
// 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 位)。
攻击流程:
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修复服务端配置:
# 禁用所有导出密码套件
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_23.2 Logjam (DH 降级)
与 FREAK 原理相同,但针对 Diffie-Hellman 密钥交换:
- 迫使服务端使用 512 位导出级 DH 参数
- 预计算阶段:对特定 512 位 DH 群做约 768 次计算(成本:约数万美元一次性)
- 在线阶段:对每个握手秒级破解
- 几乎所有支持 DHE_EXPORT 的服务器都受影响
# 禁用所有导出级 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),则可以:
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 密码套件。
# KCI 安全检测脚本
def check_kci_vulnerability(cipher_suites: list) -> dict:
"""
检查密码套件列表是否存在 KCI 漏洞
"""
kci_vulnerable = []
kci_safe = []
for suite in cipher_suites:
if "RSA" in suite and "DHE" not in suite and "ECDHE" not in suite:
# 纯 RSA 密钥交换(无 DHE/ECDHE)→ KCI 受影响
kci_vulnerable.append(suite)
elif "ECDHE" in suite or "DHE" in suite:
kci_safe.append(suite)
return {
"vulnerable": kci_vulnerable,
"safe": kci_safe,
"kci_risk_level": "HIGH" if kci_vulnerable else "LOW",
"recommendation": "启用 ECDHE/DHE 优先,禁用仅 RSA 密钥交换的密码套件"
}
# 测试
ciphers = [
"TLS_RSA_WITH_AES_256_GCM_SHA384", # ← KCI 漏洞
"TLS_RSA_WITH_AES_128_CBC_SHA", # ← KCI 漏洞
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", # ← 安全
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", # ← 安全
]
result = check_kci_vulnerability(ciphers)
print(f"KCI 风险: {result['kci_risk_level']}")
print(f"受影响套件: {result['vulnerable']}")
print(f"安全套件: {result['safe']}")预期输出:
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 加密证书
- 自适应协商:根据客户端能力选择国密套件或国际套件
Client Server
| |
| ClientHello [国密扩展 + 国际套件] |
|---------------------------------------------->|
| 如果服务端优先国密: |
| ServerHello [选择 ECC-SM2-WITH-SM4-SM3] |
| [SM2-Sign-Cert + SM2-Encr-Cert] |
| ServerKeyExchange |
|<----------------------------------------------|
| [客户端使用 SM2 加密证书公钥加密 pre-master] |
| [客户端用国密扩展字段验证服务端 SM2 证书] |
| ClientKeyExchange |
|---------------------------------------------->|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 保护完全旁路
防御:
def enforce_gm_cipher_in_client_hello(client_hello_data: bytes) -> bool:
"""
检查 ClientHello 中是否包含国密密码套件
返回 True 表示合规(包含国密套件),False 表示不合规
"""
# 国密密码套件 ID (GM/T 0024-2014)
GM_CIPHER_SUITES = {
0xE011, # ECC-SM2-WITH-SM4-SM3
0xE013, # ECC-SM2-WITH-SM4-SM3 (旧标识)
0xE001, # ECDHE-SM2-WITH-SM4-SM3
0xE003, # ECDHE-SM2-WITH-SM4-SM3 (旧标识)
}
# 解析 ClientHello 的密码套件列表
# 注意:此处为简化示例,实际需解析 TLS records
# 完整的 ClientHello 解析较复杂,生产中使用 OpenSSL/wireshark
# 简化的检查逻辑
cipher_bytes = client_hello_data # 需从 TLS record 中提取
found_gm_suite = False
# 在 ClientHello 中搜索国密套件 ID
for i in range(0, len(cipher_bytes) - 1):
suite_id = (cipher_bytes[i] << 8) | cipher_bytes[i+1]
if suite_id in GM_CIPHER_SUITES:
found_gm_suite = True
break
return found_gm_suite#### 5.2.2 国际→国密反向降级攻击
攻击目标:迫使仅支持国际 TLS 的客户端降级到已被弃用的弱密码套件(如 DES-CBC3-SHA)。
攻击步骤:
- 客户端发送 ClientHello,密码列表包含 DES-CBC3-SHA
- 服务端优先选择 TLS 1.2 + DES-CBC3-SHA
- 攻击者利用 DES 弱密钥暴力破解
def audit_server_cipher_selection(openssl_cipher_string: str) -> dict:
"""
审计 OpenSSL 密码字符串是否包含弱密码
Returns:
{"weak": [...], "safe": [...], "risk_score": int 0-100}
"""
WEAK_PATTERNS = [
'DES', 'RC4', '3DES', 'MD5', 'NULL', 'EXPORT', 'anon',
'RC2', 'IDEA', 'SEED'
]
SAFE_PATTERNS = [
'AES-256-GCM', 'AES-128-GCM', 'CHACHA20-POLY1305',
'SM4-GCM', 'SM4-CCM', 'AES-256-CCM'
]
ciphers = openssl_cipher_string.split(':')
weak = []
safe = []
for c in ciphers:
c_upper = c.upper()
if any(p in c_upper for p in WEAK_PATTERNS):
weak.append(c)
elif any(p in c_upper for p in SAFE_PATTERNS):
safe.append(c)
risk = min(100, len(weak) * 20 + len(safe) * 0)
return {
"weak": weak,
"safe": safe,
"risk_score": risk,
"recommendation": "移除所有弱密码套件" if weak else "无弱密码套件"
}
# 测试
result = audit_server_cipher_selection(
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DES-CBC3-SHA"
)
print(f"弱套件: {result['weak']}")
print(f"风险分数: {result['risk_score']}/100")#### 5.2.3 双证书架构下的降级盲区
国密 TLS 的双证书包含:
- 签名证书(SM2):用于服务端身份认证(签名握手摘要)
- 加密证书(SM2):用于加密 pre-master secret
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。
def verify_gm_encryption_cert(cert_der: bytes) -> bool:
"""
验证证书是否为 SM2 加密证书(国密 OID: 1.2.156.10197.1.301)
"""
from cryptography import x509
from cryptography.x509.oid import ObjectIdentifier
SM2_OID = "1.2.156.10197.1.301"
cert = x509.load_der_x509_certificate(cert_der)
# 检查公钥算法 OID
pubkey_oid = cert.public_key_algorithm_oid.dotted_string
if pubkey_oid != SM2_OID:
return False
# 检查密钥用法:应包含 keyEncipherment 或 keyAgreement
try:
ku = cert.extensions.get_extension_for_oid(
x509.oid.ExtensionOID.KEY_USAGE
).value
if not (ku.key_encipherment or ku.key_agreement):
return False
except x509.ExtensionNotFound:
return False
return True六、实战:TLS 降级漏洞检测脚本
#!/usr/bin/env python3
"""TLS 降级攻击自动化检测工具"""
import socket
import ssl
import struct
from datetime import datetime
from typing import Optional, Tuple
class TLSAuditTool:
"""TLS 安全审计工具"""
def __init__(self, host: str, port: int = 443, timeout: int = 10):
self.host = host
self.port = port
self.timeout = timeout
self.results = {
"host": host,
"port": port,
"timestamp": datetime.utcnow().isoformat(),
"version": None,
"cipher": None,
"vulnerabilities": [],
"recommendations": []
}
def probe_version(self, target_version: ssl.TLSVersion) -> bool:
"""
探测服务端是否支持指定 TLS 版本
"""
try:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
ctx.minimum_version = target_version
ctx.maximum_version = target_version
with socket.create_connection((self.host, self.port), self.timeout) as sock:
with ctx.wrap_socket(sock, server_hostname=self.host) as ssock:
return True
except (ssl.SSLError, OSError):
return False
def check_version_vulnerabilities(self) -> list:
"""检查版本相关漏洞"""
vulns = []
# 检查 TLS 1.0 / 1.1(已废弃)
if self.probe_version(ssl.TLSVersion.TLSv1):
vulns.append({
"id": "TLSv1.0",
"severity": "HIGH",
"description": "服务端支持 TLS 1.0,存在 BEAST/Lucky13 攻击风险"
})
if self.probe_version(ssl.TLSVersion.TLSv1_1):
vulns.append({
"id": "TLSv1.1",
"severity": "MEDIUM",
"description": "服务端支持 TLS 1.1,建议强制 TLS 1.2+"
})
return vulns
def check_cipher_vulnerabilities(self) -> list:
"""检查密码套件降级漏洞"""
vulns = []
try:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
with socket.create_connection((self.host, self.port), self.timeout) as sock:
with ctx.wrap_socket(sock, server_hostname=self.host) as ssock:
cipher = ssock.cipher()
self.results["cipher"] = cipher
if cipher:
cipher_name = cipher[0]
# 检查导出密码
if "EXPORT" in cipher_name.upper():
vulns.append({
"id": "FREAK",
"severity": "CRITICAL",
"description": f"使用导出级密码套件: {cipher_name}"
})
# 检查匿名 DH
if "anon" in cipher_name.lower() or "ADH" in cipher_name:
vulns.append({
"id": "anonDH",
"severity": "CRITICAL",
"description": f"支持匿名 Diffie-Hellman 密码套件"
})
# 检查 KCI 漏洞(无 DHE/ECDHE)
if "_RSA_" in cipher_name and "_DHE_" not in cipher_name and "_ECDHE_" not in cipher_name:
vulns.append({
"id": "KCI",
"severity": "MEDIUM",
"description": f"密码套件 {cipher_name} 受 KCI 攻击影响"
})
# 检查弱对称算法
if any(w in cipher_name for w in ["DES", "RC4", "NULL"]):
vulns.append({
"id": "weak-cipher",
"severity": "HIGH",
"description": f"使用弱对称加密算法: {cipher_name}"
})
# 检查压缩(CRIME/BREACH)
if ssock.compression() is not None:
vulns.append({
"id": "CRIME",
"severity": "HIGH",
"description": "启用 TLS 压缩,存在 CRIME/BREACH 攻击风险"
})
except Exception as e:
vulns.append({
"id": "connection-error",
"severity": "INFO",
"description": f"连接失败: {e}"
})
return vulns
def check_certificate(self) -> dict:
"""检查证书安全性"""
cert_info = {"issues": []}
try:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_default_certs()
with socket.create_connection((self.host, self.port), self.timeout) as sock:
with ctx.wrap_socket(sock, server_hostname=self.host) as ssock:
cert = ssock.getpeercert(binary_form=True)
if cert:
from cryptography import x509
x509cert = x509.load_der_x509_certificate(cert)
# 检查签名算法
sig_alg = x509cert.signature_algorithm_oid
if "md5" in sig_alg.dotted_string or "sha1" in sig_alg.dotted_string:
cert_info["issues"].append({
"id": "weak-sig-alg",
"severity": "MEDIUM",
"description": f"证书使用弱签名算法: {sig_alg.dotted_string}"
})
# 检查有效期
from datetime import datetime
if x509cert.not_valid_after < datetime.utcnow():
cert_info["issues"].append({
"id": "expired-cert",
"severity": "HIGH",
"description": "证书已过期"
})
except Exception as e:
cert_info["issues"].append({
"id": "cert-check-fail",
"severity": "INFO",
"description": f"证书检查失败: {e}"
})
return cert_info
def run_full_audit(self) -> dict:
"""执行完整审计"""
print(f"[*] 开始审计 {self.host}:{self.port}")
# 1. 版本检查
vulns = self.check_version_vulnerabilities()
vulns.extend(self.check_cipher_vulnerabilities())
# 2. 证书检查
cert_result = self.check_certificate()
for issue in cert_result["issues"]:
vulns.append(issue)
self.results["vulnerabilities"] = vulns
# 3. 生成建议
recs = []
if any(v["id"] == "TLSv1.0" for v in vulns):
recs.append("禁用 TLS 1.0 和 TLS 1.1,强制 TLS 1.2+")
if any(v["id"] == "KCI" for v in vulns):
recs.append("禁用纯 RSA 密钥交换密码套件,强制 ECDHE/DHE")
if any(v["id"] == "weak-cipher" for v in vulns):
recs.append("移除 DES/RC4/NULL 等弱加密算法")
if any(v["id"] == "FREAK" for v in vulns):
recs.append("禁用所有导出级密码套件")
self.results["recommendations"] = recs
print(f"[+] 审计完成: 发现 {len(vulns)} 个问题")
return self.results
if __name__ == "__main__":
tool = TLSAuditTool("www.example.com", 443)
results = tool.run_full_audit()
print(f"\n{'='*60}")
print(f"审计报告: {results['host']}:{results['port']}")
print(f"时间: {results['timestamp']}")
print(f"密码套件: {results['cipher'][0] if results['cipher'] else 'unknown'}")
print(f"\n发现问题 ({len(results['vulnerabilities'])}):")
for v in results['vulnerabilities']:
print(f" [{v['severity']:8s}] {v['id']:12s}: {v['description']}")
print(f"\n修复建议:")
for i, r in enumerate(results['recommendations'], 1):
print(f" {i}. {r}")七、服务端降级防护配置
7.1 Nginx 国际+国密双证书防降级配置
# nginx.conf - 防降级配置(需要编译 Tongsuo 或 BabaSSL)
server {
listen 443 ssl;
server_name secure.example.com;
# ---- 证书配置 ----
ssl_certificate /etc/nginx/certs/combined.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
# ---- 强制 TLS 1.2+ ----
ssl_protocols TLSv1.2 TLSv1.3;
# ---- 防降级密码套件 ----
# 仅使用 AEAD 模式(GCM/CCM/ChaCha20Poly1305)
# 禁用 CBC 模式(POODLE/Lucky13 攻击对象)
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:TLS_AES_256_GCM_SHA384;
# ---- HSTS (HTTP Strict Transport Security) ----
# 防止 SSL Stripping 攻击
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# ---- OCSP Stapling ----
ssl_stapling on;
ssl_stapling_verify on;
# ---- 前向保密参数 ----
ssl_ecdh_curve X25519:secp384r1:secp256r1;
ssl_dhparam /etc/nginx/certs/dhparam.pem;
# ---- 禁用会话票证(或定期轮换密钥) ----
ssl_session_tickets off;
location / {
proxy_pass http://backend;
}
}7.2 Apache + mod_ssl 防降级配置
# ssl.conf - 防降级配置
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off # TLS 1.3 使用自身协商机制
SSLSessionTickets off
# HSTS
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# OCSP Stapling
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off八、总结
| 攻击类型 | 攻击原理 | 影响协议 | 防御措施 |
|---|---|---|---|
| 版本降级 (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 压缩 |
- 国密双证书架构下需额外校验加密证书的 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)