manager: prevent file access outside of config dir

Add live_dangerously flag to manager and use this flag to
determine if a configuation file outside of AST_CONFIG_DIR
should be read.

ASTERISK-30176

Change-Id: I46b26af4047433b49ae5c8a85cb8cda806a07404
This commit is contained in:
Mike Bradeen 2022-10-03 12:54:40 -06:00 committed by Friendly Automation
parent 16a7a98643
commit 76d10ea668
5 changed files with 70 additions and 4 deletions

View File

@ -95,10 +95,13 @@ documentation_language = en_US ; Set the language you want documentation
; documented in extensions.conf.sample.
; Default gosub.
;live_dangerously = no ; Enable the execution of 'dangerous' dialplan
; functions from external sources (AMI,
; etc.) These functions (such as SHELL) are
; considered dangerous because they can allow
; privilege escalation.
; functions and configuration file access from
; external sources (AMI, etc.) These functions
; (such as SHELL) are considered dangerous
; because they can allow privilege escalation.
; Configuration files are considered dangerous
; if they exist outside of the Asterisk
; configuration directory.
; Default no
;entityid=00:11:22:33:44:55 ; Entity ID.
; This is in the form of a MAC address.

View File

@ -0,0 +1,8 @@
Subject: AMI (Asterisk Manager Interface)
Previously, GetConfig and UpdateConfig were able to access files outside of
the Asterisk configuration directory. Now this access is put behind the
live_dangerously configuration option in asterisk.conf, which is disabled by
default. If access to configuration files outside of the Asterisk configuation
directory is required via AMI, then the live_dangerously configuration option
must be set to yes.

View File

@ -350,6 +350,18 @@ void astman_send_list_complete_start(struct mansession *s, const struct message
*/
void astman_send_list_complete_end(struct mansession *s);
/*!
* \brief Enable/disable the inclusion of 'dangerous' configurations outside
* of the ast_config_AST_CONFIG_DIR
*
* This function can globally enable/disable the loading of configuration files
* outside of ast_config_AST_CONFIG_DIR.
*
* \param new_live_dangerously If true, enable the access of files outside
* ast_config_AST_CONFIG_DIR from astman.
*/
void astman_live_dangerously(int new_live_dangerously);
void __attribute__((format(printf, 2, 3))) astman_append(struct mansession *s, const char *fmt, ...);
/*! \brief Determine if a manager session ident is authenticated */

View File

@ -1491,6 +1491,11 @@ static struct stasis_forward *rtp_topic_forwarder;
/*! \brief The \ref stasis_subscription for forwarding the Security topic to the AMI topic */
static struct stasis_forward *security_topic_forwarder;
/*!
* \brief Set to true (non-zero) to globally allow all dangerous AMI actions to run
*/
static int live_dangerously;
#ifdef TEST_FRAMEWORK
/*! \brief The \ref stasis_subscription for forwarding the Test topic to the AMI topic */
static struct stasis_forward *test_suite_forwarder;
@ -3610,6 +3615,29 @@ static int action_ping(struct mansession *s, const struct message *m)
return 0;
}
void astman_live_dangerously(int new_live_dangerously)
{
if (new_live_dangerously && !live_dangerously)
{
ast_log(LOG_WARNING, "Manager Configuration load protection disabled.\n");
}
if (!new_live_dangerously && live_dangerously)
{
ast_log(LOG_NOTICE, "Manager Configuration load protection enabled.\n");
}
live_dangerously = new_live_dangerously;
}
static int restrictedFile(const char *filename)
{
if (!live_dangerously && !strncasecmp(filename, "/", 1) &&
strncasecmp(filename, ast_config_AST_CONFIG_DIR, strlen(ast_config_AST_CONFIG_DIR))) {
return 1;
}
return 0;
}
static int action_getconfig(struct mansession *s, const struct message *m)
{
struct ast_config *cfg;
@ -3628,6 +3656,11 @@ static int action_getconfig(struct mansession *s, const struct message *m)
return 0;
}
if (restrictedFile(fn)) {
astman_send_error(s, m, "File requires escalated priveledges");
return 0;
}
cfg = ast_config_load2(fn, "manager", config_flags);
if (cfg == CONFIG_STATUS_FILEMISSING) {
astman_send_error(s, m, "Config file not found");
@ -3755,6 +3788,11 @@ static int action_getconfigjson(struct mansession *s, const struct message *m)
return 0;
}
if (restrictedFile(fn)) {
astman_send_error(s, m, "File requires escalated priveledges");
return 0;
}
if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
astman_send_error(s, m, "Config file not found");
return 0;
@ -4106,6 +4144,10 @@ static int action_updateconfig(struct mansession *s, const struct message *m)
astman_send_error(s, m, "Filename not specified");
return 0;
}
if (restrictedFile(sfn) || restrictedFile(dfn)) {
astman_send_error(s, m, "File requires escalated priveledges");
return 0;
}
if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
astman_send_error(s, m, "Config file not found");
return 0;

View File

@ -476,6 +476,7 @@ void load_asterisk_conf(void)
}
if (!ast_opt_remote) {
pbx_live_dangerously(live_dangerously);
astman_live_dangerously(live_dangerously);
}
option_debug += option_debug_new;