OpenSSL-src-rust 是一个使用 Rust 编写的、以 crate 形式打包的 OpenSSL 源码和从源码构建 OpenSSL 的逻辑。目前有两个受维护的分支,分别对应两个受维护的 OpenSSL 版本,即构建 OpenSSL 3.0 的 main 分支和构建 OpenSSL 1.1.1 的 release/111 分支。
OpenSSL 3.0.4 版本在为支持 AVX512IFMA 指令的 X86_64 CPU 实现的 RSA 代码中引入了一个严重缺陷。该问题使得 2048 位私钥的 RSA 实现在此类机器上产生错误结果,并在计算过程中发生内存损坏。由于内存损坏,攻击者可能能够在执行计算的机器上触发远程代码执行。使用 2048 位 RSA 私钥的 SSL/TLS 服务器或其他服务器,若运行在支持 AVX512IFMA 指令的 X86_64 架构机器上,则会受到此问题的影响。
此漏洞导致在支持 AVX512IFMA 指令的 X86_64 架构机器上,使用 openssl-src-rust 构建 OpenSSL 3.0 版本时会在构建过程中失败并崩溃。
openssl-src(Rust)
>= 300.0.8, < 300.0.9
(GHSA-735f-pg76-fxc4)重现该错误或崩溃的过程如下:
在支持 AVX512 的 CPU 上(本演示使用 Core i7-1065G7)构建 OpenSSL-3.0.4:
CFLAGS="-O3 -g -fsanitize=address" ./config
make
运行测试:
make V=1 TESTS=test_exp test
Sanitizer 报错:
==481618==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60c000089400 at pc 0x7f01e32a9509 bp 0x7fff643ec100 sp 0x7fff643ec0f8
READ of size 8 at 0x60c000089400 thread T0
#0 0x7f01e32a9508 in bn_select_words crypto/bn/rsaz_exp.h:64
#1 0x7f01e32a9508 in bn_reduce_once_in_place crypto/bn/rsaz_exp.h:74
#2 0x7f01e32a9508 in ossl_rsaz_mod_exp_avx512_x2 crypto/bn/rsaz_exp_x2.c:223
#3 0x7f01e3287dc8 in BN_mod_exp_mont_consttime_x2 crypto/bn/bn_exp.c:1448
#4 0x4042c3 in test_mod_exp_x2 test/exptest.c:260
#5 0x40611a in run_tests test/testutil/driver.c:370
#6 0x4039ba in main test/testutil/main.c:30
#7 0x7f01e2c29319 in __libc_start_call_main (/usr/lib/libc.so.6+0x29319)
#8 0x7f01e2c293e4 in __libc_start_main_impl (/usr/lib/libc.so.6+0x293e4)
#9 0x403c40 in _start (/home/xry111/sources/lfs/openssl-3.0.4/test/exptest+0x403c40)
0x60c000089400 is located 0 bytes to the right of 128-byte region [0x60c000089380,0x60c000089400)
allocated by thread T0 here:
#0 0x7f01e3ae5107 in __interceptor_malloc ../../../../libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x7f01e34aa7a8 in CRYPTO_zalloc crypto/mem.c:197
SUMMARY: AddressSanitizer: heap-buffer-overflow crypto/bn/rsaz_exp.h:64 in bn_select_words
Shadow bytes around the buggy address:
0x0c1880009230: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
0x0c1880009240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c1880009250: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c1880009260: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
0x0c1880009270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c1880009280:[fa]fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c1880009290: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
0x0c18800092a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c18800092b0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c18800092c0: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
0x0c18800092d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==481618==ABORTING
该问题的发现者提出,此前对 OpenSSL 代码的提交可能引入了此缺陷。该提交旨在修复 BN_mod_exp_consttime,使其不会产生未归约的结果。bn_reduce_once_in_place 函数导致了堆内存损坏。
@@ -220,6 +220,9 @@ int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1,
from_words52(res1, factor_size, rr1_red);
from_words52(res2, factor_size, rr2_red);
bn_reduce_once_in_place(res1, /*carry=*/0, m1, storage, factor_size);
bn_reduce_once_in_place(res2, /*carry=*/0, m2, storage, factor_size);
该问题通过此提交中的更新得以修复,更新指出 bn_reduce_once_in_place 期望的是 BN_ULONG 的数量,而 factor_size 是模数的位大小。此更新已包含在 2022 年 10 月 12 日发布的 OpenSSL 3.0.5 中。
@@ -257,6 +257,9 @@ int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1,
from_words52(res1, factor_size, rr1_red);
from_words52(res2, factor_size, rr2_red);
/* bn_reduce_once_in_place expects number of BN_ULONG, not bit size */
factor_size /= sizeof(BN_ULONG) * 8;
bn_reduce_once_in_place(res1, /*carry=*/0, m1, storage, factor_size);
bn_reduce_once_in_place(res2, /*carry=*/0, m2, storage, factor_size);
攻击者理论上可以通过在网络(例如 TCP/IP 网络)上发送数据传输来利用此漏洞。成功的利用可能导致:
| 严重性 | 严重 9.8 / 10 |
|---|
| 攻击向量 | 网络 |
| 攻击复杂度 | 低 |
| 所需权限 | 无 |
| 用户交互 | 无 |
| 影响范围 | 未改变 |
| 机密性 | 高 |
| 完整性 | 高 |
| 可用性 | 高 |