Resolves: RHEL-29578 - vulnerable to marvin attack if the authentication option is used
This commit is contained in:
parent
e5d9de6fb9
commit
57d25d7381
231
0006-cve-2024-26306.patch
Normal file
231
0006-cve-2024-26306.patch
Normal file
@ -0,0 +1,231 @@
|
||||
From 299b356df6939f71619bf45bf7a7d2222e17d840 Mon Sep 17 00:00:00 2001
|
||||
From: Sarah Larsen <swlarsen@Sarahs-MBP.lan>
|
||||
Date: Wed, 20 Mar 2024 17:02:31 -0700
|
||||
Subject: [PATCH] Using OAEP padding instead of PKCS1 padding for OpenSSL. Fix
|
||||
for CVE-2024-26306.
|
||||
|
||||
Special thanks to Hubert Kario at Red Hat for finding the vulnerability.
|
||||
|
||||
diff --git a/src/iperf.h b/src/iperf.h
|
||||
index f137b07..f6c0313 100755
|
||||
--- a/src/iperf.h
|
||||
+++ b/src/iperf.h
|
||||
@@ -260,6 +260,7 @@ struct iperf_test
|
||||
int ctrl_sck_mss; /* MSS for the control channel */
|
||||
char *server_rsa_private_key;
|
||||
char *server_authorized_users;
|
||||
+ int use_pkcs1_padding;
|
||||
|
||||
/* boolean variables for Options */
|
||||
int daemon; /* -D option */
|
||||
diff --git a/src/iperf_api.c b/src/iperf_api.c
|
||||
index d40561c10..7fb741e77 100644
|
||||
--- a/src/iperf_api.c
|
||||
+++ b/src/iperf_api.c
|
||||
@@ -1137,6 +1137,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
{"rsa-public-key-path", required_argument, NULL, OPT_CLIENT_RSA_PUBLIC_KEY},
|
||||
{"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY},
|
||||
{"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS},
|
||||
+ {"use-pkcs1-padding", no_argument, NULL, OPT_USE_PKCS1_PADDING},
|
||||
#endif /* HAVE_SSL */
|
||||
{"fq-rate", required_argument, NULL, OPT_FQ_RATE},
|
||||
{"pacing-timer", required_argument, NULL, OPT_PACING_TIMER},
|
||||
@@ -1630,6 +1631,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
case OPT_SERVER_AUTHORIZED_USERS:
|
||||
test->server_authorized_users = strdup(optarg);
|
||||
break;
|
||||
+ case OPT_USE_PKCS1_PADDING:
|
||||
+ test->use_pkcs1_padding = 1;
|
||||
+ break;
|
||||
#endif /* HAVE_SSL */
|
||||
case OPT_PACING_TIMER:
|
||||
test->settings->pacing_timer = unit_atoi(optarg);
|
||||
@@ -1100,7 +1104,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
i_errno = IESETCLIENTAUTH;
|
||||
return -1;
|
||||
}
|
||||
- encode_auth_setting(client_username, client_password, client_rsa_public_key, &test->settings->authtoken);
|
||||
+ encode_auth_setting(client_username, client_password, client_rsa_public_key, &test->settings->authtoken, test->use_pkcs1_padding);
|
||||
}
|
||||
|
||||
if (test->role == 'c' && (test->server_rsa_private_key || test->server_authorized_users)){
|
||||
@@ -1346,7 +1350,7 @@ int test_is_authorized(struct iperf_test *test){
|
||||
if (test->settings->authtoken){
|
||||
char *username = NULL, *password = NULL;
|
||||
time_t ts;
|
||||
- decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
|
||||
+ decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts, test->use_pkcs1_padding);
|
||||
int ret = check_authentication(username, password, ts, test->server_authorized_users);
|
||||
if (ret == 0){
|
||||
iperf_printf(test, report_authetication_successed, username, ts);
|
||||
diff --git a/src/iperf_locale.c b/src/iperf_locale.c
|
||||
index d5a5354..3b6860d 100644
|
||||
--- a/src/iperf_locale.c
|
||||
+++ b/src/iperf_locale.c
|
||||
@@ -128,6 +128,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
|
||||
" authentication credentials\n"
|
||||
" --authorized-users-path path to the configuration file containing user\n"
|
||||
" credentials\n"
|
||||
+ " --use-pkcs1-padding use pkcs1 padding at your own risk\n"
|
||||
#endif //HAVE_SSL
|
||||
"Client specific:\n"
|
||||
" -c, --client <host> run in client mode, connecting to <host>\n"
|
||||
diff --git a/src/iperf_api.h b/src/iperf_api.h
|
||||
index 3a5df03..255227c 100755
|
||||
--- a/src/iperf_api.h
|
||||
+++ b/src/iperf_api.h
|
||||
@@ -68,6 +68,7 @@ struct iperf_stream;
|
||||
#define OPT_SERVER_AUTHORIZED_USERS 15
|
||||
#define OPT_PACING_TIMER 16
|
||||
#define OPT_CONNECT_TIMEOUT 17
|
||||
+#define OPT_USE_PKCS1_PADDING 30
|
||||
|
||||
/* states */
|
||||
#define TEST_START 1
|
||||
diff --git a/src/iperf_auth.h b/src/iperf_auth.h
|
||||
index 38971d8..1f78699 100644
|
||||
--- a/src/iperf_auth.h
|
||||
+++ b/src/iperf_auth.h
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
int test_load_pubkey(const char *public_keyfile);
|
||||
int test_load_private_key(const char *private_keyfile);
|
||||
-int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken);
|
||||
-int decode_auth_setting(int enable_debug, const char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts);
|
||||
+int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken, int use_pkcs1_padding);
|
||||
+int decode_auth_setting(int enable_debug, const char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts, int use_pkcs1_padding);
|
||||
int check_authentication(const char *username, const char *password, const time_t ts, const char *filename);
|
||||
ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream);
|
||||
diff --git a/src/iperf3.1 b/src/iperf3.1
|
||||
index 1be8cc3..87c3e02 100644
|
||||
--- a/src/iperf3.1
|
||||
+++ b/src/iperf3.1
|
||||
@@ -155,6 +155,15 @@ send output to a log file.
|
||||
force flushing output at every interval.
|
||||
Used to avoid buffering when sending output to pipe.
|
||||
.TP
|
||||
+.BR --use-pkcs1-padding
|
||||
+This option is only meaningful when using iperf3's authentication
|
||||
+features. Versions of iperf3 prior to 3.17 used PCKS1 padding in the
|
||||
+RSA-encrypted credentials, which was vulnerable to a side-channel
|
||||
+attack that could reveal a server's private key. Beginning with
|
||||
+iperf-3.17, OAEP padding is used, however this is a breaking change
|
||||
+that is not compatible with older iperf3 versions. Use this option to
|
||||
+preserve the less secure, but more compatible, behavior.
|
||||
+.TP
|
||||
.BR -d ", " --debug " "
|
||||
emit debugging output.
|
||||
Primarily (perhaps exclusively) of use to developers.
|
||||
diff --git a/src/iperf_auth.c b/src/iperf_auth.c
|
||||
index f8d2b0a..2d7d519 100644
|
||||
--- a/src/iperf_auth.c
|
||||
+++ b/src/iperf_auth.c
|
||||
@@ -194,11 +194,12 @@ int test_load_private_key(const char *file){
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsigned char **encryptedtext) {
|
||||
+int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsigned char **encryptedtext, int use_pkcs1_padding) {
|
||||
EVP_PKEY *public_key = NULL;
|
||||
RSA *rsa = NULL;
|
||||
- unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
|
||||
- int keysize, encryptedtext_len, rsa_buffer_len;
|
||||
+ unsigned char *rsa_buffer = NULL;
|
||||
+ size_t encryptedtext_len = 0;
|
||||
+ int rsa_buffer_len, keysize;
|
||||
|
||||
public_key = load_pubkey(public_keyfile);
|
||||
rsa = EVP_PKEY_get1_RSA(public_key);
|
||||
@@ -210,20 +211,35 @@ int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsig
|
||||
|
||||
BIO *bioBuff = BIO_new_mem_buf((void*)plaintext, (int)strlen(plaintext));
|
||||
rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2);
|
||||
- encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, pad);
|
||||
+
|
||||
+ int padding = RSA_PKCS1_OAEP_PADDING;
|
||||
+ if (use_pkcs1_padding){
|
||||
+ padding = RSA_PKCS1_PADDING;
|
||||
+ }
|
||||
+
|
||||
+ encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, padding);
|
||||
|
||||
RSA_free(rsa);
|
||||
OPENSSL_free(rsa_buffer);
|
||||
- OPENSSL_free(bioBuff);
|
||||
+ OPENSSL_free(bioBuff);
|
||||
+
|
||||
+ if (encryptedtext_len < 0) {
|
||||
+ goto errreturn;
|
||||
+ }
|
||||
+
|
||||
+ return encryptedtext_len;
|
||||
|
||||
- return encryptedtext_len;
|
||||
+ errreturn:
|
||||
+ fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, const char *private_keyfile, unsigned char **plaintext) {
|
||||
+int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, const char *private_keyfile, unsigned char **plaintext, int use_pkcs1_padding) {
|
||||
EVP_PKEY *private_key = NULL;
|
||||
RSA *rsa = NULL;
|
||||
- unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
|
||||
- int plaintext_len, rsa_buffer_len, keysize;
|
||||
+ unsigned char *rsa_buffer = NULL;
|
||||
+ size_t plaintext_len = 0;
|
||||
+ int rsa_buffer_len, keysize;
|
||||
|
||||
private_key = load_key(private_keyfile);
|
||||
rsa = EVP_PKEY_get1_RSA(private_key);
|
||||
@@ -235,35 +250,45 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt
|
||||
|
||||
BIO *bioBuff = BIO_new_mem_buf((void*)encryptedtext, encryptedtext_len);
|
||||
rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2);
|
||||
- plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, pad);
|
||||
+
|
||||
+ int padding = RSA_PKCS1_OAEP_PADDING;
|
||||
+ if (use_pkcs1_padding){
|
||||
+ padding = RSA_PKCS1_PADDING;
|
||||
+ }
|
||||
+
|
||||
+ plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, padding);
|
||||
|
||||
RSA_free(rsa);
|
||||
OPENSSL_free(rsa_buffer);
|
||||
OPENSSL_free(bioBuff);
|
||||
|
||||
+ if (plaintext_len < 0) {
|
||||
+ plaintext_len = 0;
|
||||
+ }
|
||||
+
|
||||
return plaintext_len;
|
||||
}
|
||||
|
||||
-int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken){
|
||||
+int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken, int use_pkcs1_padding){
|
||||
time_t t = time(NULL);
|
||||
time_t utc_seconds = mktime(localtime(&t));
|
||||
char text[150];
|
||||
sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds);
|
||||
unsigned char *encrypted = NULL;
|
||||
int encrypted_len;
|
||||
- encrypted_len = encrypt_rsa_message(text, public_keyfile, &encrypted);
|
||||
+ encrypted_len = encrypt_rsa_message(text, public_keyfile, &encrypted, use_pkcs1_padding);
|
||||
Base64Encode(encrypted, encrypted_len, authtoken);
|
||||
return (0); //success
|
||||
}
|
||||
|
||||
-int decode_auth_setting(int enable_debug, char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts){
|
||||
+int decode_auth_setting(int enable_debug, char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts, int use_pkcs1_padding){
|
||||
unsigned char *encrypted_b64 = NULL;
|
||||
size_t encrypted_len_b64;
|
||||
Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64);
|
||||
|
||||
unsigned char *plaintext = NULL;
|
||||
int plaintext_len;
|
||||
- plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_keyfile, &plaintext);
|
||||
+ plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_keyfile, &plaintext, use_pkcs1_padding);
|
||||
plaintext[plaintext_len] = '\0';
|
||||
|
||||
char s_username[20], s_password[20];
|
@ -1,6 +1,6 @@
|
||||
Name: iperf3
|
||||
Version: 3.5
|
||||
Release: 9%{?dist}
|
||||
Release: 10%{?dist}
|
||||
Summary: Measurement tool for TCP/UDP bandwidth performance
|
||||
|
||||
Group: Applications/Internet
|
||||
@ -15,6 +15,7 @@ Patch0002: 0002-udp-counters-manpage.patch
|
||||
Patch0003: 0003-covscan-sctp.patch
|
||||
Patch0004: 0004-cve-2023-38403.patch
|
||||
Patch0005: 0005-cve-2023-7250.patch
|
||||
Patch0006: 0006-cve-2024-26306.patch
|
||||
|
||||
%description
|
||||
Iperf is a tool to measure maximum TCP bandwidth, allowing the tuning of
|
||||
@ -62,6 +63,9 @@ rm -f %{buildroot}%{_libdir}/libiperf.la
|
||||
%{_libdir}/*.so
|
||||
|
||||
%changelog
|
||||
* Tue Jun 11 2024 Michal Ruprich <mruprich@redhat.com> - 3.5-10
|
||||
- Resolves: RHEL-29578 - vulnerable to marvin attack if the authentication option is used
|
||||
|
||||
* Tue Jun 04 2024 Michal Ruprich <mruprich@redhat.com> - 3.5-9
|
||||
- Resolves: RHEL-17069 - possible denial of service
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user