LinuxShell脚本安全实践_权限与环境控制解析【教程】

17次阅读

脚本执行权限必须设为750且组严格限定,禁止755;需用set -euo pipefail、ifS=、引号化变量、重置PATH、校验二进制完整性、mktemp创建临时文件并设600权限。

LinuxShell脚本安全实践_权限与环境控制解析【教程】

脚本执行权限设置必须用 chmod 750 而非 755

如果脚本含敏感操作(如修改系统配置、读取 /etc/shadow),执行权限开放给“其他用户”(o+r-x)等于默认放行任意本地账户调用。实际中 chmod 750 确保仅属主+同组可执行,且组应严格限定(如新建专用组 adminscripts,仅加入必要账号)。755 常见于 Web 可读目录,但 Shell 脚本一旦被普通用户执行,可能绕过 sudo 策略或触发环境变量污染。

  • 检查当前权限:ls -l /path/to/script.sh,确认输出第三段不含 x(如 -rwxr-x--- 合规,-rwxr-xr-x 不合规)
  • 设权后立即验证:sudo -u nobody /path/to/script.sh 应报 Permission denied,而非静默失败或意外执行
  • 避免在 /tmp/var/tmp 中存放带执行权限的脚本——这些目录通常设了 sticky bit,但不阻止同组用户覆盖或重命名

set -euo pipefail 是基础安全开关,但需配合 IFS= 和引号化

仅加 set -euo pipefail 不足以防御路径遍历或空格分词攻击。例如 for file in $(ls *.log) 在文件名含空格时会崩,而 find ... -print0 | while IFS= read -r -d '' f 才可靠。关键点在于:IFS= 阻止 read 自动裁剪首尾空白,read -r 禁用反斜杠转义,所有变量引用必须用 "$var"

  • set -u 会让未定义变量(如 $USER_HOME 拼写错成 $USER_HOMR)直接退出,避免静默使用空值
  • set -o pipefail 使管道中任一命令失败即整体失败,否则 grep xxx /etc/passwd | head -1 可能因 grep 无匹配而返回 1,但 head 仍成功,脚本误判为“找到结果”
  • 禁止裸写 cp $src $dst,必须写成 cp "$src" "$dst";若 $src/tmp/my file.txt,不加引号会拆成两个参数

PATH 和 LD_LIBRARY_PATH 必须显式重置,不能依赖用户环境

脚本启动时若继承用户 PATH(如含 ~/bin/usr/local/bin),攻击者可通过篡改其中的 lsawk 等命令劫持执行流。正确做法是开头就覆盖:PATH="/usr/bin:/bin:/usr/sbin:/sbin",并用 command -v 校验关键工具存在。

  • 清除危险变量:unset LD_PRELOAD LD_LIBRARY_PATH pythonPATH PERL5LIB,这些可被用于动态库/解释器注入
  • 用绝对路径调用核心命令更稳妥(如 /bin/cp 而非 cp),但前提是已确认该路径在目标系统存在(centos 和 Alpine 的 /bin 内容差异大)
  • 若脚本需调用自定义二进制,应先 sha256sum -c checksums.sha256 校验完整性,再加入 PATH

临时文件必须用 mktemp 创建,且禁止 /tmp 下硬编码路径

写死 /tmp/myscript.pid/tmp/output.log 是典型竞争条件漏洞:攻击者可在 if [ ! -f /tmp/myscript.pid ]; then touch /tmp/myscript.pid 的间隙创建符号链接,指向 /etc/passwd。必须用 mktemp 生成唯一路径,并立即 chmod 600

  • 正确模式:
    tmpdir=$(mktemp -d) || exit 1 chmod 700 "$tmpdir" trap 'rm -rf "$tmpdir"' EXIT
  • 单文件也需 mktemptmpfile=$(mktemp) && chmod 600 "$tmpfile",不可用 $$(进程号)拼接,因 PID 可预测
  • 避免 mktemp /tmp/myapp.XXXXXX —— 这种用法在旧版 mktemp 中不安全,现代应只用无参数形式或 -t 指定模板前缀

脚本里最易被忽略的不是语法错误,而是对环境变量和临时资源的假设——它们在开发机上总“恰好工作”,一到生产环境就因权限收紧、路径变更或并发访问暴露问题。

text=ZqhQzanResources