From 2ff0b05d116df54613fdaf71ac7bbfbdf0c985b1 Mon Sep 17 00:00:00 2001 From: Tomas Halman Date: Wed, 17 Apr 2024 10:30:19 +0200 Subject: [PATCH] CVE-2024-24814 and race condition in cache handling Resolves: RHEL-36492 Race condition in mod_auth_openidc filecache Resolves: RHEL-25421 mod_auth_openidc: DoS when using `OIDCSessionType client-cookie` and manipulating cookies (CVE-2024-24814) --- 0003-CVE-2024-24814.patch | 46 +++++++++++++++++++ 0004-race-condition.patch | 95 +++++++++++++++++++++++++++++++++++++++ mod_auth_openidc.spec | 16 +++++-- 3 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 0003-CVE-2024-24814.patch create mode 100644 0004-race-condition.patch diff --git a/0003-CVE-2024-24814.patch b/0003-CVE-2024-24814.patch new file mode 100644 index 0000000..eeadcb9 --- /dev/null +++ b/0003-CVE-2024-24814.patch @@ -0,0 +1,46 @@ +diff -up mod_auth_openidc-2.4.9.4/src/util.c.orig mod_auth_openidc-2.4.9.4/src/util.c +--- mod_auth_openidc-2.4.9.4/src/util.c.orig 2024-02-29 17:54:55.939797412 +0100 ++++ mod_auth_openidc-2.4.9.4/src/util.c 2024-02-29 18:01:12.042842605 +0100 +@@ -1270,25 +1270,24 @@ static char* oidc_util_get_chunk_cookie_ + */ + char* oidc_util_get_chunked_cookie(request_rec *r, const char *cookieName, + int chunkSize) { +- char *cookieValue = NULL; +- char *chunkValue = NULL; +- int i = 0; +- if (chunkSize == 0) { +- cookieValue = oidc_util_get_cookie(r, cookieName); +- } else { +- int chunkCount = oidc_util_get_chunked_count(r, cookieName); +- if (chunkCount > 0) { +- cookieValue = ""; +- for (i = 0; i < chunkCount; i++) { +- chunkValue = oidc_util_get_cookie(r, +- oidc_util_get_chunk_cookie_name(r, cookieName, i)); +- if (chunkValue != NULL) +- cookieValue = apr_psprintf(r->pool, "%s%s", cookieValue, +- chunkValue); +- } +- } else { +- cookieValue = oidc_util_get_cookie(r, cookieName); ++ char *cookieValue = NULL, *chunkValue = NULL; ++ int chunkCount = 0, i = 0; ++ if (chunkSize == 0) ++ return oidc_util_get_cookie(r, cookieName); ++ chunkCount = oidc_util_get_chunked_count(r, cookieName); ++ if (chunkCount == 0) ++ return oidc_util_get_cookie(r, cookieName); ++ if ((chunkCount < 0) || (chunkCount > 99)) { ++ oidc_warn(r, "chunk count out of bounds: %d", chunkCount); ++ return NULL; ++ } ++ for (i = 0; i < chunkCount; i++) { ++ chunkValue = oidc_util_get_cookie(r, oidc_util_get_chunk_cookie_name(r, cookieName, i)); ++ if (chunkValue == NULL) { ++ oidc_warn(r, "could not find chunk %d; aborting", i); ++ break; + } ++ cookieValue = apr_psprintf(r->pool, "%s%s", cookieValue ? cookieValue : "", chunkValue); + } + return cookieValue; + } diff --git a/0004-race-condition.patch b/0004-race-condition.patch new file mode 100644 index 0000000..c93f0a3 --- /dev/null +++ b/0004-race-condition.patch @@ -0,0 +1,95 @@ +diff -up mod_auth_openidc-2.4.10/src/cache/file.c.orig mod_auth_openidc-2.4.10/src/cache/file.c +--- mod_auth_openidc-2.4.10/src/cache/file.c.orig 2024-04-16 11:12:38.942552103 +0200 ++++ mod_auth_openidc-2.4.10/src/cache/file.c 2024-04-16 11:13:09.890588209 +0200 +@@ -329,8 +329,10 @@ static apr_status_t oidc_cache_file_clea + } + + /* read the header with cache metadata info */ ++ apr_file_lock(fd, APR_FLOCK_EXCLUSIVE); + rc = oidc_cache_file_read(r, path, fd, &info, + sizeof(oidc_cache_file_info_t)); ++ apr_file_unlock(fd); + apr_file_close(fd); + + if (rc == APR_SUCCESS) { +@@ -372,14 +374,15 @@ static apr_status_t oidc_cache_file_clea + /* + * write a value for the specified key to the cache + */ +-static apr_byte_t oidc_cache_file_set(request_rec *r, const char *section, +- const char *key, const char *value, apr_time_t expiry) { ++static apr_byte_t oidc_cache_file_set(request_rec *r, const char *section, const char *key, ++ const char *value, apr_time_t expiry) { + apr_file_t *fd = NULL; + apr_status_t rc = APR_SUCCESS; + char s_err[128]; + + /* get the fully qualified path to the cache file based on the key name */ +- const char *path = oidc_cache_file_path(r, section, key); ++ const char *target = oidc_cache_file_path(r, section, key); ++ const char *path = apr_psprintf(r->pool, "%s.tmp", target); + + /* only on writes (not on reads) we clean the cache first (if not done recently) */ + oidc_cache_file_clean(r); +@@ -387,24 +390,22 @@ static apr_byte_t oidc_cache_file_set(re + /* just remove cache file if value is NULL */ + if (value == NULL) { + if ((rc = apr_file_remove(path, r->pool)) != APR_SUCCESS) { +- oidc_error(r, "could not delete cache file \"%s\" (%s)", path, +- apr_strerror(rc, s_err, sizeof(s_err))); ++ oidc_error(r, "could not delete cache file \"%s\" (%s)", path, apr_strerror(rc, s_err, sizeof(s_err))); + } + return TRUE; + } + + /* try to open the cache file for writing, creating it if it does not exist */ +- if ((rc = apr_file_open(&fd, path, +- (APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE), +- APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) { +- oidc_error(r, "cache file \"%s\" could not be opened (%s)", path, +- apr_strerror(rc, s_err, sizeof(s_err))); ++ if ((rc = apr_file_open(&fd, path, (APR_FOPEN_WRITE | APR_FOPEN_CREATE), ++ APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) { ++ oidc_error(r, "cache file \"%s\" could not be opened (%s)", path, apr_strerror(rc, s_err, sizeof(s_err))); + return FALSE; + } + + /* lock the file and move the write pointer to the start of it */ + apr_file_lock(fd, APR_FLOCK_EXCLUSIVE); + apr_off_t begin = 0; ++ apr_file_trunc(fd, begin); + apr_file_seek(fd, APR_SET, &begin); + + /* construct the metadata for this cache entry in the header info */ +@@ -413,22 +414,24 @@ static apr_byte_t oidc_cache_file_set(re + info.len = strlen(value) + 1; + + /* write the header */ +- if ((rc = oidc_cache_file_write(r, path, fd, &info, +- sizeof(oidc_cache_file_info_t))) != APR_SUCCESS) ++ if ((rc = oidc_cache_file_write(r, path, fd, &info, sizeof(oidc_cache_file_info_t))) ++ != APR_SUCCESS) + return FALSE; + + /* next write the value */ +- rc = oidc_cache_file_write(r, path, fd, (void *) value, info.len); ++ rc = oidc_cache_file_write(r, path, fd, (void*) value, info.len); + + /* unlock and close the written file */ + apr_file_unlock(fd); + apr_file_close(fd); + ++ if (rename(path, target) != 0) { ++ oidc_error(r, "cache file: %s could not be renamed to: %s", path, target); ++ return FALSE; ++ } ++ + /* log our success/failure */ +- oidc_debug(r, +- "%s entry for key \"%s\" in file of %" APR_SIZE_T_FMT " bytes", +- (rc == APR_SUCCESS) ? "successfully stored" : "could not store", +- key, info.len); ++ oidc_debug(r, "%s entry for key \"%s\" in file of %" APR_SIZE_T_FMT " bytes", (rc == APR_SUCCESS) ? "successfully stored" : "could not store", key, info.len); + + return (rc == APR_SUCCESS); + } diff --git a/mod_auth_openidc.spec b/mod_auth_openidc.spec index 792ab92..fc9dd63 100644 --- a/mod_auth_openidc.spec +++ b/mod_auth_openidc.spec @@ -15,14 +15,16 @@ Name: mod_auth_openidc Version: 2.4.9.4 -Release: 5%{?dist} +Release: 6%{?dist} Summary: OpenID Connect auth module for Apache HTTP Server License: ASL 2.0 URL: https://github.com/zmartzone/mod_auth_openidc Source0: https://github.com/zmartzone/mod_auth_openidc/archive/v%{version}.tar.gz -Patch0: 0001-CVE-2022-23527.patch -Patch1: 0002-CVE-2023-28625.patch +Patch1: 0001-CVE-2022-23527.patch +Patch2: 0002-CVE-2023-28625.patch +Patch3: 0003-CVE-2024-24814.patch +Patch4: 0004-race-condition.patch BuildRequires: gcc BuildRequires: httpd-devel @@ -98,6 +100,12 @@ install -m 700 -d $RPM_BUILD_ROOT%{httpd_pkg_cache_dir}/cache %dir %attr(0700, apache, apache) %{httpd_pkg_cache_dir}/cache %changelog +* Fri Apr 12 2024 Tomas Halman - 2.4.9.4-6 +- Resolves: RHEL-36492 Race condition in mod_auth_openidc filecache +- Resolves: RHEL-25421 mod_auth_openidc: DoS when using + `OIDCSessionType client-cookie` and manipulating cookies + (CVE-2024-24814) + * Tue Apr 25 2023 Tomas Halman - 2.4.9.4-5 Related: rhbz#2141850 - fix cjose version dependency @@ -108,7 +116,7 @@ install -m 700 -d $RPM_BUILD_ROOT%{httpd_pkg_cache_dir}/cache - Resolves: rhbz#2184144 - CVE-2023-28625 NULL pointer dereference when OIDCStripCookies is set and a crafted Cookie header is supplied -* Thu Feb 21 2023 Tomas Halman - 2.4.9.4-2 +* Tue Feb 21 2023 Tomas Halman - 2.4.9.4-2 - Resolves: rhbz#2153659 - CVE-2022-23527 - Open Redirect in oidc_validate_redirect_url() using tab character