CVE-2021-3711: OpenSSL SM2 解密缓冲区溢出漏洞分析
0x00 漏洞背景与详情
- 漏洞名称:OpenSSL SM2 解密缓冲区溢出漏洞
- CVE 编号:CVE-2021-3711
- 影响组件:OpenSSL
- 影响版本:OpenSSL 1.1.1 - 1.1.1k
- 漏洞等级:高危 (CVSS 3.1 评分: 8.8)
- 核心风险:远程代码执行 (RCE)、拒绝服务 (DoS)
该漏洞源于 OpenSSL 在实现 SM2 (中国国家商用密码算法) 解密逻辑时,对输出缓冲区大小的计算存在缺陷。攻击者可通过发送特制的畸形 SM2 密文,导致堆缓冲区溢出,进而造成服务崩溃或潜在的远程代码执行。
0x01 漏洞原理分析
在 SM2 解密过程中,应用程序通常会调用两次 EVP_PKEY_decrypt 函数:
- 第一次调用:传入
NULL作为输出缓冲区,函数返回解密后明文所需的字节数(outlen)。 - 第二次调用:应用程序根据
outlen分配堆内存,并再次调用函数进行实际的解密操作。
漏洞根源:
位于 crypto/sm2/sm2_pmeth.c 中的 pkey_sm2_decrypt 函数在预估“所需长度”时,使用了错误的逻辑。当攻击者构造畸形的 ASN.1 编码密文时,该函数返回的长度会小于实际解密后写入的数据长度。在第二次调用实际解密并写入数据时,就会向过小的缓冲区中写入超出其容量的数据,从而触发堆缓冲区溢出。
0x02 漏洞 POC 与高级利用姿势
POC 逻辑示意
触发该漏洞的关键在于构造一个“长度声明与实际内容不符”的恶意 SM2 密文。
构造步骤:
- 获取一个有效的 SM2 公钥。
- 生成一个标准的 SM2 密文,并将其封装为 ASN.1 格式。
- 篡改 ASN.1 结构中的长度字段,使其在 OpenSSL 进行长度预估时返回一个较小值(如 10 字节),但实际密文解密后会产生更多字节(如 100 字节)。
- 调用
EVP_PKEY_decrypt触发溢出。
原理示意 (C语言):
堆内存布局与 RCE 利用思路
由于 OpenSSL 广泛应用于高性能服务端,直接通过堆溢出实现 RCE 具有挑战性,但理论上可通过以下高级思路达成:
- 堆风水 (Heap Feng Shui):
- 攻击者通过发送大量 TLS 扩展数据或证书,在堆上“喷射”(Spray)目标对象(如 OpenSSL 的
BIO或EVP_PKEY结构体)。 - 利用连接关闭产生的“孔洞”精确定位恶意 SM2 密文的分配位置,使得
out缓冲区紧邻目标敏感结构。
- 攻击者通过发送大量 TLS 扩展数据或证书,在堆上“喷射”(Spray)目标对象(如 OpenSSL 的
- 劫持 BIO 结构体控制流:
BIO结构体包含一个指向BIO_METHOD的指针,而BIO_METHOD内部包含bread、bwrite等函数指针。- 通过溢出覆盖相邻
BIO的method指针,使其指向攻击者在堆中控制的伪造BIO_METHOD结构。 - 当服务端尝试对该
BIO进行读写操作时,程序便会跳转到伪造结构中定义的恶意地址,结合 ROP(返回导向编程)绕过 DEP/ASLR,最终执行 Shellcode。
实战场景与崩溃分析 (Crash Analysis)
- 国密 SSL/TLS 握手拒绝服务 (DoS):
- 在支持国密 TLS(如基于 OpenSSL 1.1.1 的定制版)的 Web 服务器中,攻击者在握手阶段发送畸形的
ClientKeyExchange数据包即可触发堆溢出。 - 崩溃现象:由于覆盖了相邻堆块的元数据(如
size字段),往往会在随后调用free()时触发 glibc 的完整性检查,报错double free or corruption并导致服务崩溃(SIGABRT)。
- 在支持国密 TLS(如基于 OpenSSL 1.1.1 的定制版)的 Web 服务器中,攻击者在握手阶段发送畸形的
- 加密机/安全网关横向移动:
- 许多硬件安全模块 (HSM) 提供 SM2 加解密接口。若后端处理逻辑未及时修补 OpenSSL,内部网络中的攻击者可通过批量构造畸形 API 请求,尝试稳定内存布局,最终实现内网横向控制。
0x03 应急排查与日志痕迹分析建议
1. 漏洞环境排查
- 版本检测:执行
openssl version。- 风险版本:
1.1.1至1.1.1k。 - 安全版本:
1.1.1l及以上,或3.0.0及以上。
- 风险版本:
- 应用检查:确认业务系统是否开启了国密套件支持,或是否调用了 SM2 加解密相关接口。
2. 日志痕迹分析
- 系统日志:查看内核日志(
dmesg//var/log/syslog),寻找包含segfault、libcrypto.so.1.1相关的内存段错误记录。 - Core Dump 分析:如果服务崩溃,提取 Core Dump 文件通过
gdb查看崩溃时的调用栈。如果崩溃点位于sm2_decrypt或相关的 SM2 解析函数中,基本可确认遭到攻击。 - 网络流量监测:关注 TLS 握手包中异常大的
ClientKeyExchange数据包,或不符合规范的 ASN.1 编码密文。
0x04 修复与缓解建议
- 升级版本(最有效):将 OpenSSL 升级到官方发布的修复版本
1.1.1l或更新版本。 - 禁用 SM2/国密算法:如果在业务场景中并非强制要求使用国密算法,可以通过配置 TLS 密码套件暂时禁用 SM2。