shell脚本执行安全的核心是控制执行环境、约束变量行为、隔离调用路径;须重置path、禁用eval、白名单限定命令、净化路径、mktemp创建临时文件并设严格权限。

Shell脚本执行安全的核心,不是靠“封禁”某些命令,而是通过**控制执行环境、约束变量行为、隔离调用路径**,让敏感命令根本无法被意外或恶意触发。直接在脚本里写 if [ "$cmd" = "rm" ]; then exit 1; fi 这类逻辑既不可靠,也容易绕过。
严格限制命令调用来源
不依赖用户输入拼接命令,是防注入的第一步。所有命令应明确声明、静态定义,避免动态解析:
- 禁用
eval、system、$(...)嵌套中含未校验变量的用法 - 用数组传递参数:例如
cmd=(cp "-v" "$src" "$dst"); "${cmd[@]}",而非cp $src $dst - 对必须动态选择的命令,仅从白名单中选取:
case "$action" in "backup"|"restore") ... ;; *) err "Invalid action"; exit 1 ;; esac
重置并锁定PATH与关键环境变量
攻击者常通过污染 PATH 或设置 LD_PRELOAD 替换系统命令。脚本启动即应清理:
- 开头立即重设:
PATH="/usr/bin:/bin:/usr/sbin:/sbin" - 显式校验关键工具存在:
command -v cp >/dev/null || { err "cp not found"; exit 1; } - 清除高危变量:
unset LD_PRELOAD LD_LIBRARY_PATH PYTHONPATH PERL5LIB - 避免继承用户环境——不使用
source ~/.bashrc或类似操作
敏感操作必须显式授权与降权执行
即使脚本本身不以 root 运行,也不代表它不能触发危险行为。需分层控制:
- 禁止脚本自身设 SUID/SGID(Google 风格指南明确禁止)
- 需要特权操作时,用
sudo调用最小权限子命令,并在/etc/sudoers中精确限定可执行命令和参数(如alice ALL=(root) NOPASSWD: /bin/systemctl restart nginx) - 对
rm、dd、mount等高危命令,封装为带参数校验的函数:safe_rm() { [[ "$1" =~ ^/var/log/.*\.log$ ]] && /bin/rm "$1" || { err "Refused: unsafe path $1"; return 1; }; }
文件与路径访问必须预检与净化
很多“敏感命令”实际是路径遍历导致的越权访问。防御重点在输入归一化:
- 用
realpath --canonicalize-existing "$input"获取绝对真实路径 - 检查是否在允许目录内:
[[ "$clean_path" == "/var/log/"* ]] || { err "Path outside allowed scope"; exit 1; } - 禁止
..、~、空字节等非法字符出现在路径变量中 - 临时文件必须用
mktemp -d创建,权限设为600或700,且不在/tmp下硬编码路径











