From e19da5d86f118bf723ab8d5ac388d932b01b705c Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Wed, 25 Sep 2024 13:05:58 -0500 Subject: [PATCH] manager.c: Restrict ModuleLoad to the configured modules directory. When using the ModuleLoad AMI action, it was possible to traverse upwards through the directories to files outside of the configured modules directory. We decided it would be best to restrict access to modules exclusively in the configured directory. You will now get an error when the specified module is outside of this limitation. Fixes: #897 UserNote: The ModuleLoad AMI action now restricts modules to the configured modules directory. --- main/manager.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/main/manager.c b/main/manager.c index 225b7e3a67..fdf64d52b2 100644 --- a/main/manager.c +++ b/main/manager.c @@ -6682,6 +6682,42 @@ static int manager_modulecheck(struct mansession *s, const struct message *m) return 0; } +/** + * \brief Check if the given file path is in the modules dir or not + * + * \note When the module is being loaded / reloaded / unloaded, the modules dir is + * automatically prepended + * + * \return 1 if inside modules dir + * \return 0 if outside modules dir + * \return -1 on failure + */ +static int file_in_modules_dir(const char *filename) +{ + char *stripped_filename; + RAII_VAR(char *, path, NULL, ast_free); + RAII_VAR(char *, real_path, NULL, ast_free); + + /* Don't bother checking */ + if (live_dangerously) { + return 1; + } + + stripped_filename = ast_strip(ast_strdupa(filename)); + + /* Always prepend the modules dir since that is what the code does for ModuleLoad */ + if (ast_asprintf(&path, "%s/%s", ast_config_AST_MODULE_DIR, stripped_filename) == -1) { + return -1; + } + + real_path = realpath(path, NULL); + if (!real_path) { + return -1; + } + + return ast_begins_with(real_path, ast_config_AST_MODULE_DIR); +} + static int manager_moduleload(struct mansession *s, const struct message *m) { int res; @@ -6696,6 +6732,15 @@ static int manager_moduleload(struct mansession *s, const struct message *m) astman_send_error(s, m, "Need module name"); } + res = file_in_modules_dir(module); + if (res == 0) { + astman_send_error(s, m, "Module must be in the configured modules directory."); + return 0; + } else if (res == -1) { + astman_send_error(s, m, "Module not found."); + return 0; + } + if (!strcasecmp(loadtype, "load")) { res = ast_load_resource(module); if (res) { @@ -6748,8 +6793,9 @@ static int manager_moduleload(struct mansession *s, const struct message *m) ast_module_reload(NULL); /* Reload all modules */ astman_send_ack(s, m, "All modules reloaded"); } - } else + } else { astman_send_error(s, m, "Incomplete ModuleLoad action."); + } return 0; }