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
(cherry picked from commit 81f10e847e
)
This commit is contained in:
parent
120aca73ba
commit
c59eb7e6d8
|
@ -95,10 +95,13 @@ documentation_language = en_US ; Set the language you want documentation
|
||||||
; documented in extensions.conf.sample.
|
; documented in extensions.conf.sample.
|
||||||
; Default gosub.
|
; Default gosub.
|
||||||
;live_dangerously = no ; Enable the execution of 'dangerous' dialplan
|
;live_dangerously = no ; Enable the execution of 'dangerous' dialplan
|
||||||
; functions from external sources (AMI,
|
; functions and configuration file access from
|
||||||
; etc.) These functions (such as SHELL) are
|
; external sources (AMI, etc.) These functions
|
||||||
; considered dangerous because they can allow
|
; (such as SHELL) are considered dangerous
|
||||||
; privilege escalation.
|
; because they can allow privilege escalation.
|
||||||
|
; Configuration files are considered dangerous
|
||||||
|
; if they exist outside of the Asterisk
|
||||||
|
; configuration directory.
|
||||||
; Default no
|
; Default no
|
||||||
;entityid=00:11:22:33:44:55 ; Entity ID.
|
;entityid=00:11:22:33:44:55 ; Entity ID.
|
||||||
; This is in the form of a MAC address.
|
; This is in the form of a MAC address.
|
||||||
|
|
|
@ -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.
|
|
@ -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);
|
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, ...);
|
void __attribute__((format(printf, 2, 3))) astman_append(struct mansession *s, const char *fmt, ...);
|
||||||
|
|
||||||
/*! \brief Determine if a manager session ident is authenticated */
|
/*! \brief Determine if a manager session ident is authenticated */
|
||||||
|
|
|
@ -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 */
|
/*! \brief The \ref stasis_subscription for forwarding the Security topic to the AMI topic */
|
||||||
static struct stasis_forward *security_topic_forwarder;
|
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
|
#ifdef TEST_FRAMEWORK
|
||||||
/*! \brief The \ref stasis_subscription for forwarding the Test topic to the AMI topic */
|
/*! \brief The \ref stasis_subscription for forwarding the Test topic to the AMI topic */
|
||||||
static struct stasis_forward *test_suite_forwarder;
|
static struct stasis_forward *test_suite_forwarder;
|
||||||
|
@ -3610,6 +3615,29 @@ static int action_ping(struct mansession *s, const struct message *m)
|
||||||
return 0;
|
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)
|
static int action_getconfig(struct mansession *s, const struct message *m)
|
||||||
{
|
{
|
||||||
struct ast_config *cfg;
|
struct ast_config *cfg;
|
||||||
|
@ -3628,6 +3656,11 @@ static int action_getconfig(struct mansession *s, const struct message *m)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (restrictedFile(fn)) {
|
||||||
|
astman_send_error(s, m, "File requires escalated priveledges");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
cfg = ast_config_load2(fn, "manager", config_flags);
|
cfg = ast_config_load2(fn, "manager", config_flags);
|
||||||
if (cfg == CONFIG_STATUS_FILEMISSING) {
|
if (cfg == CONFIG_STATUS_FILEMISSING) {
|
||||||
astman_send_error(s, m, "Config file not found");
|
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;
|
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))) {
|
if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
|
||||||
astman_send_error(s, m, "Config file not found");
|
astman_send_error(s, m, "Config file not found");
|
||||||
return 0;
|
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");
|
astman_send_error(s, m, "Filename not specified");
|
||||||
return 0;
|
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))) {
|
if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
|
||||||
astman_send_error(s, m, "Config file not found");
|
astman_send_error(s, m, "Config file not found");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -476,6 +476,7 @@ void load_asterisk_conf(void)
|
||||||
}
|
}
|
||||||
if (!ast_opt_remote) {
|
if (!ast_opt_remote) {
|
||||||
pbx_live_dangerously(live_dangerously);
|
pbx_live_dangerously(live_dangerously);
|
||||||
|
astman_live_dangerously(live_dangerously);
|
||||||
}
|
}
|
||||||
|
|
||||||
option_debug += option_debug_new;
|
option_debug += option_debug_new;
|
||||||
|
|
Loading…
Reference in New Issue