Shell 腳本的安全性考量 文章首圖

Shell 腳本的安全性考量

Shell 腳本的安全性考量

在 Linux 系統管理中,Shell 腳本無疑是自動化任務的得力助手。從簡單的檔案備份到複雜的系統監控,腳本能大幅提升工作效率。然而,正因為腳本通常擁有較高的執行權限,且邏輯相對直接,若撰寫時疏忽了安全細節,往往會成為系統被攻擊的突破口。本文将探討在 Ubuntu 22.04 與 Debian 12 環境下,撰寫 Shell 腳本時必須注意的核心安全原則,並提供實用的防禦範例。

嚴禁直接執行使用者輸入

許多初學者常犯的一個錯誤是將使用者輸入直接拼接到命令字串中執行。這不僅容易導致邏輯錯誤,更可能引發命令注入(Command Injection)攻擊。例如,若腳本接收使用者輸入的檔案名稱並刪除它,惡意使用者可以輸入 file.txt; rm -rf / 來摧毀系統。

解決之道在於「驗證」與「白名單機制」。我們應嚴格限制輸入字元的範圍,僅允許字母、數字、底線或連字號。以下範例展示如何安全地處理使用者輸入的檔案名稱:

#!/bin/bash

# 檢查是否傳入參數
if [ -z "$1" ]; then
    echo "錯誤:請提供檔案名稱。"
    exit 1
fi

# 使用正則表達式驗證輸入,僅允許字母、數字、底線、連字號和點號
if [[ ! "$1" =~ ^[a-zA-Z0-9_.-]+$ ]]; then
    echo "錯誤:檔案名稱包含非法字元。"
    exit 1
fi

# 檢查檔案是否存在
if [ ! -f "$1" ]; then
    echo "錯誤:檔案 $1 不存在。"
    exit 1
fi

echo "檔案 $1 驗證通過,開始處理..."
# 在此處進行後續的安全操作

此腳本利用 [[ ... =~ ... ]] 結構進行正規表示式匹配,確保輸入內容乾淨。即使使用者嘗試注入惡意指令,也會因字元不符合規範而被拒絕。

使用 set 選項強化腳本行為

預設情況下,Shell 腳本在遇到錯誤時可能會繼續執行後續指令,這在處理敏感資料或系統變更時極為危險。透過在腳本開頭加入 set 選項,我們可以強制腳本在發生錯誤時立即停止,並顯示詳細的除錯資訊。

建議在每個腳本的第一行(shebang 之後)加入以下設定:

#!/bin/bash
# 錯誤時立即退出
set -e
# 若變數未定義則報錯
set -u
# 若管道中任何一個指令失敗則視為失敗
set -o pipefail
  • set -e:一旦任何指令回傳非零值(代表錯誤),腳本立即終止。這防止了錯誤連鎖反應。
  • set -u:若嘗試使用未初始化的變數,腳本會報錯並停止。這能避免因為變數名稱拼寫錯誤而導致刪除錯誤目錄的慘劇。
  • set -o pipefail:在 Unix 管道(pipe)中,若其中一個指令失敗,整個管道的回傳值將為該失敗指令的值,而非最後一個指令的值。這對於檢查數據處理流程至關重要。

權限最小化原則

腳本本身應具備執行權限,但絕不應隨意賦予 root 權限,除非必要。若腳本確實需要提升權限,應明確指定並限制範圍。此外,腳本檔案本身的權限也需嚴格控制。

在 Ubuntu 或 Debian 系統中,建議將腳本檔案權限設定為 700,僅允許所有者執行:

chmod 700 /path/to/your/script.sh

若腳本需要讀取特定目錄,應使用 sudo 明確呼叫所需指令,而非整個腳本以 root 執行。例如:

#!/bin/bash
set -e

# 僅對需要 root 權限的指令使用 sudo
if ! command -v sudo &> /dev/null; then
    echo "錯誤:系統未安裝 sudo。"
    exit 1
fi

# 僅在需要時提升權限,並記錄日誌
echo "正在備份系統設定..."
sudo tar -czf /tmp/system_backup.tar.gz /etc/ 2>/dev/null

if [ $? -eq 0 ]; then
    echo "備份成功。"
else
    echo "備份失敗,請檢查權限或目錄是否存在。"
    exit 1
fi

常見問題解答

Q1:為什麼我不應該在腳本中使用 eval eval 會將字串當作指令執行,這極易引發命令注入風險。除非你完全控制字串內容且無其他替代方案,否則應避免使用。例如,與其使用 eval "echo $var",不如直接使用 echo "$var"

Q2:如何防止腳本被惡意篡改? 對於關鍵腳本,建議設定檔案屬性為不可變(immutable)。在 Debian/Ubuntu 中,可使用 chattr 指令:

sudo chattr +i /path/to/secure_script.sh

這將阻止任何人(包括 root)修改或刪除該檔案,除非先移除 i 屬性。這提供了額外的保護層,防止攻擊者在取得部分權限後修改腳本邏輯。

小結

Shell 腳本的安全性並非一蹴可幾,而是貫穿於撰寫的每一個細節。從輸入驗證、錯誤處理到權限控制,每一步都需謹慎對待。透過採用 set 選項、驗證使用者輸入以及遵循最小權限原則,我們可以大幅降低腳本被濫用的風險。記住,安全的腳本不僅能保護系統,更能確保自動化任務的穩定與可靠。在享受自動化帶來便利的同時,切勿忘記安全這道防線。