mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 20:04:50 +00:00
manager.c: Prevent path traversal with GetConfig.
When using AMI GetConfig, it was possible to access files outside of the Asterisk configuration directory by using filenames with ".." and "./" even while live_dangerously was not enabled. This change resolves the full path and ensures we are still in the configuration directory before attempting to access the file.
This commit is contained in:
@@ -3752,12 +3752,43 @@ void astman_live_dangerously(int new_live_dangerously)
|
|||||||
live_dangerously = new_live_dangerously;
|
live_dangerously = new_live_dangerously;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check if a file is restricted or not
|
||||||
|
*
|
||||||
|
* \return 0 on success
|
||||||
|
* \return 1 on restricted file
|
||||||
|
* \return -1 on failure
|
||||||
|
*/
|
||||||
static int restrictedFile(const char *filename)
|
static int restrictedFile(const char *filename)
|
||||||
{
|
{
|
||||||
if (!live_dangerously && !strncasecmp(filename, "/", 1) &&
|
char *stripped_filename;
|
||||||
strncasecmp(filename, ast_config_AST_CONFIG_DIR, strlen(ast_config_AST_CONFIG_DIR))) {
|
RAII_VAR(char *, path, NULL, ast_free);
|
||||||
|
RAII_VAR(char *, real_path, NULL, ast_free);
|
||||||
|
|
||||||
|
if (live_dangerously) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stripped_filename = ast_strip(ast_strdupa(filename));
|
||||||
|
|
||||||
|
/* If the file path starts with '/', don't prepend ast_config_AST_CONFIG_DIR */
|
||||||
|
if (stripped_filename[0] == '/') {
|
||||||
|
real_path = realpath(stripped_filename, NULL);
|
||||||
|
} else {
|
||||||
|
if (ast_asprintf(&path, "%s/%s", ast_config_AST_CONFIG_DIR, stripped_filename) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
real_path = realpath(path, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!real_path) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ast_begins_with(real_path, ast_config_AST_CONFIG_DIR)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3770,6 +3801,7 @@ static int action_getconfig(struct mansession *s, const struct message *m)
|
|||||||
const char *category_name;
|
const char *category_name;
|
||||||
int catcount = 0;
|
int catcount = 0;
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
|
int ret = 0;
|
||||||
struct ast_category *cur_category = NULL;
|
struct ast_category *cur_category = NULL;
|
||||||
struct ast_variable *v;
|
struct ast_variable *v;
|
||||||
struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
|
struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
|
||||||
@@ -3779,9 +3811,13 @@ static int action_getconfig(struct mansession *s, const struct message *m)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restrictedFile(fn)) {
|
ret = restrictedFile(fn);
|
||||||
|
if (ret == 1) {
|
||||||
astman_send_error(s, m, "File requires escalated priveledges");
|
astman_send_error(s, m, "File requires escalated priveledges");
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (ret == -1) {
|
||||||
|
astman_send_error(s, m, "Config file not found");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = ast_config_load2(fn, "manager", config_flags);
|
cfg = ast_config_load2(fn, "manager", config_flags);
|
||||||
|
Reference in New Issue
Block a user