mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-13 05:18:55 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81bfe0a62b | ||
|
|
bbe68db10a |
@@ -1 +1 @@
|
||||
ChangeLogs/ChangeLog-20.9.1.md
|
||||
ChangeLogs/ChangeLog-20.9.2.md
|
||||
65
ChangeLogs/ChangeLog-20.9.2.md
Normal file
65
ChangeLogs/ChangeLog-20.9.2.md
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
## Change Log for Release asterisk-20.9.2
|
||||
|
||||
### Links:
|
||||
|
||||
- [Full ChangeLog](https://downloads.asterisk.org/pub/telephony/asterisk/releases/ChangeLog-20.9.2.md)
|
||||
- [GitHub Diff](https://github.com/asterisk/asterisk/compare/20.9.1...20.9.2)
|
||||
- [Tarball](https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20.9.2.tar.gz)
|
||||
- [Downloads](https://downloads.asterisk.org/pub/telephony/asterisk)
|
||||
|
||||
### Summary:
|
||||
|
||||
- Commits: 1
|
||||
- Commit Authors: 1
|
||||
- Issues Resolved: 0
|
||||
- Security Advisories Resolved: 1
|
||||
- [GHSA-c4cg-9275-6w44](https://github.com/asterisk/asterisk/security/advisories/GHSA-c4cg-9275-6w44): Write=originate, is sufficient permissions for code execution / System() dialplan
|
||||
|
||||
### User Notes:
|
||||
|
||||
|
||||
### Upgrade Notes:
|
||||
|
||||
|
||||
### Commit Authors:
|
||||
|
||||
- George Joseph: (1)
|
||||
|
||||
## Issue and Commit Detail:
|
||||
|
||||
### Closed Issues:
|
||||
|
||||
- !GHSA-c4cg-9275-6w44: Write=originate, is sufficient permissions for code execution / System() dialplan
|
||||
|
||||
### Commits By Author:
|
||||
|
||||
- #### George Joseph (1):
|
||||
- manager.c: Add entries to Originate blacklist
|
||||
|
||||
|
||||
### Commit List:
|
||||
|
||||
- manager.c: Add entries to Originate blacklist
|
||||
|
||||
### Commit Details:
|
||||
|
||||
#### manager.c: Add entries to Originate blacklist
|
||||
Author: George Joseph
|
||||
Date: 2024-07-22
|
||||
|
||||
Added Reload and DBdeltree to the list of dialplan application that
|
||||
can't be executed via the Originate manager action without also
|
||||
having write SYSTEM permissions.
|
||||
|
||||
Added CURL, DB*, FILE, ODBC and REALTIME* to the list of dialplan
|
||||
functions that can't be executed via the Originate manager action
|
||||
without also having write SYSTEM permissions.
|
||||
|
||||
If the Queue application is attempted to be run by the Originate
|
||||
manager action and an AGI parameter is specified in the app data,
|
||||
it'll be rejected unless the manager user has either the AGI or
|
||||
SYSTEM permissions.
|
||||
|
||||
Resolves: #GHSA-c4cg-9275-6w44
|
||||
|
||||
161
main/manager.c
161
main/manager.c
@@ -6325,6 +6325,145 @@ aocmessage_cleanup:
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct originate_permissions_entry {
|
||||
const char *search;
|
||||
int permission;
|
||||
int (*searchfn)(const char *app, const char *data, const char *search);
|
||||
};
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Check if the application is allowed for Originate
|
||||
*
|
||||
* \param app The "app" parameter
|
||||
* \param data The "appdata" parameter (ignored)
|
||||
* \param search The search string
|
||||
* \retval 1 Match
|
||||
* \retval 0 No match
|
||||
*/
|
||||
static int app_match(const char *app, const char *data, const char *search)
|
||||
{
|
||||
/*
|
||||
* We use strcasestr so we don't have to trim any blanks
|
||||
* from the front or back of the string.
|
||||
*/
|
||||
return !!(strcasestr(app, search));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Check if the appdata is allowed for Originate
|
||||
*
|
||||
* \param app The "app" parameter (ignored)
|
||||
* \param data The "appdata" parameter
|
||||
* \param search The search string
|
||||
* \retval 1 Match
|
||||
* \retval 0 No match
|
||||
*/
|
||||
static int appdata_match(const char *app, const char *data, const char *search)
|
||||
{
|
||||
return !!(strstr(data, search));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Check if the Queue application is allowed for Originate
|
||||
*
|
||||
* It's only allowed if there's no AGI parameter set
|
||||
*
|
||||
* \param app The "app" parameter
|
||||
* \param data The "appdata" parameter
|
||||
* \param search The search string
|
||||
* \retval 1 Match
|
||||
* \retval 0 No match
|
||||
*/
|
||||
static int queue_match(const char *app, const char *data, const char *search)
|
||||
{
|
||||
char *parse;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(queuename);
|
||||
AST_APP_ARG(options);
|
||||
AST_APP_ARG(url);
|
||||
AST_APP_ARG(announceoverride);
|
||||
AST_APP_ARG(queuetimeoutstr);
|
||||
AST_APP_ARG(agi);
|
||||
AST_APP_ARG(gosub);
|
||||
AST_APP_ARG(rule);
|
||||
AST_APP_ARG(position);
|
||||
);
|
||||
|
||||
if (!strcasestr(app, "queue")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
parse = ast_strdupa(data);
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
/*
|
||||
* The Queue application is fine unless the AGI parameter is set.
|
||||
* If it is, we need to check the user's permissions.
|
||||
*/
|
||||
return !ast_strlen_zero(args.agi);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Originate application and application data are passed
|
||||
* to each searchfn in the list. If a searchfn returns true
|
||||
* and the user's permissions don't include the permissions specified
|
||||
* in the list entry, the Originate action will be denied.
|
||||
*
|
||||
* If no searchfn returns true, the Originate action is allowed.
|
||||
*/
|
||||
static struct originate_permissions_entry originate_app_permissions[] = {
|
||||
/*
|
||||
* The app_match function checks if the search string is
|
||||
* anywhere in the app parameter. The check is case-insensitive.
|
||||
*/
|
||||
{ "agi", EVENT_FLAG_SYSTEM, app_match },
|
||||
{ "dbdeltree", EVENT_FLAG_SYSTEM, app_match },
|
||||
{ "exec", EVENT_FLAG_SYSTEM, app_match },
|
||||
{ "externalivr", EVENT_FLAG_SYSTEM, app_match },
|
||||
{ "mixmonitor", EVENT_FLAG_SYSTEM, app_match },
|
||||
{ "originate", EVENT_FLAG_SYSTEM, app_match },
|
||||
{ "reload", EVENT_FLAG_SYSTEM, app_match },
|
||||
{ "system", EVENT_FLAG_SYSTEM, app_match },
|
||||
/*
|
||||
* Since the queue_match function specifically checks
|
||||
* for the presence of the AGI parameter, we'll allow
|
||||
* the call if the user has either the AGI or SYSTEM
|
||||
* permission.
|
||||
*/
|
||||
{ "queue", EVENT_FLAG_AGI | EVENT_FLAG_SYSTEM, queue_match },
|
||||
/*
|
||||
* The appdata_match function checks if the search string is
|
||||
* anywhere in the appdata parameter. Unlike app_match,
|
||||
* the check is case-sensitive. These are generally
|
||||
* dialplan functions.
|
||||
*/
|
||||
{ "CURL", EVENT_FLAG_SYSTEM, appdata_match },
|
||||
{ "DB", EVENT_FLAG_SYSTEM, appdata_match },
|
||||
{ "EVAL", EVENT_FLAG_SYSTEM, appdata_match },
|
||||
{ "FILE", EVENT_FLAG_SYSTEM, appdata_match },
|
||||
{ "ODBC", EVENT_FLAG_SYSTEM, appdata_match },
|
||||
{ "REALTIME", EVENT_FLAG_SYSTEM, appdata_match },
|
||||
{ "SHELL", EVENT_FLAG_SYSTEM, appdata_match },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
static int is_originate_app_permitted(const char *app, const char *data,
|
||||
int permission)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; originate_app_permissions[i].search; i++) {
|
||||
if (originate_app_permissions[i].searchfn(app, data, originate_app_permissions[i].search)) {
|
||||
return !!(permission & originate_app_permissions[i].permission);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int action_originate(struct mansession *s, const struct message *m)
|
||||
{
|
||||
const char *name = astman_get_header(m, "Channel");
|
||||
@@ -6418,26 +6557,8 @@ static int action_originate(struct mansession *s, const struct message *m)
|
||||
}
|
||||
|
||||
if (!ast_strlen_zero(app) && s->session) {
|
||||
int bad_appdata = 0;
|
||||
/* To run the System application (or anything else that goes to
|
||||
* shell), you must have the additional System privilege */
|
||||
if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
|
||||
&& (
|
||||
strcasestr(app, "system") || /* System(rm -rf /)
|
||||
TrySystem(rm -rf /) */
|
||||
strcasestr(app, "exec") || /* Exec(System(rm -rf /))
|
||||
TryExec(System(rm -rf /)) */
|
||||
strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /)
|
||||
EAGI(/bin/rm,-rf /) */
|
||||
strcasestr(app, "mixmonitor") || /* MixMonitor(blah,,rm -rf) */
|
||||
strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf) */
|
||||
strcasestr(app, "originate") || /* Originate(Local/1234,app,System,rm -rf) */
|
||||
(strstr(appdata, "SHELL") && (bad_appdata = 1)) || /* NoOp(${SHELL(rm -rf /)}) */
|
||||
(strstr(appdata, "EVAL") && (bad_appdata = 1)) /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
|
||||
)) {
|
||||
char error_buf[64];
|
||||
snprintf(error_buf, sizeof(error_buf), "Originate Access Forbidden: %s", bad_appdata ? "Data" : "Application");
|
||||
astman_send_error(s, m, error_buf);
|
||||
if (!is_originate_app_permitted(app, appdata, s->session->writeperm)) {
|
||||
astman_send_error(s, m, "Originate Access Forbidden: app or data blacklisted");
|
||||
res = 0;
|
||||
goto fast_orig_cleanup;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user