最有效方式是直接在 /etc/sudoers 中显式设置 secure_path 并确保其不被覆盖:defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",同时启用 env_reset、禁用 env_keep path 和 setenv,最后实测验证生效。

直接在 /etc/sudoers 中设置 secure_path 并确保它不被覆盖或绕过,是固定 sudo 命令搜索路径、防止 PATH 劫持最有效的方式。关键不是“写上就行”,而是让这个路径真正生效、不可篡改、且覆盖所有执行场景。
确认并显式声明 secure_path 值
该路径必须只包含系统管理员完全可控、用户无写权限的目录,不能含 /tmp、/var/tmp、~/.local/bin 或任何可被普通用户修改的路径。
- 运行
sudo visudo,添加或修改这一行(不要注释):Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - 检查是否被其他配置覆盖:搜索
!secure_path或env_keep += "PATH",这些会禁用或弱化 secure_path - 若需对特定用户组豁免(如运维组),用
Defaults:%admin !secure_path,但应有强审计机制配套
阻止 PATH 通过环境重置机制泄露
即使设置了 secure_path,如果 env_reset 被关闭或 env_keep 错误保留了 PATH,攻击者仍可通过 sudo -E 或配置漏洞绕过。
- 确保
Defaults env_reset已启用(默认通常开启,但需确认未被!env_reset关闭) - 禁止在
env_keep中加入PATH:
错误写法:Defaults env_keep += "PATH"
正确做法:完全不保留 PATH,依赖 secure_path 主动覆盖 - 禁用
SETENV权限:检查 sudoers 中无类似user ALL=(ALL) SETENV: /bin/bash的规则,这类配置允许用户传入任意环境变量,包括 PATH
验证 secure_path 是否真实生效
改完配置后必须实测,不能只看配置文件是否存在。
- 运行
sudo -V | grep "Value to override.*PATH",输出中应明确显示你的 secure_path 值 - 执行
sudo env | grep "^PATH=",结果应严格等于你设定的 secure_path 字符串,不能多也不能少 - 在当前目录放一个假
ls(如touch ls; chmod +x ls),再运行sudo ls—— 应调用/bin/ls,而非当前目录版本;若调用了假 ls,说明 secure_path 未生效或被绕过
脚本内也需配合绝对路径调用
secure_path 只影响 sudo 启动时的初始 PATH。一旦脚本开始运行,它内部调用的子命令(如 date、cp)仍可能被后续污染的 PATH 劫持。
- 敏感脚本开头强制重置 PATH:
PATH="/usr/local/bin:/usr/bin:/bin" - 所有系统命令优先用绝对路径:
/bin/cp、/usr/bin/find、/usr/bin/python3 - 或统一定义变量:
CP=/bin/cp; FIND=/usr/bin/find; PYTHON=/usr/bin/python3
后续全部使用$CP、$FIND等










