
OpenSSL-src RSA 개인 키 연산 시 힙 메모리 손상 : CVE-2022-2274
OpenSSL-src-rust는 Rust로 작성되어 crate로 패키징된, OpenSSL을 소스에서 빌드하기 위한 소스 코드 및 로직입니다. 현재 유지 관리되는 두 OpenSSL 버전에 대응하는 두 개의 유지 관리 브랜치, 즉 OpenSSL 3.0을 빌드하는 main과 OpenSSL 1.1.1을 빌드하는 release/111이 있습니다.
OpenSSL 3.0.4 릴리스는 AVX512IFMA 명령어를 지원하는 X86_64 CPU용 RSA 구현에 심각한 버그를 도입했습니다. 이 문제로 인해 해당 시스템에서 2048비트 개인 키를 사용하는 RSA 구현이 부정확해지고, 계산 중에 메모리 손상이 발생합니다. 메모리 손상의 결과로 공격자는 계산을 수행하는 시스템에서 원격 코드 실행을 유발할 수 있습니다. X86_64 아키텍처의 AVX512IFMA 명령어를 지원하는 시스템에서 실행되는, 2048비트 RSA 개인 키를 사용하는 SSL/TLS 서버 또는 기타 서버가 이 문제의 영향을 받습니다.
이 취약점으로 인해 openssl-src-rust를 사용한 OpenSSL 3.0 빌드가 X86_64 아키텍처의 AVX512IFMA 명령어를 지원하는 시스템에서 실패하고 프로세스가 충돌했습니다.
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
새니타이저가 다음과 같이 보고합니다:
==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이 축약되지 않은(unreduced) 결과를 생성하지 않도록 수정하기 위한 것이었습니다. 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 네트워크)를 통해 전송을 보내 이 취약점을 악용할 수 있습니다. 성공적인 악용은 다음과 같은 결과를 초래할 수 있습니다:
| 심각도 | Critical 9.8 / 10 |
|---|
| 공격 벡터 | Network |
| 공격 복잡도 | Low |
| 필요한 권한 | None |
| 사용자 상호 작용 | None |
| 범위 | Unchanged |
| 기밀성 | High |
| 무결성 | High |
| 가용성 | High |