Commit a1c7ab47ca for asterisk.org
commit a1c7ab47ca14dc41822bf5f44a5fd5cb563daa68
Author: Mike Bradeen <mbradeen@sangoma.com>
Date: Thu Jan 15 13:52:30 2026 -0700
ast_coredumper: check ast_debug_tools.conf permissions
Prevent ast_coredumper from using ast_debug_tools.conf files that are
not owned by root or are writable by other users or groups.
Prevent ast_logescalator and ast_loggrabber from doing the same if
they are run as root.
Resolves: #GHSA-rvch-3jmx-3jf3
UserNote: ast_debug_tools.conf must be owned by root and not be
writable by other users or groups to be used by ast_coredumper or
by ast_logescalator or ast_loggrabber when run as root.
diff --git a/contrib/scripts/ast_coredumper b/contrib/scripts/ast_coredumper
index ad752be068..2d8ea76726 100755
--- a/contrib/scripts/ast_coredumper
+++ b/contrib/scripts/ast_coredumper
@@ -42,11 +42,9 @@ COMMANDLINE_COREDUMPS=false
# Read config files from most important to least important.
# Variables set on the command line or environment always take precedence.
-# shellcheck disable=SC1091
-[ -f ./ast_debug_tools.conf ] && source ./ast_debug_tools.conf
-# shellcheck disable=SC1090
-[ -f ~/ast_debug_tools.conf ] && source ~/ast_debug_tools.conf
-[ -f /etc/asterisk/ast_debug_tools.conf ] && source /etc/asterisk/ast_debug_tools.conf
+safe_source_config ./ast_debug_tools.conf
+safe_source_config ~/ast_debug_tools.conf
+safe_source_config /etc/asterisk/ast_debug_tools.conf
if [ -n "${DATEFORMAT}" ] ; then
err <<-EOF
@@ -432,6 +430,43 @@ check_gdb() {
fi
}
+# Function to safely source a config file with security checks
+# This prevents privilege escalation by ensuring config files are
+# owned by root and not writable by group or others
+safe_source_config() {
+ local config_file="$1"
+
+ # Return if file doesn't exist
+ [ -f "$config_file" ] || return 0
+
+ # Get the absolute path
+ config_file=$(readlink -f "$config_file")
+
+ # Get file owner UID and permissions
+ local file_stat
+ file_stat=$(stat -c "%u %a" "$config_file" 2>/dev/null) || return 0
+ local owner_uid=${file_stat%% *}
+ local perms=${file_stat##* }
+
+ # File must be owned by root (UID 0)
+ if [ "$owner_uid" -ne 0 ]; then
+ err "Config file $config_file is not owned by root. Skipping for security." >&2
+ return 1
+ fi
+
+ # File must not be writable by group or others (check group-write and other-write bits)
+ # Extract the group and other permission digits
+ local group_perms=$((perms / 10 % 10))
+ local other_perms=$((perms % 10))
+
+ if [ $((group_perms & 2)) -ne 0 ] || [ $((other_perms & 2)) -ne 0 ]; then
+ err "Config file $config_file is writable by group or others. Skipping for security." >&2
+ return 1
+ fi
+
+ source "$config_file"
+}
+
# shellcheck disable=SC2317
find_pid() {
if [ -n "$PID" ] ; then
diff --git a/contrib/scripts/ast_logescalator b/contrib/scripts/ast_logescalator
index b5a44ccefe..a4eced8eae 100755
--- a/contrib/scripts/ast_logescalator
+++ b/contrib/scripts/ast_logescalator
@@ -127,10 +127,51 @@ declare -A DEBUG_COMMANDS=(
VERBOSE_LEVELS="NOTICE,WARNING,ERROR,VERBOSE"
DEBUG_LEVELS="DEBUG"
+# Function to safely source a config file with security checks
+# This prevents privilege escalation by ensuring config files are
+# owned by root and not writable by group or others when running as root
+safe_source_config() {
+ local config_file="$1"
+
+ # Return if file doesn't exist
+ [ -f "$config_file" ] || return 0
+
+ # Get the absolute path
+ config_file=$(readlink -f "$config_file")
+
+ # Check if running as root (effective UID is 0)
+ if [ $EUID -eq 0 ]; then
+ # Running as root - apply strict security checks
+ # Get file owner UID and permissions
+ local file_stat
+ file_stat=$(stat -c "%u %a" "$config_file" 2>/dev/null) || return 0
+ local owner_uid=${file_stat%% *}
+ local perms=${file_stat##* }
+
+ # File must be owned by root (UID 0)
+ if [ "$owner_uid" -ne 0 ]; then
+ echo "WARNING: Config file $config_file is not owned by root. Skipping for security." >&2
+ return 1
+ fi
+
+ # File must not be writable by group or others (check group-write and other-write bits)
+ # Extract the group and other permission digits
+ local group_perms=$((perms / 10 % 10))
+ local other_perms=$((perms % 10))
+
+ if [ $((group_perms & 2)) -ne 0 ] || [ $((other_perms & 2)) -ne 0 ]; then
+ echo "WARNING: Config file $config_file is writable by group or others. Skipping for security." >&2
+ return 1
+ fi
+ fi
+
+ source "$config_file"
+}
+
# Read config files from least important to most important
-[ -f /etc/asterisk/ast_debug_tools.conf ] && source /etc/asterisk/ast_debug_tools.conf
-[ -f ~/ast_debug_tools.conf ] && source ~/ast_debug_tools.conf
-[ -f ./ast_debug_tools.conf ] && source ./ast_debug_tools.conf
+safe_source_config /etc/asterisk/ast_debug_tools.conf
+safe_source_config ~/ast_debug_tools.conf
+safe_source_config ./ast_debug_tools.conf
DATEFORMAT=${DATEFORMAT:-'date +%FT%H-%M-%S%z'}
UNIQUEID=$($DATEFORMAT)
diff --git a/contrib/scripts/ast_loggrabber b/contrib/scripts/ast_loggrabber
index b549ec329a..0683dfd991 100755
--- a/contrib/scripts/ast_loggrabber
+++ b/contrib/scripts/ast_loggrabber
@@ -101,10 +101,51 @@ append_logfiles=false
declare -a LOGFILES
declare -a ARGS_LOGFILES
+# Function to safely source a config file with security checks
+# This prevents privilege escalation by ensuring config files are
+# owned by root and not writable by group or others when running as root
+safe_source_config() {
+ local config_file="$1"
+
+ # Return if file doesn't exist
+ [ -f "$config_file" ] || return 0
+
+ # Get the absolute path
+ config_file=$(readlink -f "$config_file")
+
+ # Check if running as root (effective UID is 0)
+ if [ $EUID -eq 0 ]; then
+ # Running as root - apply strict security checks
+ # Get file owner UID and permissions
+ local file_stat
+ file_stat=$(stat -c "%u %a" "$config_file" 2>/dev/null) || return 0
+ local owner_uid=${file_stat%% *}
+ local perms=${file_stat##* }
+
+ # File must be owned by root (UID 0)
+ if [ "$owner_uid" -ne 0 ]; then
+ echo "WARNING: Config file $config_file is not owned by root. Skipping for security." >&2
+ return 1
+ fi
+
+ # File must not be writable by group or others (check group-write and other-write bits)
+ # Extract the group and other permission digits
+ local group_perms=$((perms / 10 % 10))
+ local other_perms=$((perms % 10))
+
+ if [ $((group_perms & 2)) -ne 0 ] || [ $((other_perms & 2)) -ne 0 ]; then
+ echo "WARNING: Config file $config_file is writable by group or others. Skipping for security." >&2
+ return 1
+ fi
+ fi
+
+ source "$config_file"
+}
+
# Read config files from least important to most important
-[ -f /etc/asterisk/ast_debug_tools.conf ] && source /etc/asterisk/ast_debug_tools.conf
-[ -f ~/ast_debug_tools.conf ] && source ~/ast_debug_tools.conf
-[ -f ./ast_debug_tools.conf ] && source ./ast_debug_tools.conf
+safe_source_config /etc/asterisk/ast_debug_tools.conf
+safe_source_config ~/ast_debug_tools.conf
+safe_source_config ./ast_debug_tools.conf
if [ ${#LOGFILES[@]} -eq 0 ] ; then
LOGFILES+=(/var/log/asterisk/messages* /var/log/asterisk/queue* \
@@ -178,15 +219,14 @@ df=${tarball_uniqueid:-$(${DATEFORMAT})}
# Extract the Python timestamp conver script from the end of this
# script and save it to /tmp/.ast_tsconvert.py
-ss=`egrep -n "^#@@@SCRIPTSTART@@@" $0 |cut -f1 -d:`
-tail -n +${ss} $0 >/tmp/.ast_tsconvert.py
+install -m 0600 /dev/stdin /tmp/.ast_tsconvert.py < <(sed '1,/^#@@@SCRIPTSTART@@@/ d' "$0")
tmpdir=$(mktemp -d)
if [ -z "$tmpdir" ] ; then
echo "${prog}: Unable to create temporary directory."
exit 1
fi
-trap "rm -rf $tmpdir" EXIT
+trap "rm -rf $tmpdir /tmp/.ast_tsconvert.py" EXIT
tardir=asterisk-${df}.logfiles
# Now iterate over the logfiles