系统读取的全局profile文件按顺序为:/etc/profile、/etc/profile.d/*.sh、/etc/bash.bashrc(仅bash),且仅在登录shell中生效;其中/etc/profile为主入口,/etc/profile.d/下.sh文件会被依次source,/etc/bash.bashrc不影响sh或dash。

哪些文件会被系统读取为全局Profile
Linux启动shell时,会按固定顺序加载多个全局配置文件,顺序错了就可能被绕过或覆盖。关键路径只有三个:/etc/profile、/etc/profile.d/*.sh、/etc/bash.bashrc(仅bash),且只在登录shell中生效。
-
/etc/profile是主入口,但默认不检查子文件权限,容易被低权限用户写入恶意脚本 -
/etc/profile.d/下的每个.sh文件都会被 source,但系统不校验文件属主和权限,常见被植入后门的位置 -
/etc/bash.bashrc不影响 sh 或 dash,别误以为改它就能覆盖所有shell
如何验证当前环境变量是否被污染
别只看 env 输出——那只是结果。真正要查的是变量从哪来、谁写的、有没有被篡改过。
- 用
bash -ilc 'echo $PATH'模拟真实登录shell,避免交互式shell缓存干扰 - 检查
PATH中每个目录是否存在、是否可写:for d in $(echo $PATH | tr ':' '\n'); do ls -ld "$d" 2>/dev/null | grep -E '^-.*[w-]{2}..[w-]'; done - 搜可疑变量定义:
grep -r 'export.*=' /etc/profile* /etc/profile.d/ 2>/dev/null | grep -v 'PATH\|HOME\|LANG'
加固操作必须做的三件事
不是加个 readonly 就完事。重点是阻断注入路径、收紧执行权限、切断非必要继承。
- 把
/etc/profile.d/下所有文件属主设为root:root,权限改为644(chmod 644 /etc/profile.d/*.sh) - 在
/etc/profile开头插入校验逻辑:检查/etc/profile.d/下文件是否含非root属主或非644权限,有则退出(避免静默失败) - 禁止用户通过
~/.bashrc覆盖关键变量:在/etc/profile末尾加export PATH="/usr/local/bin:/usr/bin:/bin"并紧跟readonly PATH
为什么 readonly PATH 有时没用
因为 readonly 只对当前shell有效,子进程不会继承“只读属性”,只继承值。更麻烦的是,某些程序(比如用 execve 直接调用解释器的脚本)会忽略父shell的只读标记。
- 真正起作用的是路径本身不可写——如果
/usr/local/bin被普通用户拥有,他仍可放一个同名恶意二进制并靠PATH优先级劫持 -
sudo环境默认不继承PATH,但若配置了env_keep += "PATH",就得同步加固/etc/sudoers - 容器或 systemd 服务绕过
/etc/profile是常态,得单独处理其启动环境,不能指望全局profile一劳永逸
最常漏掉的是 /etc/profile.d/ 目录本身的权限——它要是 775 或属组可写,前面所有文件权限设置都白做。加固前先 ls -ld /etc/profile.d 看一眼。










