Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2022-29967: Fix file access check for directory traversal, and fix call for callb… · babelouest/glewlwyd@e3f7245

static_compressed_inmemory_website_callback.c in Glewlwyd through 2.6.2 allows directory traversal.

CVE
#web

@@ -4,7 +4,7 @@ * * Copyright 2020-2022 Nicolas Mora [email protected] * * Version 20220425 * Version 20220428 * * The MIT License (MIT) * @@ -89,6 +89,8 @@ */ #include <pthread.h> #include <zlib.h> #include <limits.h> #include <stdlib.h> #include <string.h> #include <ulfius.h>
@@ -158,7 +160,7 @@ static void callback_static_file_uncompressed_stream_free(void * cls) { static int callback_static_file_uncompressed (const struct _u_request * request, struct _u_response * response, void * user_data) { size_t length; FILE * f; char * file_requested, * file_path, * url_dup_save; char * file_requested, * file_path, * url_dup_save, * real_path = NULL; const char * content_type; int ret = U_CALLBACK_CONTINUE;
@@ -185,34 +187,40 @@ static int callback_static_file_uncompressed (const struct _u_request * request, }
file_path = msprintf("%s/%s", ((struct _u_compressed_inmemory_website_config *)user_data)->files_path, file_requested); real_path = realpath(file_path, NULL); if (0 == o_strncmp(((struct _u_compressed_inmemory_website_config *)user_data)->files_path, real_path, o_strlen(((struct _u_compressed_inmemory_website_config *)user_data)->files_path))) { f = fopen (file_path, “rb”); if (f) { fseek (f, 0, SEEK_END); length = ftell (f); fseek (f, 0, SEEK_SET);
content_type = u_map_get_case(&((struct _u_compressed_inmemory_website_config *)user_data)->mime_types, get_filename_ext(file_requested)); if (content_type == NULL) { content_type = u_map_get(&((struct _u_compressed_inmemory_website_config *)user_data)->mime_types, “*”); y_log_message(Y_LOG_LEVEL_WARNING, "Static File Server - Unknown mime type for extension %s", get_filename_ext(file_requested)); } u_map_put(response->map_header, "Content-Type", content_type); u_map_copy_into(response->map_header, &((struct _u_compressed_inmemory_website_config *)user_data)->map_header);
f = fopen (file_path, “rb”); if (f) { fseek (f, 0, SEEK_END); length = ftell (f); fseek (f, 0, SEEK_SET);
content_type = u_map_get_case(&((struct _u_compressed_inmemory_website_config *)user_data)->mime_types, get_filename_ext(file_requested)); if (content_type == NULL) { content_type = u_map_get(&((struct _u_compressed_inmemory_website_config *)user_data)->mime_types, “*”); y_log_message(Y_LOG_LEVEL_WARNING, "Static File Server - Unknown mime type for extension %s", get_filename_ext(file_requested)); } u_map_put(response->map_header, "Content-Type", content_type); u_map_copy_into(response->map_header, &((struct _u_compressed_inmemory_website_config *)user_data)->map_header);
if (ulfius_set_stream_response(response, 200, callback_static_file_uncompressed_stream, callback_static_file_uncompressed_stream_free, length, CHUNK, f) != U_OK) { y_log_message(Y_LOG_LEVEL_ERROR, “Static File Server - Error ulfius_set_stream_response”); } } else { if (((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404 == NULL) { ret = U_CALLBACK_IGNORE; if (ulfius_set_stream_response(response, 200, callback_static_file_uncompressed_stream, callback_static_file_uncompressed_stream_free, length, CHUNK, f) != U_OK) { y_log_message(Y_LOG_LEVEL_ERROR, “Static File Server - Error ulfius_set_stream_response”); } } else { ulfius_add_header_to_response(response, "Location", ((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404); response->status = 302; if (((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404 == NULL) { ret = U_CALLBACK_IGNORE; } else { ulfius_add_header_to_response(response, "Location", ((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404); response->status = 302; } } o_free(url_dup_save); } else { response->status = 403; } o_free(file_path); o_free(url_dup_save); free(real_path); // realpath uses malloc
} else { y_log_message(Y_LOG_LEVEL_ERROR, “Static File Server - Error, user_data is NULL or inconsistent”); ret = U_CALLBACK_ERROR; @@ -290,7 +298,7 @@ int callback_static_compressed_inmemory_website (const struct _u_request * reque unsigned char * file_content, * file_content_orig = NULL; size_t length, read_length, offset, data_zip_len = 0; FILE * f; char * file_requested, * file_path, * url_dup_save, * data_zip = NULL; char * file_requested, * file_path, * url_dup_save, * data_zip = NULL, * real_path = NULL; const char * content_type;
/* @@ -328,12 +336,11 @@ int callback_static_compressed_inmemory_website (const struct _u_request * reque compress_mode = U_COMPRESS_DEFL; }

if (compress_mode != U_COMPRESS_NONE) { if (compress_mode == U_COMPRESS_GZIP && config->allow_cache_compressed && u_map_has_key(&config->gzip_files, file_requested)) { ulfius_set_binary_body_response(response, 200, u_map_get(&config->gzip_files, file_requested), u_map_get_length(&config->gzip_files, file_requested)); u_map_put(response->map_header, U_CONTENT_HEADER, U_ACCEPT_GZIP);
content_type = u_map_get_case(&config->mime_types, get_filename_ext(file_requested)); if (content_type == NULL) { content_type = u_map_get(&config->mime_types, “*”); @@ -343,7 +350,7 @@ int callback_static_compressed_inmemory_website (const struct _u_request * reque } else if (compress_mode == U_COMPRESS_DEFL && config->allow_cache_compressed && u_map_has_key(&config->deflate_files, file_requested)) { ulfius_set_binary_body_response(response, 200, u_map_get(&config->deflate_files, file_requested), u_map_get_length(&config->deflate_files, file_requested)); u_map_put(response->map_header, U_CONTENT_HEADER, U_ACCEPT_DEFLATE);
content_type = u_map_get_case(&config->mime_types, get_filename_ext(file_requested)); if (content_type == NULL) { content_type = u_map_get(&config->mime_types, “*”); @@ -352,120 +359,129 @@ int callback_static_compressed_inmemory_website (const struct _u_request * reque u_map_copy_into(response->map_header, &config->map_header); } else { file_path = msprintf("%s/%s", ((struct _u_compressed_inmemory_website_config *)user_data)->files_path, file_requested); real_path = realpath(file_path, NULL); if (0 == o_strncmp(((struct _u_compressed_inmemory_website_config *)user_data)->files_path, real_path, o_strlen(((struct _u_compressed_inmemory_website_config *)user_data)->files_path))) { if (!pthread_mutex_lock(&config->lock)) { f = fopen (file_path, “rb”); if (f) { content_type = u_map_get_case(&config->mime_types, get_filename_ext(file_requested)); if (content_type == NULL) { content_type = u_map_get(&config->mime_types, “*”); y_log_message(Y_LOG_LEVEL_WARNING, "Static File Server - Unknown mime type for extension %s", get_filename_ext(file_requested)); } if (!string_array_has_value((const char **)config->mime_types_compressed, content_type)) { compress_mode = U_COMPRESS_NONE; }
if (!pthread_mutex_lock(&config->lock)) { f = fopen (file_path, “rb”); if (f) { content_type = u_map_get_case(&config->mime_types, get_filename_ext(file_requested)); if (content_type == NULL) { content_type = u_map_get(&config->mime_types, “*”); y_log_message(Y_LOG_LEVEL_WARNING, "Static File Server - Unknown mime type for extension %s", get_filename_ext(file_requested)); } if (!string_array_has_value((const char **)config->mime_types_compressed, content_type)) { compress_mode = U_COMPRESS_NONE; }
u_map_put(response->map_header, "Content-Type", content_type); u_map_copy_into(response->map_header, &config->map_header);
fseek (f, 0, SEEK_END); offset = length = ftell (f); fseek (f, 0, SEEK_SET);
if (length) { if ((file_content_orig = file_content = o_malloc(length)) != NULL && (data_zip = o_malloc((2*length)+20)) != NULL) { defstream.zalloc = u_zalloc; defstream.zfree = u_zfree; defstream.opaque = Z_NULL; defstream.avail_in = (uInt)length; defstream.next_in = (Bytef *)file_content; while ((read_length = fread(file_content, sizeof(char), offset, f))) { file_content += read_length; offset -= read_length; }
if (compress_mode == U_COMPRESS_GZIP) { if (deflateInit2(&defstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, U_GZIP_WINDOW_BITS | U_GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY) != Z_OK) { y_log_message(Y_LOG_LEVEL_ERROR, "callback_static_compressed_inmemory_website - Error deflateInit (gzip)"); ret = U_CALLBACK_ERROR; } } else { if (deflateInit(&defstream, Z_BEST_COMPRESSION) != Z_OK) { y_log_message(Y_LOG_LEVEL_ERROR, "callback_static_compressed_inmemory_website - Error deflateInit (deflate)"); ret = U_CALLBACK_ERROR; u_map_put(response->map_header, "Content-Type", content_type); u_map_copy_into(response->map_header, &config->map_header);
fseek (f, 0, SEEK_END); offset = length = ftell (f); fseek (f, 0, SEEK_SET);
if (length) { if ((file_content_orig = file_content = o_malloc(length)) != NULL && (data_zip = o_malloc((2*length)+20)) != NULL) { defstream.zalloc = u_zalloc; defstream.zfree = u_zfree; defstream.opaque = Z_NULL; defstream.avail_in = (uInt)length; defstream.next_in = (Bytef *)file_content; while ((read_length = fread(file_content, sizeof(char), offset, f))) { file_content += read_length; offset -= read_length; } } if (ret == U_CALLBACK_CONTINUE) { do { if ((data_zip = o_realloc(data_zip, data_zip_len+_U_W_BLOCK_SIZE)) != NULL) { defstream.avail_out = _U_W_BLOCK_SIZE; defstream.next_out = ((Bytef *)data_zip)+data_zip_len; switch ((res = deflate(&defstream, Z_FINISH))) { case Z_OK: case Z_STREAM_END: case Z_BUF_ERROR: break; default: y_log_message(Y_LOG_LEVEL_ERROR, "callback_static_compressed_inmemory_website - Error deflate %d", res); ret = U_CALLBACK_ERROR; break; } data_zip_len += _U_W_BLOCK_SIZE - defstream.avail_out; } else { y_log_message(Y_LOG_LEVEL_ERROR, “callback_static_compressed_inmemory_website - Error allocating resources for data_zip”);
if (compress_mode == U_COMPRESS_GZIP) { if (deflateInit2(&defstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, U_GZIP_WINDOW_BITS | U_GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY) != Z_OK) { y_log_message(Y_LOG_LEVEL_ERROR, "callback_static_compressed_inmemory_website - Error deflateInit (gzip)"); ret = U_CALLBACK_ERROR; } } while (U_CALLBACK_CONTINUE == ret && defstream.avail_out == 0);
} else { if (deflateInit(&defstream, Z_BEST_COMPRESSION) != Z_OK) { y_log_message(Y_LOG_LEVEL_ERROR, "callback_static_compressed_inmemory_website - Error deflateInit (deflate)"); ret = U_CALLBACK_ERROR; } } if (ret == U_CALLBACK_CONTINUE) { if (compress_mode == U_COMPRESS_GZIP) { if (config->allow_cache_compressed) { u_map_put_binary(&config->gzip_files, file_requested, data_zip, 0, defstream.total_out); do { if ((data_zip = o_realloc(data_zip, data_zip_len+_U_W_BLOCK_SIZE)) != NULL) { defstream.avail_out = _U_W_BLOCK_SIZE; defstream.next_out = ((Bytef *)data_zip)+data_zip_len; switch ((res = deflate(&defstream, Z_FINISH))) { case Z_OK: case Z_STREAM_END: case Z_BUF_ERROR: break; default: y_log_message(Y_LOG_LEVEL_ERROR, "callback_static_compressed_inmemory_website - Error deflate %d", res); ret = U_CALLBACK_ERROR; break; } data_zip_len += _U_W_BLOCK_SIZE - defstream.avail_out; } else { y_log_message(Y_LOG_LEVEL_ERROR, “callback_static_compressed_inmemory_website - Error allocating resources for data_zip”); ret = U_CALLBACK_ERROR; } ulfius_set_binary_body_response(response, 200, u_map_get(&config->gzip_files, file_requested), u_map_get_length(&config->gzip_files, file_requested)); } else { if (config->allow_cache_compressed) { u_map_put_binary(&config->deflate_files, file_requested, data_zip, 0, defstream.total_out); } while (U_CALLBACK_CONTINUE == ret && defstream.avail_out == 0);
if (ret == U_CALLBACK_CONTINUE) { if (compress_mode == U_COMPRESS_GZIP) { if (config->allow_cache_compressed) { u_map_put_binary(&config->gzip_files, file_requested, data_zip, 0, defstream.total_out); } ulfius_set_binary_body_response(response, 200, u_map_get(&config->gzip_files, file_requested), u_map_get_length(&config->gzip_files, file_requested)); } else { if (config->allow_cache_compressed) { u_map_put_binary(&config->deflate_files, file_requested, data_zip, 0, defstream.total_out); } ulfius_set_binary_body_response(response, 200, u_map_get(&config->deflate_files, file_requested), u_map_get_length(&config->deflate_files, file_requested)); } ulfius_set_binary_body_response(response, 200, u_map_get(&config->deflate_files, file_requested), u_map_get_length(&config->deflate_files, file_requested)); u_map_put(response->map_header, U_CONTENT_HEADER, compress_mode==U_COMPRESS_GZIP?U_ACCEPT_GZIP:U_ACCEPT_DEFLATE); } u_map_put(response->map_header, U_CONTENT_HEADER, compress_mode==U_COMPRESS_GZIP?U_ACCEPT_GZIP:U_ACCEPT_DEFLATE); } deflateEnd(&defstream); o_free(data_zip); } else { y_log_message(Y_LOG_LEVEL_ERROR, “callback_static_compressed_inmemory_website - Error allocating resource for file_content or data_zip”); ret = U_CALLBACK_ERROR; } deflateEnd(&defstream); o_free(data_zip); o_free(file_content_orig); } fclose(f); } else { if (((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404 == NULL) { ret = U_CALLBACK_IGNORE; } else { y_log_message(Y_LOG_LEVEL_ERROR, “callback_static_compressed_inmemory_website - Error allocating resource for file_content or data_zip”); ret = U_CALLBACK_ERROR; ulfius_add_header_to_response(response, "Location", ((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404); response->status = 302; } o_free(file_content_orig); } fclose(f); pthread_mutex_unlock(&config->lock); } else { if (((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404 == NULL) { ret = U_CALLBACK_IGNORE; } else { ulfius_add_header_to_response(response, "Location", ((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404); response->status = 302; } y_log_message(Y_LOG_LEVEL_ERROR, “callback_static_compressed_inmemory_website - Error pthread_lock_mutex”); ret = U_CALLBACK_ERROR; } pthread_mutex_unlock(&config->lock); } else { y_log_message(Y_LOG_LEVEL_ERROR, “callback_static_compressed_inmemory_website - Error pthread_lock_mutex”); ret = U_CALLBACK_ERROR; response->status = 403; } o_free(file_path); free(real_path); // realpath uses malloc } } else { ret = callback_static_file_uncompressed(request, response, user_data); } free_string_array(accept_list); } else { ret = callback_static_file_uncompressed(request, response, user_data); } } else { ret = callback_static_file_uncompressed(request, response, user_data); } o_free(url_dup_save); }

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907