import mod_auth_openidc-2.3.7-11.module+el8.6.0+14082+b6f23e95
This commit is contained in:
parent
1664f80d95
commit
214d572d0c
@ -0,0 +1,406 @@
|
||||
From 3c4949e1436473644836f0c4634b809c7526c43a Mon Sep 17 00:00:00 2001
|
||||
From: Hans Zandbelt <hans.zandbelt@zmartzone.eu>
|
||||
Date: Thu, 10 Jun 2021 15:32:48 +0200
|
||||
Subject: [PATCH 1/3] use encrypted JWTs for storing encrypted cache contents
|
||||
|
||||
- avoid using static AAD/IV; thanks @niebardzo
|
||||
- bump to 2.4.9-dev
|
||||
|
||||
Signed-off-by: Hans Zandbelt <hans.zandbelt@zmartzone.eu>
|
||||
---
|
||||
ChangeLog | 4 +
|
||||
src/cache/common.c | 331 ++++----------------------------------
|
||||
|
||||
diff --git a/ChangeLog b/ChangeLog
|
||||
index 075f98d..b4ab0a1 100644
|
||||
--- a/ChangeLog
|
||||
+++ b/ChangeLog
|
||||
@@ -1,3 +1,7 @@
|
||||
+06/10/2021
|
||||
+- use encrypted JWTs for storing encrypted cache contents and avoid using static AAD/IV; thanks @niebardzo
|
||||
+- bump to 2.4.9-dev
|
||||
+
|
||||
09/03/2020
|
||||
- add SameSite attribute on cookie clearance / logout; thanks @v0gler
|
||||
- bump to 2.4.4.1
|
||||
diff --git a/src/cache/common.c b/src/cache/common.c
|
||||
index c33876a..e665370 100644
|
||||
--- a/src/cache/common.c
|
||||
+++ b/src/cache/common.c
|
||||
@@ -229,324 +229,59 @@ apr_byte_t oidc_cache_mutex_destroy(server_rec *s, oidc_cache_mutex_t *m) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
-#define oidc_cache_crypto_openssl_error(r, fmt, ...) \
|
||||
- oidc_error(r, "%s: %s", apr_psprintf(r->pool, fmt, ##__VA_ARGS__), ERR_error_string(ERR_get_error(), NULL))
|
||||
-
|
||||
-#define OIDC_CACHE_CIPHER EVP_aes_256_gcm()
|
||||
-#define OIDC_CACHE_TAG_LEN 16
|
||||
-
|
||||
-#if (OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined(LIBRESSL_VERSION_NUMBER))
|
||||
-#define OIDC_CACHE_CRYPTO_GET_TAG EVP_CTRL_AEAD_GET_TAG
|
||||
-#define OIDC_CACHE_CRYPTO_SET_TAG EVP_CTRL_AEAD_SET_TAG
|
||||
-#define OIDC_CACHE_CRYPTO_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN
|
||||
-#else
|
||||
-#define OIDC_CACHE_CRYPTO_GET_TAG EVP_CTRL_GCM_GET_TAG
|
||||
-#define OIDC_CACHE_CRYPTO_SET_TAG EVP_CTRL_GCM_SET_TAG
|
||||
-#define OIDC_CACHE_CRYPTO_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN
|
||||
-#endif
|
||||
+#define OIDC_CACHE_CRYPTO_JSON_KEY "c"
|
||||
|
||||
/*
|
||||
- * AES GCM encrypt
|
||||
+ * AES GCM encrypt using the crypto passphrase as symmetric key
|
||||
*/
|
||||
-static int oidc_cache_crypto_encrypt_impl(request_rec *r,
|
||||
- unsigned char *plaintext, int plaintext_len, const unsigned char *aad,
|
||||
- int aad_len, unsigned char *key, const unsigned char *iv, int iv_len,
|
||||
- unsigned char *ciphertext, const unsigned char *tag, int tag_len) {
|
||||
- EVP_CIPHER_CTX *ctx;
|
||||
-
|
||||
- int len;
|
||||
-
|
||||
- int ciphertext_len;
|
||||
-
|
||||
- /* create and initialize the context */
|
||||
- if (!(ctx = EVP_CIPHER_CTX_new())) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_new");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* initialize the encryption cipher */
|
||||
- if (!EVP_EncryptInit_ex(ctx, OIDC_CACHE_CIPHER, NULL, NULL, NULL)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_EncryptInit_ex");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* set IV length */
|
||||
- if (!EVP_CIPHER_CTX_ctrl(ctx, OIDC_CACHE_CRYPTO_SET_IVLEN, iv_len, NULL)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_ctrl");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* initialize key and IV */
|
||||
- if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_EncryptInit_ex");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* provide AAD data */
|
||||
- if (!EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptUpdate aad: aad_len=%d",
|
||||
- aad_len);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* provide the message to be encrypted and obtain the encrypted output */
|
||||
- if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_EncryptUpdate ciphertext");
|
||||
- return -1;
|
||||
- }
|
||||
- ciphertext_len = len;
|
||||
-
|
||||
- /*
|
||||
- * finalize the encryption; normally ciphertext bytes may be written at
|
||||
- * this stage, but this does not occur in GCM mode
|
||||
- */
|
||||
- if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_EncryptFinal_ex");
|
||||
- return -1;
|
||||
- }
|
||||
- ciphertext_len += len;
|
||||
-
|
||||
- /* get the tag */
|
||||
- if (!EVP_CIPHER_CTX_ctrl(ctx, OIDC_CACHE_CRYPTO_GET_TAG, tag_len,
|
||||
- (void *) tag)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_ctrl");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* clean up */
|
||||
- EVP_CIPHER_CTX_free(ctx);
|
||||
-
|
||||
- return ciphertext_len;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * AES GCM decrypt
|
||||
- */
|
||||
-static int oidc_cache_crypto_decrypt_impl(request_rec *r,
|
||||
- unsigned char *ciphertext, int ciphertext_len, const unsigned char *aad,
|
||||
- int aad_len, const unsigned char *tag, int tag_len, unsigned char *key,
|
||||
- const unsigned char *iv, int iv_len, unsigned char *plaintext) {
|
||||
- EVP_CIPHER_CTX *ctx;
|
||||
- int len;
|
||||
- int plaintext_len;
|
||||
- int ret;
|
||||
-
|
||||
- /* create and initialize the context */
|
||||
- if (!(ctx = EVP_CIPHER_CTX_new())) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_new");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* initialize the decryption cipher */
|
||||
- if (!EVP_DecryptInit_ex(ctx, OIDC_CACHE_CIPHER, NULL, NULL, NULL)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptInit_ex");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* set IV length */
|
||||
- if (!EVP_CIPHER_CTX_ctrl(ctx, OIDC_CACHE_CRYPTO_SET_IVLEN, iv_len, NULL)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_ctrl");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* initialize key and IV */
|
||||
- if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptInit_ex");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* provide AAD data */
|
||||
- if (!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptUpdate aad: aad_len=%d",
|
||||
- aad_len);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* provide the message to be decrypted and obtain the plaintext output */
|
||||
- if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptUpdate ciphertext");
|
||||
- return -1;
|
||||
- }
|
||||
- plaintext_len = len;
|
||||
-
|
||||
- /* set expected tag value; works in OpenSSL 1.0.1d and later */
|
||||
- if (!EVP_CIPHER_CTX_ctrl(ctx, OIDC_CACHE_CRYPTO_SET_TAG, tag_len,
|
||||
- (void *) tag)) {
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_ctrl");
|
||||
- return -1;
|
||||
- }
|
||||
+static apr_byte_t oidc_cache_crypto_encrypt(request_rec *r, const char *plaintext, const char *key,
|
||||
+ char **result) {
|
||||
+ apr_byte_t rv = FALSE;
|
||||
+ json_t *json = NULL;
|
||||
|
||||
- /*
|
||||
- * finalize the decryption; a positive return value indicates success,
|
||||
- * anything else is a failure - the plaintext is not trustworthy
|
||||
- */
|
||||
- ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
|
||||
+ json = json_object();
|
||||
+ json_object_set_new(json, OIDC_CACHE_CRYPTO_JSON_KEY, json_string(plaintext));
|
||||
|
||||
- /* clean up */
|
||||
- EVP_CIPHER_CTX_free(ctx);
|
||||
-
|
||||
- if (ret > 0) {
|
||||
- /* success */
|
||||
- plaintext_len += len;
|
||||
- return plaintext_len;
|
||||
- } else {
|
||||
- /* verify failed */
|
||||
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptFinal_ex");
|
||||
- return -1;
|
||||
- }
|
||||
-}
|
||||
+ rv = oidc_util_jwt_create(r, (const char*) key, json, result);
|
||||
|
||||
-/*
|
||||
- * static AAD value for encryption/decryption
|
||||
- */
|
||||
-static const unsigned char OIDC_CACHE_CRYPTO_GCM_AAD[] = { 0x4d, 0x23, 0xc3,
|
||||
- 0xce, 0xc3, 0x34, 0xb4, 0x9b, 0xdb, 0x37, 0x0c, 0x43, 0x7f, 0xec, 0x78,
|
||||
- 0xde };
|
||||
+ if (json)
|
||||
+ json_decref(json);
|
||||
|
||||
-/*
|
||||
- * static IV value for encryption/decryption
|
||||
- */
|
||||
-static const unsigned char OIDC_CACHE_CRYPTO_GCM_IV[] = { 0x00, 0x01, 0x02,
|
||||
- 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
- 0x0f };
|
||||
-
|
||||
-/*
|
||||
- * AES GCM encrypt using the static AAD and IV
|
||||
- */
|
||||
-static int oidc_cache_crypto_encrypt(request_rec *r, const char *plaintext,
|
||||
- unsigned char *key, char **result) {
|
||||
- char *encoded = NULL, *p = NULL, *e_tag = NULL;
|
||||
- unsigned char *ciphertext = NULL;
|
||||
- int plaintext_len, ciphertext_len, encoded_len, e_tag_len;
|
||||
- unsigned char tag[OIDC_CACHE_TAG_LEN];
|
||||
-
|
||||
- /* allocate space for the ciphertext */
|
||||
- plaintext_len = strlen(plaintext) + 1;
|
||||
- ciphertext = apr_pcalloc(r->pool,
|
||||
- (plaintext_len + EVP_CIPHER_block_size(OIDC_CACHE_CIPHER)));
|
||||
-
|
||||
- ciphertext_len = oidc_cache_crypto_encrypt_impl(r,
|
||||
- (unsigned char *) plaintext, plaintext_len,
|
||||
- OIDC_CACHE_CRYPTO_GCM_AAD, sizeof(OIDC_CACHE_CRYPTO_GCM_AAD), key,
|
||||
- OIDC_CACHE_CRYPTO_GCM_IV, sizeof(OIDC_CACHE_CRYPTO_GCM_IV),
|
||||
- ciphertext, tag, sizeof(tag));
|
||||
-
|
||||
- /* base64url encode the resulting ciphertext */
|
||||
- encoded_len = oidc_base64url_encode(r, &encoded, (const char *) ciphertext,
|
||||
- ciphertext_len, 1);
|
||||
- if (encoded_len > 0) {
|
||||
- p = encoded;
|
||||
-
|
||||
- /* now allocated space for the concatenated base64url encoded ciphertext and tag */
|
||||
- encoded = apr_pcalloc(r->pool,
|
||||
- encoded_len + 1 + OIDC_CACHE_TAG_LEN + 1);
|
||||
- memcpy(encoded, p, encoded_len);
|
||||
- p = encoded + encoded_len;
|
||||
- *p = OIDC_CHAR_DOT;
|
||||
- p++;
|
||||
-
|
||||
- /* base64url encode the tag and append it in the buffer */
|
||||
- e_tag_len = oidc_base64url_encode(r, &e_tag, (const char *) tag,
|
||||
- OIDC_CACHE_TAG_LEN, 1);
|
||||
- memcpy(p, e_tag, e_tag_len);
|
||||
- encoded_len += e_tag_len + 1;
|
||||
-
|
||||
- /* make sure the result is \0 terminated */
|
||||
- encoded[encoded_len] = '\0';
|
||||
-
|
||||
- *result = encoded;
|
||||
- }
|
||||
-
|
||||
- return encoded_len;
|
||||
+ return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
- * AES GCM decrypt using the static AAD and IV
|
||||
+ * AES GCM decrypt using the crypto passphrase as symmetric key
|
||||
*/
|
||||
-static int oidc_cache_crypto_decrypt(request_rec *r, const char *cache_value,
|
||||
- unsigned char *key, unsigned char **plaintext) {
|
||||
+static apr_byte_t oidc_cache_crypto_decrypt(request_rec *r, const char *cache_value,
|
||||
+ const char *key, char **plaintext) {
|
||||
|
||||
- int len = -1;
|
||||
+ apr_byte_t rv = FALSE;
|
||||
+ json_t *json = NULL;
|
||||
|
||||
- /* grab the base64url-encoded tag after the "." */
|
||||
- char *encoded_tag = strstr(cache_value, ".");
|
||||
- if (encoded_tag == NULL) {
|
||||
- oidc_error(r,
|
||||
- "corrupted cache value: no tag separator found in encrypted value");
|
||||
- return FALSE;
|
||||
- }
|
||||
+ rv = oidc_util_jwt_verify(r, (const char*) key, cache_value, &json);
|
||||
+ if (rv == FALSE)
|
||||
+ goto end;
|
||||
|
||||
- /* make sure we don't modify the original string since it may be just a pointer into the cache (shm) */
|
||||
- cache_value = apr_pstrmemdup(r->pool, cache_value,
|
||||
- strlen(cache_value) - strlen(encoded_tag));
|
||||
- encoded_tag++;
|
||||
+ rv = oidc_json_object_get_string(r->pool, json, OIDC_CACHE_CRYPTO_JSON_KEY, plaintext, NULL);
|
||||
|
||||
- /* base64url decode the ciphertext */
|
||||
- char *d_bytes = NULL;
|
||||
- int d_len = oidc_base64url_decode(r->pool, &d_bytes, cache_value);
|
||||
+ end:
|
||||
|
||||
- /* base64url decode the tag */
|
||||
- char *t_bytes = NULL;
|
||||
- int t_len = oidc_base64url_decode(r->pool, &t_bytes, encoded_tag);
|
||||
+ if (json)
|
||||
+ json_decref(json);
|
||||
|
||||
- /* see if we're still good to go */
|
||||
- if ((d_len > 0) && (t_len > 0)) {
|
||||
-
|
||||
- /* allocated space for the plaintext */
|
||||
- *plaintext = apr_pcalloc(r->pool,
|
||||
- (d_len + EVP_CIPHER_block_size(OIDC_CACHE_CIPHER) - 1));
|
||||
-
|
||||
- /* decrypt the ciphertext providing the tag value */
|
||||
-
|
||||
- len = oidc_cache_crypto_decrypt_impl(r, (unsigned char *) d_bytes,
|
||||
- d_len, OIDC_CACHE_CRYPTO_GCM_AAD,
|
||||
- sizeof(OIDC_CACHE_CRYPTO_GCM_AAD), (unsigned char *) t_bytes,
|
||||
- t_len, key, OIDC_CACHE_CRYPTO_GCM_IV,
|
||||
- sizeof(OIDC_CACHE_CRYPTO_GCM_IV), *plaintext);
|
||||
-
|
||||
- /* check the result and make sure it is \0 terminated */
|
||||
- if (len > -1) {
|
||||
- (*plaintext)[len] = '\0';
|
||||
- } else {
|
||||
- *plaintext = NULL;
|
||||
- }
|
||||
-
|
||||
- }
|
||||
-
|
||||
- return len;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * hash the crypto passhphrase so it has enough key length for AES GCM 256
|
||||
- */
|
||||
-static unsigned char *oidc_cache_hash_passphrase(request_rec *r,
|
||||
- const char *passphrase) {
|
||||
-
|
||||
- unsigned char *key = NULL;
|
||||
- unsigned int key_len = 0;
|
||||
- oidc_jose_error_t err;
|
||||
-
|
||||
- if (oidc_jose_hash_bytes(r->pool, OIDC_JOSE_ALG_SHA256,
|
||||
- (const unsigned char *) passphrase, strlen(passphrase), &key,
|
||||
- &key_len, &err) == FALSE) {
|
||||
- oidc_error(r, "oidc_jose_hash_bytes returned an error: %s", err.text);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- return key;
|
||||
+ return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* hash a cache key and a crypto passphrase so the result is suitable as an randomized cache key
|
||||
*/
|
||||
-static char *oidc_cache_get_hashed_key(request_rec *r, const char *passphrase,
|
||||
- const char *key) {
|
||||
+static char* oidc_cache_get_hashed_key(request_rec *r, const char *passphrase, const char *key) {
|
||||
char *input = apr_psprintf(r->pool, "%s:%s", passphrase, key);
|
||||
char *output = NULL;
|
||||
- if (oidc_util_hash_string_and_base64url_encode(r, OIDC_JOSE_ALG_SHA256,
|
||||
- input, &output) == FALSE) {
|
||||
- oidc_error(r,
|
||||
- "oidc_util_hash_string_and_base64url_encode returned an error");
|
||||
+ if (oidc_util_hash_string_and_base64url_encode(r, OIDC_JOSE_ALG_SHA256, input, &output)
|
||||
+ == FALSE) {
|
||||
+ oidc_error(r, "oidc_util_hash_string_and_base64url_encode returned an error");
|
||||
return NULL;
|
||||
}
|
||||
return output;
|
||||
@@ -588,9 +323,7 @@ apr_byte_t oidc_cache_get(request_rec *r, const char *section, const char *key,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- rc = (oidc_cache_crypto_decrypt(r, cache_value,
|
||||
- oidc_cache_hash_passphrase(r, cfg->crypto_passphrase),
|
||||
- (unsigned char **) value) > 0);
|
||||
+ rc = oidc_cache_crypto_decrypt(r, cache_value, cfg->crypto_passphrase, value);
|
||||
|
||||
out:
|
||||
/* log the result */
|
||||
@@ -634,9 +367,7 @@ apr_byte_t oidc_cache_set(request_rec *r, const char *section, const char *key,
|
||||
goto out;
|
||||
|
||||
if (value != NULL) {
|
||||
- if (oidc_cache_crypto_encrypt(r, value,
|
||||
- oidc_cache_hash_passphrase(r, cfg->crypto_passphrase),
|
||||
- &encoded) <= 0)
|
||||
+ if (oidc_cache_crypto_encrypt(r, value, cfg->crypto_passphrase, &encoded) == FALSE)
|
||||
goto out;
|
||||
value = encoded;
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
From dad95a3ca050910d44ff346edead722e341417ef Mon Sep 17 00:00:00 2001
|
||||
From: Hans Zandbelt <hans.zandbelt@zmartzone.eu>
|
||||
Date: Fri, 25 Jun 2021 11:42:57 +0200
|
||||
Subject: [PATCH 2/3] avoid XSS vulnerability when using OIDCPreservePost On
|
||||
|
||||
and supplying URLs that contain single quotes; thanks @oss-aimoto
|
||||
|
||||
Signed-off-by: Hans Zandbelt <hans.zandbelt@zmartzone.eu>
|
||||
---
|
||||
ChangeLog | 4 ++++
|
||||
src/mod_auth_openidc.c | 2 +-
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ChangeLog b/ChangeLog
|
||||
index b4ab0a1..7054f0b 100644
|
||||
--- a/ChangeLog
|
||||
+++ b/ChangeLog
|
||||
@@ -1,3 +1,7 @@
|
||||
+06/25/2021
|
||||
+- avoid XSS vulnerability when using OIDCPreservePost On and supplying URLs that contain single quotes
|
||||
+ thanks @oss-aimoto
|
||||
+
|
||||
06/10/2021
|
||||
- use encrypted JWTs for storing encrypted cache contents and avoid using static AAD/IV; thanks @niebardzo
|
||||
- bump to 2.4.9-dev
|
||||
diff --git a/src/mod_auth_openidc.c b/src/mod_auth_openidc.c
|
||||
index 4cc7976..ea84e5e 100644
|
||||
--- a/src/mod_auth_openidc.c
|
||||
+++ b/src/mod_auth_openidc.c
|
||||
@@ -519,7 +519,7 @@ static int oidc_request_post_preserved_restore(request_rec *r,
|
||||
" input.type = \"hidden\";\n"
|
||||
" document.forms[0].appendChild(input);\n"
|
||||
" }\n"
|
||||
- " document.forms[0].action = '%s';\n"
|
||||
+ " document.forms[0].action = \"%s\";\n"
|
||||
" document.forms[0].submit();\n"
|
||||
" }\n"
|
||||
" </script>\n", method, original_url);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,149 @@
|
||||
From 93b81054d4d1ece64a6799cc50a65b0daeabf4d1 Mon Sep 17 00:00:00 2001
|
||||
From: AIMOTO NORIHITO <aimoto@osstech.co.jp>
|
||||
Date: Mon, 28 Jun 2021 13:05:52 +0900
|
||||
Subject: [PATCH 3/3] Add a function to escape Javascript characters
|
||||
|
||||
---
|
||||
src/mod_auth_openidc.c | 6 ++--
|
||||
src/mod_auth_openidc.h | 1 +
|
||||
src/util.c | 81 ++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 85 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/mod_auth_openidc.c b/src/mod_auth_openidc.c
|
||||
index ea84e5e..37743b3 100644
|
||||
--- a/src/mod_auth_openidc.c
|
||||
+++ b/src/mod_auth_openidc.c
|
||||
@@ -474,7 +474,7 @@ apr_byte_t oidc_post_preserve_javascript(request_rec *r, const char *location,
|
||||
" </script>\n", jmethod, json,
|
||||
location ?
|
||||
apr_psprintf(r->pool, "window.location='%s';\n",
|
||||
- location) :
|
||||
+ oidc_util_javascript_escape(r->pool, location)) :
|
||||
"");
|
||||
if (location == NULL) {
|
||||
if (javascript_method)
|
||||
@@ -522,7 +522,7 @@ static int oidc_request_post_preserved_restore(request_rec *r,
|
||||
" document.forms[0].action = \"%s\";\n"
|
||||
" document.forms[0].submit();\n"
|
||||
" }\n"
|
||||
- " </script>\n", method, original_url);
|
||||
+ " </script>\n", method, oidc_util_javascript_escape(r->pool, original_url));
|
||||
|
||||
const char *body = " <p>Restoring...</p>\n"
|
||||
" <form method=\"post\"></form>\n";
|
||||
@@ -1626,7 +1626,7 @@ static int oidc_session_redirect_parent_window_to_logout(request_rec *r,
|
||||
char *java_script = apr_psprintf(r->pool,
|
||||
" <script type=\"text/javascript\">\n"
|
||||
" window.top.location.href = '%s?session=logout';\n"
|
||||
- " </script>\n", oidc_get_redirect_uri(r, c));
|
||||
+ " </script>\n", oidc_util_javascript_escape(r->pool, oidc_get_redirect_uri(r, c)));
|
||||
|
||||
return oidc_util_html_send(r, "Redirecting...", java_script, NULL, NULL,
|
||||
DONE);
|
||||
diff --git a/src/mod_auth_openidc.h b/src/mod_auth_openidc.h
|
||||
index ea79e6b..b88937a 100644
|
||||
--- a/src/mod_auth_openidc.h
|
||||
+++ b/src/mod_auth_openidc.h
|
||||
@@ -747,6 +747,7 @@ apr_byte_t oidc_json_object_get_string(apr_pool_t *pool, json_t *json, const cha
|
||||
apr_byte_t oidc_json_object_get_int(apr_pool_t *pool, json_t *json, const char *name, int *value, const int default_value);
|
||||
apr_byte_t oidc_json_object_get_bool(apr_pool_t *pool, json_t *json, const char *name, int *value, const int default_value);
|
||||
char *oidc_util_html_escape(apr_pool_t *pool, const char *input);
|
||||
+char *oidc_util_javascript_escape(apr_pool_t *pool, const char *input);
|
||||
void oidc_util_table_add_query_encoded_params(apr_pool_t *pool, apr_table_t *table, const char *params);
|
||||
apr_hash_t * oidc_util_merge_key_sets(apr_pool_t *pool, apr_hash_t *k1, apr_hash_t *k2);
|
||||
apr_byte_t oidc_util_regexp_substitute(apr_pool_t *pool, const char *input, const char *regexp, const char *replace, char **output, char **error_str);
|
||||
diff --git a/src/util.c b/src/util.c
|
||||
index 4b4e16b..f98c824 100644
|
||||
--- a/src/util.c
|
||||
+++ b/src/util.c
|
||||
@@ -369,6 +369,87 @@ char *oidc_util_html_escape(apr_pool_t *pool, const char *s) {
|
||||
return apr_pstrdup(pool, r);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * JavaScript escape a string
|
||||
+ */
|
||||
+char* oidc_util_javascript_escape(apr_pool_t *pool, const char *s) {
|
||||
+ const char *cp;
|
||||
+ char *output;
|
||||
+ size_t outputlen;
|
||||
+ int i;
|
||||
+
|
||||
+ if (s == NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ outputlen = 0;
|
||||
+ for (cp = s; *cp; cp++) {
|
||||
+ switch (*cp) {
|
||||
+ case '\'':
|
||||
+ case '"':
|
||||
+ case '\\':
|
||||
+ case '/':
|
||||
+ case 0x0D:
|
||||
+ case 0x0A:
|
||||
+ outputlen += 2;
|
||||
+ break;
|
||||
+ case '<':
|
||||
+ case '>':
|
||||
+ outputlen += 4;
|
||||
+ break;
|
||||
+ default:
|
||||
+ outputlen += 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ i = 0;
|
||||
+ output = apr_palloc(pool, outputlen + 1);
|
||||
+ for (cp = s; *cp; cp++) {
|
||||
+ switch (*cp) {
|
||||
+ case '\'':
|
||||
+ (void)strcpy(&output[i], "\\'");
|
||||
+ i += 2;
|
||||
+ break;
|
||||
+ case '"':
|
||||
+ (void)strcpy(&output[i], "\\\"");
|
||||
+ i += 2;
|
||||
+ break;
|
||||
+ case '\\':
|
||||
+ (void)strcpy(&output[i], "\\\\");
|
||||
+ i += 2;
|
||||
+ break;
|
||||
+ case '/':
|
||||
+ (void)strcpy(&output[i], "\\/");
|
||||
+ i += 2;
|
||||
+ break;
|
||||
+ case 0x0D:
|
||||
+ (void)strcpy(&output[i], "\\r");
|
||||
+ i += 2;
|
||||
+ break;
|
||||
+ case 0x0A:
|
||||
+ (void)strcpy(&output[i], "\\n");
|
||||
+ i += 2;
|
||||
+ break;
|
||||
+ case '<':
|
||||
+ (void)strcpy(&output[i], "\\x3c");
|
||||
+ i += 4;
|
||||
+ break;
|
||||
+ case '>':
|
||||
+ (void)strcpy(&output[i], "\\x3e");
|
||||
+ i += 4;
|
||||
+ break;
|
||||
+ default:
|
||||
+ output[i] = *cp;
|
||||
+ i += 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ output[i] = '\0';
|
||||
+ return output;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/*
|
||||
* get the URL scheme that is currently being accessed
|
||||
*/
|
||||
--
|
||||
2.27.0
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
Name: mod_auth_openidc
|
||||
Version: 2.3.7
|
||||
Release: 9%{?dist}
|
||||
Release: 11%{?dist}
|
||||
Summary: OpenID Connect auth module for Apache HTTP Server
|
||||
|
||||
Group: System Environment/Daemons
|
||||
@ -46,6 +46,9 @@ Patch20: 0020-prevent-open-redirect-on-refresh-token-requests-rele.patch
|
||||
Patch21: 0021-prevent-XSS-and-open-redirect-on-OIDC-session-manage.patch
|
||||
Patch22: 0022-replace-potentially-harmful-backslashes-with-forward.patch
|
||||
Patch23: 0023-apply-OIDCRedirectURLsAllowed-setting-to-target_link.patch
|
||||
Patch24: 0024-use-encrypted-JWTs-for-storing-encrypted-cache-conte.patch
|
||||
Patch25: 0025-avoid-XSS-vulnerability-when-using-OIDCPreservePost-.patch
|
||||
Patch26: 0026-Add-a-function-to-escape-Javascript-characters.patch
|
||||
|
||||
BuildRequires: gcc
|
||||
BuildRequires: httpd-devel
|
||||
@ -89,6 +92,9 @@ an OpenID Connect Relying Party and/or OAuth 2.0 Resource Server.
|
||||
%patch21 -p1
|
||||
%patch22 -p1
|
||||
%patch23 -p1
|
||||
%patch24 -p1
|
||||
%patch25 -p1
|
||||
%patch26 -p1
|
||||
|
||||
%build
|
||||
# workaround rpm-buildroot-usage
|
||||
@ -141,6 +147,13 @@ install -m 700 -d $RPM_BUILD_ROOT%{httpd_pkg_cache_dir}/cache
|
||||
%dir %attr(0700, apache, apache) %{httpd_pkg_cache_dir}/cache
|
||||
|
||||
%changelog
|
||||
* Fri Jan 28 2022 Tomas Halman <thalman@redhat.com> - 2.3.7-11
|
||||
- Resolves: rhbz#1987222 - CVE-2021-32792 XSS when using OIDCPreservePost On
|
||||
|
||||
* Fri Jan 28 2022 Tomas Halman <thalman@redhat.com> - 2.3.7-10
|
||||
- Resolves: rhbz#1987216 - CVE-2021-32791 hardcoded static IV and AAD with a
|
||||
reused key in AES GCM encryption [rhel-8] (edit)
|
||||
|
||||
* Fri Oct 29 2021 Tomas Halman <thalman@redhat.com> - 2.3.7-9
|
||||
- Resolves: rhbz#2001853 - CVE-2021-39191 open redirect by supplying a crafted URL
|
||||
in the target_link_uri parameter
|
||||
|
Loading…
Reference in New Issue
Block a user