openssl: AVX512-specific heap buffer overflow with 3.0.4 release
Build OpenSSL-3.0.4 on a CPU with AVX512 (my CPU is a Core i7-1065G7) with:
CFLAGS="-O3 -g -fsanitize=address" ./config
make
Run a test:
make V=1 TESTS=test_exp test
The sanitizer complains:
==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
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 6
- Comments: 27 (22 by maintainers)
Links to this issue
Commits related to this issue
- rsa: fix bn_reduce_once_in_place call for rsaz_mod_exp_avx512_x2 bn_reduce_once_in_place expects the number of BN_ULONG, but factor_size is moduli bit size. Fixes #18625. Signed-off-by: Xi Ruoyao <... — committed to xry111/openssl by xry111 2 years ago
- rsa: fix bn_reduce_once_in_place call for rsaz_mod_exp_avx512_x2 bn_reduce_once_in_place expects the number of BN_ULONG, but factor_size is moduli bit size. Fixes #18625. Signed-off-by: Xi Ruoyao <... — committed to openssl/openssl by xry111 2 years ago
- dev-libs/openssl: backport AVX512 overflow fix Bug: https://github.com/openssl/openssl/issues/18625 Signed-off-by: Sam James <sam@gentoo.org> — committed to gentoo/gentoo by thesamesam 2 years ago
- rsa: fix bn_reduce_once_in_place call for rsaz_mod_exp_avx512_x2 bn_reduce_once_in_place expects the number of BN_ULONG, but factor_size is moduli bit size. Fixes #18625. Signed-off-by: Xi Ruoyao <... — committed to sftcd/openssl by xry111 2 years ago
Actually I don’t like the idea of “marking every heap buffer overflow as a security vulnerability”. Vim has started to do such thing in this year. Now we are being noised by about ten “high severity” vim CVEs per month, w/o any exploit in practice. I think we shouldn’t mark a bug as “security vulnerability” unless we have some evidence showing it can (or at least, may) be expolited.
That being said, to me 3.0.5 should be released ASAP because this issue is very severe, regardless of it’s a vulnerability or not.
I’ll also add my voice to those urging a quick 3.0.5 release as well. If that is not feasible then the openssl project should consider sending an email to the announcement/release list about this issue. Many people don’t follow the project closely enough to be aware that there is a known severe bug in the latest release.
@khantext
Yes. Here is a program (derived from the OpenSSL server fuzzer code) which sets up an SSL server and sends an offending payload. It uses memory buffers rather than TCP/IP but they are functionally analogous.
With AddressSanitizer enabled, this crashes as follows:
Yes.
If the application halts upon crashing, a single payload transmission constitutes a succesful DoS attack.
If the embedding application (e.g. Apache web server) automatically respawns after crashing, then repeated transmissions will render the server mostly unusable.
The ratio between the cost of launching the attack (sending only 2 dozen bytes of payload) vs. the cost of bearing the attack (crashing and respawning) is high, so it’s trivial to do this from basic hardware and network connection.
Three buffer are overwritten:
res1,res2andstorage. There are 2 arrays which are read, but not written to:m1andm2. After the buffer overflow:m1can be inferred fromres1.m2can be inferred fromres2.res2is known, the values ofm2can be inferred fromstorage.m2is known, the values ofres2can be inferred fromstorage.From this it follows that if the attacker controls a certain region (e.g. the values pre-overwrite can be known or defined, and the values post-overwrite can be read), then the values of an unrelated memory region (which may (but not necessarily does) contain sensitive information), can be known.
A region can be controlled by the attacker if it is allocated by either:
For this to work it is imperative that a crash due to corrupted malloc chunks does not occur, either by chance or by manipulation by the attacker.
If the attacker controls the contents of a region (e.g.
m1), andres1is known to constitute some internal data structure, and the pre-overwrite contents ofres1is known, then the data structure contents can be filled in with bytes of the attacker’s choosing.Apart from this it is also necessary to avert a crash for the data structure rewrite to be meaningful.
Impacting the integrity of certain data structures (e.g. increasing the
remainingfield of a PACKET) may lead to additional escalation.I don’t see any reason to rule out a full compromise. Despite the fact that all inputs to the modexp function are unknown to the attacker (private key components, blinding factor), these inputs bear little relation to the post-overwrite state of the out-of-bounds memory. Given that OpenSSL makes heavy use of function pointers, overwriting a pointer to refer to
execveor similar may be fruitful. Furthermore, the subtraction logic performed bybn_reduce_once_in_placelends itself to circumventing ASLR without prior knowledge of the (randomized) memory layout, as shown in the blog post.I want to note that each of these except DoS are speculative and not trivial to perform, and are predicated upon meticulously controlling the regions that are overread and overwritten by way of influencing the state machine flow, though automatic exploit generators based on symbolic execution reportedly do exist.
For applications that immediately respawn the exploit does not have to be very reliable. If it works as intended 1/10000th of the time that’s good enough to eventually achieve the goal.
I would strongly advocate for it to occur quickly. I think this issue qualifies as a CRITICAL within OpenSSL’s vulnerability severity policy, and it makes it effectively impossible for users to upgrade to 3.0.4 to obtain its security fixes.
Using
OPENSSL_ia32cap=:~0x200000(disabling just AVX512IFMA) seems to fix the problem when I test it.I’ve fixed the text above.
This vulnerability have been allocated the
CVE-2022-2274name. It has been classified by the project as HIGH severity.There is a workaround that can be used until the 3.0.5 release is done:
We anticipate that the 3.0.5 release will be done on Tuesday the 5th of July.
Edit: corrected the value in the workaround.
FWIW, the post https://guidovranken.com/2022/06/27/notes-on-openssl-remote-memory-corruption/ seems to be doing the rounds.