應對 Linux sudo 本地提權漏洞:離線升級 Sudo 到安全版本
一、引言
在 Linux 系統中,sudo(superuser do)是一個非常重要的工具,它允許授權用戶以超級用戶(root)的權限執行命令。然而,就像其他軟件一樣,sudo 也可能存在安全漏洞,其中本地提權漏洞是比較嚴重的一種。攻擊者可以利用這些漏洞在本地系統上提升自己的權限,從而對系統造成嚴重的破壞。為了保障系統的安全,及時升級 sudo 到安全版本是非常必要的。本文將詳細介紹如何使用一個 shell 腳本將 sudo 升級到 1.9.17p1 版本,以修復潛在的本地提權漏洞。
二、漏洞概述
Linux sudo 本地提權漏洞可能會讓本地用戶繞過正常的權限檢查機制,獲取 root 權限。這種漏洞一旦被利用,攻擊者可以執行任意命令,修改系統配置,竊取敏感信息等,給系統安全帶來極大的威脅。因此,系統管理員需要密切關注 sudo 的安全更新,并及時進行升級。
三、升級腳本詳解
1. 腳本功能概述
該腳本的主要功能是將系統中的 sudo 升級到 1.9.17p1 版本。它會完成以下幾個步驟:
- 解壓 sudo 源碼壓縮包
- 備份原有的 sudo 可執行文件
- 替換 sudo 可執行文件和相關動態庫及插件
- 更新動態庫緩存
- 配置
/etc/sudo.conf
文件 - 驗證升級結果
編譯好的包
https://wwyq.lanzouo.com/iHNZN307lx8d
密碼:i33z
2. 腳本代碼及詳細解釋
#!/bin/bash# 配置變量
ARCHIVE="sudo1.9.17p1.tar.gz"
EXTRACT_PATH="/root/usr/local"
SUDO_DIR="$EXTRACT_PATH/sudo-1.9.17p1"
SUDO_BIN="$SUDO_DIR/bin/sudo"
SUDO_LIB_UTIL="$SUDO_DIR/libexec/sudo/libsudo_util.so.0"
SUDO_PLUGIN="$SUDO_DIR/libexec/sudo/sudoers.so"
DEST_SUDO="/usr/bin/sudo"
DEST_LIB="/usr/lib64"
DEST_PLUGIN_DIR="/usr/libexec/sudo"
SUDO_CONF="/etc/sudo.conf"
LOG_FILE="/var/log/sudo_upgrade_$(date +%s).log"# 日志函數
log_message() {local message="[$(date '+%Y-%m-%d %H:%M:%S')] $1"echo "$message"echo "$message" >> "$LOG_FILE"
}# 錯誤處理函數
handle_error() {log_message "錯誤: $1"[ -n "$2" ] && log_message "詳細信息: $2"log_message "升級過程已中止。請檢查日志文件: $LOG_FILE"exit 1
}# 檢查命令執行狀態
check_status() {if [ $? -ne 0 ]; thenhandle_error "$1" "$2"fi
}# 檢查是否是 root 用戶
if [ "$(id -u)" != "0" ]; thenecho "錯誤:請以 root 用戶運行此腳本。"exit 1
filog_message "開始升級 sudo 到 1.9.17p1 ..."# 1. 解壓 tar.gz 文件
if [ ! -f "$ARCHIVE" ]; thenhandle_error "$ARCHIVE 文件不存在,請確認文件在當前目錄下。"
fimkdir -p "$EXTRACT_PATH"
log_message "正在解壓 $ARCHIVE ..."
tar -zxf "$ARCHIVE"
check_status "解壓失敗,請檢查壓縮包是否損壞或格式是否為 .tar.gz"# 2. 確保目標目錄存在
if [ ! -d "$SUDO_DIR" ]; thenhandle_error "解壓后未找到 $SUDO_DIR 目錄,請檢查壓縮包內容結構是否正確。"
fi# 3. 備份原有 sudo(如果存在)
if [ -f "$DEST_SUDO" ]; thenlog_message "正在備份原 sudo..."cp "$DEST_SUDO" "${DEST_SUDO}.bak"check_status "備份原 sudo 失敗"log_message "已備份原 sudo 至 ${DEST_SUDO}.bak"
elselog_message "警告: 未找到原有 sudo 可執行文件,跳過備份步驟"
fi# 4. 替換 sudo 可執行文件
log_message "正在安裝新版本 sudo..."
cp "$SUDO_BIN" "$DEST_SUDO"
check_status "復制 sudo 可執行文件失敗"
chmod 4755 "$DEST_SUDO"
check_status "設置 sudo 權限失敗"
log_message "已安裝新版本 sudo 到 $DEST_SUDO"# 5. 安裝動態庫
log_message "正在安裝動態庫..."
cp "$SUDO_LIB_UTIL" "$DEST_LIB/"
check_status "復制動態庫失敗"
log_message "已安裝 libsudo_util.so.0 到 $DEST_LIB/"# 6. 安裝插件
log_message "正在安裝插件..."
mkdir -p "$DEST_PLUGIN_DIR"
check_status "創建插件目錄失敗"
cp "$SUDO_PLUGIN" "$DEST_PLUGIN_DIR/"
check_status "復制插件文件失敗"
chmod -R go+rx "$DEST_PLUGIN_DIR"
check_status "設置插件目錄權限失敗"
log_message "已安裝 sudoers.so 插件到 $DEST_PLUGIN_DIR"# 7. 更新動態庫緩存
log_message "正在更新動態庫緩存..."
ldconfig
check_status "更新動態庫緩存失敗"
log_message "動態庫緩存已更新"# 8. 創建或修復 /etc/sudo.conf 文件
log_message "正在配置 /etc/sudo.conf..."
if [ -f "$SUDO_CONF" ]; thenlog_message "清理舊的 sudoers 插件配置..."# 備份配置文件cp "$SUDO_CONF" "${SUDO_CONF}.bak"# 刪除舊的 sudoers 插件配置行(如果有)sed -i '/Plugin sudoers_policy/d' "$SUDO_CONF"sed -i '/Plugin sudoers_io/d' "$SUDO_CONF"
elselog_message "創建新的 sudo.conf 文件..."touch "$SUDO_CONF"check_status "創建 sudo.conf 文件失敗"
fi# 添加正確的插件路徑
echo "# Added by upgrade-sudo.sh" >> "$SUDO_CONF"
echo "Plugin sudoers_policy /usr/libexec/sudo/sudoers.so" >> "$SUDO_CONF"
echo "Plugin sudoers_io /usr/libexec/sudo/sudoers.so" >> "$SUDO_CONF"
check_status "配置 sudo.conf 失敗"
log_message "已配置 /etc/sudo.conf 中的插件路徑"# 9. 驗證安裝結果
log_message "正在驗證安裝..."
"$DEST_SUDO" -V &>/dev/null
if [ $? -eq 0 ]; thenlog_message "sudo 升級成功!版本信息:""$DEST_SUDO" -V >> "$LOG_FILE"echo "sudo 升級成功!版本信息:""$DEST_SUDO" -V
elsehandle_error "升級失敗,請檢查日志。"
filog_message "升級完成!你現在可以在普通用戶下直接使用 sudo 命令。"
echo ""
echo "升級完成!詳細日志已保存至: $LOG_FILE"
3. 代碼逐行解釋
配置變量部分
ARCHIVE="sudo1.9.17p1.tar.gz"
EXTRACT_PATH="/root/usr/local"
SUDO_DIR="$EXTRACT_PATH/sudo-1.9.17p1"
SUDO_BIN="$SUDO_DIR/bin/sudo"
SUDO_LIB_UTIL="$SUDO_DIR/libexec/sudo/libsudo_util.so.0"
SUDO_PLUGIN="$SUDO_DIR/libexec/sudo/sudoers.so"
DEST_SUDO="/usr/bin/sudo"
DEST_LIB="/usr/lib64"
DEST_PLUGIN_DIR="/usr/libexec/sudo"
SUDO_CONF="/etc/sudo.conf"
LOG_FILE="/var/log/sudo_upgrade_$(date +%s).log"
這部分代碼定義了腳本中使用的各種變量,包括 sudo 源碼壓縮包的名稱、解壓路徑、目標文件和目錄的路徑,以及日志文件的名稱。
日志和錯誤處理函數
# 日志函數
log_message() {local message="[$(date '+%Y-%m-%d %H:%M:%S')] $1"echo "$message"echo "$message" >> "$LOG_FILE"
}# 錯誤處理函數
handle_error() {log_message "錯誤: $1"[ -n "$2" ] && log_message "詳細信息: $2"log_message "升級過程已中止。請檢查日志文件: $LOG_FILE"exit 1
}# 檢查命令執行狀態
check_status() {if [ $? -ne 0 ]; thenhandle_error "$1" "$2"fi
}
log_message
函數用于記錄日志,將消息同時輸出到終端和日志文件中。handle_error
函數用于處理錯誤,記錄錯誤信息并終止腳本的執行。check_status
函數用于檢查上一個命令的執行狀態,如果執行失敗則調用 handle_error
函數。
檢查用戶權限
# 檢查是否是 root 用戶
if [ "$(id -u)" != "0" ]; thenecho "錯誤:請以 root 用戶運行此腳本。"exit 1
fi
升級 sudo 需要 root 權限,因此腳本會檢查當前用戶是否為 root 用戶,如果不是則輸出錯誤信息并退出。
解壓源碼壓縮包
# 1. 解壓 tar.gz 文件
if [ ! -f "$ARCHIVE" ]; thenhandle_error "$ARCHIVE 文件不存在,請確認文件在當前目錄下。"
fimkdir -p "$EXTRACT_PATH"
log_message "正在解壓 $ARCHIVE ..."
tar -zxf "$ARCHIVE"
check_status "解壓失敗,請檢查壓縮包是否損壞或格式是否為 .tar.gz"
腳本會先檢查 sudo 源碼壓縮包是否存在,如果不存在則輸出錯誤信息并退出。然后創建解壓目錄并解壓壓縮包,同時檢查解壓是否成功。
備份原有 sudo
# 3. 備份原有 sudo(如果存在)
if [ -f "$DEST_SUDO" ]; thenlog_message "正在備份原 sudo..."cp "$DEST_SUDO" "${DEST_SUDO}.bak"check_status "備份原 sudo 失敗"log_message "已備份原 sudo 至 ${DEST_SUDO}.bak"
elselog_message "警告: 未找到原有 sudo 可執行文件,跳過備份步驟"
fi
如果系統中已經存在 sudo 可執行文件,則將其備份到一個帶有 .bak
后綴的文件中,以便在升級失敗時可以恢復。
替換 sudo 可執行文件和相關文件
# 4. 替換 sudo 可執行文件
log_message "正在安裝新版本 sudo..."
cp "$SUDO_BIN" "$DEST_SUDO"
check_status "復制 sudo 可執行文件失敗"
chmod 4755 "$DEST_SUDO"
check_status "設置 sudo 權限失敗"
log_message "已安裝新版本 sudo 到 $DEST_SUDO"# 5. 安裝動態庫
log_message "正在安裝動態庫..."
cp "$SUDO_LIB_UTIL" "$DEST_LIB/"
check_status "復制動態庫失敗"
log_message "已安裝 libsudo_util.so.0 到 $DEST_LIB/"# 6. 安裝插件
log_message "正在安裝插件..."
mkdir -p "$DEST_PLUGIN_DIR"
check_status "創建插件目錄失敗"
cp "$SUDO_PLUGIN" "$DEST_PLUGIN_DIR/"
check_status "復制插件文件失敗"
chmod -R go+rx "$DEST_PLUGIN_DIR"
check_status "設置插件目錄權限失敗"
log_message "已安裝 sudoers.so 插件到 $DEST_PLUGIN_DIR"
這部分代碼將新版本的 sudo 可執行文件、動態庫和插件復制到相應的目標目錄,并設置正確的權限。
更新動態庫緩存
# 7. 更新動態庫緩存
log_message "正在更新動態庫緩存..."
ldconfig
check_status "更新動態庫緩存失敗"
log_message "動態庫緩存已更新"
ldconfig
命令用于更新系統的動態庫緩存,確保系統可以找到新安裝的動態庫。
配置 /etc/sudo.conf
文件
# 8. 創建或修復 /etc/sudo.conf 文件
log_message "正在配置 /etc/sudo.conf..."
if [ -f "$SUDO_CONF" ]; thenlog_message "清理舊的 sudoers 插件配置..."# 備份配置文件cp "$SUDO_CONF" "${SUDO_CONF}.bak"# 刪除舊的 sudoers 插件配置行(如果有)sed -i '/Plugin sudoers_policy/d' "$SUDO_CONF"sed -i '/Plugin sudoers_io/d' "$SUDO_CONF"
elselog_message "創建新的 sudo.conf 文件..."touch "$SUDO_CONF"check_status "創建 sudo.conf 文件失敗"
fi# 添加正確的插件路徑
echo "# Added by upgrade-sudo.sh" >> "$SUDO_CONF"
echo "Plugin sudoers_policy /usr/libexec/sudo/sudoers.so" >> "$SUDO_CONF"
echo "Plugin sudoers_io /usr/libexec/sudo/sudoers.so" >> "$SUDO_CONF"
check_status "配置 sudo.conf 失敗"
log_message "已配置 /etc/sudo.conf 中的插件路徑"
腳本會檢查 /etc/sudo.conf
文件是否存在,如果存在則備份并清理舊的插件配置行,然后添加正確的插件路徑。如果文件不存在則創建一個新的文件。
驗證安裝結果
# 9. 驗證安裝結果
log_message "正在驗證安裝..."
"$DEST_SUDO" -V &>/dev/null
if [ $? -eq 0 ]; thenlog_message "sudo 升級成功!版本信息:""$DEST_SUDO" -V >> "$LOG_FILE"echo "sudo 升級成功!版本信息:""$DEST_SUDO" -V
elsehandle_error "升級失敗,請檢查日志。"
fi
最后,腳本會驗證升級結果,通過運行 sudo -V
命令來檢查新版本的 sudo 是否可以正常工作。如果命令執行成功,則表示升級成功,否則輸出錯誤信息并終止腳本。
四、使用方法
- 準備工作:將
sudo1.9.17p1.tar.gz
文件下載到腳本所在的目錄。 - 運行腳本:以 root 用戶身份運行 update_sudo.sh 腳本。
sudo ./update_sudo.sh
- 查看日志:升級過程中的詳細信息會記錄在
/var/log/sudo_upgrade_.log
文件中,如果升級失敗,可以查看該日志文件來排查問題。
五、總結
通過及時升級 sudo 到安全版本,可以有效避免 Linux sudo 本地提權漏洞帶來的安全風險。本文介紹的腳本提供了一種自動化的升級方法,方便系統管理員快速完成升級任務。在升級過程中,腳本會進行詳細的日志記錄和錯誤處理,確保升級過程的可靠性。同時,建議定期關注 sudo 的安全更新,及時采取措施保障系統的安全。
希望本文對你有所幫助,如果你在升級過程中遇到任何問題,歡迎在評論區留言討論。