Linux PAM 配置详解:从原理到实战,彻底阻断非授权提权

一、问题的本质:为什么 sudo su - 能绕过防线?

在日常运维中,很多管理员会遇到这样的困惑:

建立普通用户并添加到 sudoers 后,发现该用户可以通过 sudo su -sudo su 配合自己的密码直接切换到 root。这不就是"串权"了吗?

核心问题在于:大多数教程只教了你一半。 网上常见的 wheel 组限制方案,只能拦截直接 使用 su - root 的路径,却对 sudo su - 这条"借道"路径束手无策。

要理解这一点,必须先搞清楚 Linux 中两条截然不同的提权路径:

路径 命令示例 认证机制 控制文件
su 路径 su -, su - root PAM 认证栈 /etc/pam.d/su
sudo 路径 sudo su -, sudo -i sudoers 策略 + PAM /etc/sudoers + /etc/pam.d/sudo

这两条路径独立运行、互不干涉。只封住一条,另一条依然是敞开的。


二、PAM 是什么?------可插拔认证模块

PAM(Pluggable Authentication Modules,可插拔认证模块)是 Linux 系统中一套分层、模块化 的认证框架。它的设计哲学是:将认证逻辑从应用程序中剥离出来,通过配置文件动态组合。

2.1 PAM 的四类管理模块

每个 PAM 配置文件(位于 /etc/pam.d/ 下)都包含四类管理标记:

标记 作用 示例场景
auth 验证用户身份(你是谁?) 密码校验、双因素认证
account 账户有效性检查(你能用吗?) 账户是否过期、登录时间限制
password 密码修改策略(你能改吗?) 密码复杂度、历史密码限制
session 会话管理(你做了什么?) 环境变量设置、审计日志记录

2.2 控制标记:决定模块的"话语权"

PAM 使用控制标记决定当某个模块失败时,整体认证流程该如何继续:

控制标记 行为 通俗解释
required 必须成功,失败继续检查但最终拒绝 "一票否决,但面子给足"
requisite 必须成功,失败立即终止 "一票否决,当场翻脸"
sufficient 成功则跳过后续,失败忽略 "过了这村没这店"
optional 成败不影响结果 "仅供参考"

理解 required vs requisite 的区别至关重要:requisite 在失败时立即返回,避免暴露过多系统信息(如提示"密码错误"前就被拒绝),是更安全的做法。


三、实战第一步:用 pam_wheel.so 锁住 su 大门

3.1 为什么选 pam_wheel.so

pam_wheel.so 是 PAM 中专门用于实施 "wheel 组"策略 的模块。它的核心功能是:只允许特定用户组成员使用 su 切换到 root(或目标用户)

根据官方手册,该模块支持多个关键参数:

参数 作用
use_uid 检查调用者的真实 UID,而非从终端会话获取的用户名(防伪造)
group=name 指定自定义组名,替代默认的 wheel
deny 反向逻辑:wheel 组成员被禁止使用 su
root_only 仅在目标用户是 root(UID=0)时才检查
trust wheel 组成员免密通过(极度危险,生产环境禁用

3.2 配置 /etc/pam.d/su

打开配置文件:

bash 复制代码
sudo vim /etc/pam.d/su

你会看到类似以下的内容:

text 复制代码
#%PAM-1.0
auth        sufficient    pam_rootok.so
#auth       required      pam_wheel.so use_uid
auth        substack      system-auth
auth        include       postlogin
account     sufficient    pam_succeed_if.so uid = 0 use_uid quiet
account     include       system-auth
password    include       system-auth
session     include       system-auth
session     include       postlogin
session     optional      pam_xauth.so

关键操作: 找到被注释掉的 pam_wheel.so 行,取消注释:

text 复制代码
auth        required      pam_wheel.so use_uid
各配置组合的效果解析

根据 openEuler 社区的技术文档,这两行的组合决定了谁能使用 su

pam_rootok.so pam_wheel.so 效果
开启(默认) 注释(默认) 所有用户 都能使用 su,root 切换免密
注释 注释 所有用户都能使用 su,但 root 切换也需密码
开启 开启 只有 root 和 wheel 组成员 能使用 su
注释 开启 只有 wheel 组成员 能使用 su,root 也被限制

推荐配置: 保留 pam_rootok.so(让 root 能免密切换,方便救援),同时开启 pam_wheel.so use_uid。这样 root 和 wheel 组成员可用 su,其他用户一律拒绝。

3.3 为什么必须加 use_uid

use_uid 参数的含义是:检查调用进程的真实 UID,而不是尝试从终端会话获取用户名

如果没有 use_uid,攻击者可能通过环境变量伪造或终端会话劫持来绕过检查。加上 use_uid 后,PAM 直接读取进程的真实 UID,与 /etc/passwd/etc/group 中的记录比对,无法伪造

3.4 配合 /etc/login.defs(可选增强)

某些发行版支持在 /etc/login.defs 中添加:

bash 复制代码
SU_WHEEL_ONLY yes

这行配置会进一步强化 su 命令的行为,确保只有 wheel 组成员才能切换用户。不过现代 Linux 中,pam_wheel.so 已足够,此配置更多是历史兼容 。


四、实战第二步:用 /etc/sudoers 堵住 sudo su - 的后门

4.1 为什么 pam_wheel.so 拦不住 sudo su -

这是许多管理员的误区。让我们拆解 sudo su - 的执行流程:

  1. sudo 阶段 :用户执行 sudo su -,系统先检查 /etc/sudoers

    • 如果用户有 ALL 权限,sudo 允许其以 root 身份执行 /bin/su -
    • 此时 sudo 的 PAM 认证已完成,/etc/pam.d/su 无关
  2. su 阶段su 命令被 root 身份调用,进入 /etc/pam.d/su

    • pam_rootok.so 发现当前 UID 已经是 0(root),直接通过
    • pam_wheel.so 检查的是"调用 su 的进程"------此时是 root,自然通过。

结论: sudo su - 完全绕过了 pam_wheel.so 对普通用户的限制,因为 su 是以 root 身份被调用的。

4.2 在 sudoers 中配置命令黑名单

编辑 sudoers 文件(必须使用 visudo,它会检查语法,防止配置错误导致系统锁死):

bash 复制代码
sudo visudo

为用户添加规则,允许所有命令,但明确禁止 su 和 bash

text 复制代码
kong ALL=(ALL) ALL,!/bin/su,!/bin/su -,!/bin/bash,!/bin/sh
规则解析
字段 含义
kong 目标用户名
ALL= 在所有主机上生效
(ALL) 可以以任何用户身份执行(包括 root)
ALL 允许执行所有命令
!/bin/su 但禁止 执行 /bin/su
!/bin/bash 但禁止 执行 /bin/bash(防止 sudo bash 绕过)

注意: 必须同时禁止 subashsh 等可以获取交互式 shell 的命令。只禁止 su 是不够的,因为用户可以通过 sudo bash 直接获得 root shell 。

4.3 更精细的白名单策略(推荐生产环境)

与其用黑名单"防漏",不如用白名单"精确授权":

text 复制代码
kong ALL=(ALL) /usr/bin/systemctl *, /usr/bin/cat /var/log/*, !/bin/su, !/bin/bash

这种配置只允许用户执行特定维护命令,从根本上消除提权可能。


五、完整流程图:双重防护机制

上图展示了完整的认证流程:

  • su 路径 (上方):普通用户调用 su → 经过 pam_wheel.so 检查 → 非 wheel 成员直接被拒绝(红色箭头)。
  • sudo 路径 (下方):普通用户调用 sudo su - → sudoers 解析权限 → 发现 !/bin/su 规则 → 拒绝执行(红色箭头)。
  • wheel 组成员(绿色):无论走 su 还是 sudo 路径,只要配置允许,均可通行。

六、验证与排错

6.1 验证 pam_wheel.so 是否生效

以非 wheel 用户登录,尝试:

bash 复制代码
su - root

预期结果:

text 复制代码
Password: 
su: Permission denied

即使输入正确密码也应被拒绝。

6.2 验证 sudoers 限制是否生效

bash 复制代码
sudo su -

预期结果:

text 复制代码
Sorry, user kong is not allowed to execute '/bin/su -' as root on localhost.

6.3 查看 PAM 调试日志

如果配置未生效,可开启调试:

bash 复制代码
# 临时开启(CentOS/RHEL)
sudo touch /etc/pam_debug

# 或查看系统日志
sudo tail -f /var/log/secure    # CentOS/RHEL
sudo tail -f /var/log/auth.log  # Debian/Ubuntu

日志中会显示每个 PAM 模块的返回状态(successignoreauth_err 等)。


七、常见误区与陷阱

误区 1:"加了 wheel 组就安全了"

错误。 只加 wheel 组只能防 su - root,防不了 sudo su -。两条路径必须分别配置。

误区 2:usermod -g wheelusermod -aG wheel 一样

完全不同:

bash 复制代码
# 危险!将用户主组改为 wheel,可能破坏原有权限
usermod -g wheel kong

# 正确!将 wheel 作为附加组
usermod -aG wheel kong

-g 修改的是主组 (GID),会替换用户原有主组;-aG追加附加组,不影响现有权限。

误区 3:只禁止 su,不禁止 bash

存在绕过风险。 如果用户有 sudo ALL 权限但只被禁止了 su,他可以:

bash 复制代码
sudo bash        # 直接获得 root shell
sudo -i          # 等效于 sudo su -
sudo /bin/sh     # 使用其他 shell

必须同时禁止所有交互式 shell

误区 4:使用 chmod 777 /etc/sudoers

绝对禁止。 /etc/sudoers 的权限必须是 0440r--r-----)。任何其他权限都会导致 sudo 拒绝读取,系统提示权限错误。修改时始终使用 visudo


八、总结:最小权限原则的实践

防护层级 配置文件 核心配置 拦截对象
第一层 /etc/pam.d/su auth required pam_wheel.so use_uid 非 wheel 用户使用 su
第二层 /etc/sudoers ALL,!/bin/su,!/bin/bash 授权用户使用 sudo su -
第三层 /etc/login.defs SU_WHEEL_ONLY yes(可选) 强化 su 限制

最终效果:

  • 非 wheel 普通用户:su - 被拒绝,sudo su - 被拒绝,彻底无法获得 root。
  • wheel 组成员:保留 su - 权限(知道 root 密码即可),或根据 sudoers 规则使用 sudo
  • root 用户:始终保留救援通道(通过 pam_rootok.so)。

这种"PAM 管入口,sudoers 管行为"的双重防护,是 Linux 权限管理中最经典、最可靠的纵深防御实践。

相关推荐
invicinble1 小时前
spring提供的其他机制
java·后端·spring
ZPC82101 小时前
Linux Preempt-RT 实时内核 ** 抖动(Jitter)** 完整测试方法
linux·运维·服务器
阿昌喜欢吃黄桃1 小时前
如果线程池中线程异常后:销毁还是复用?
java·线程·线程池·多线程·juc
2501_920047031 小时前
openclaw在ubuntu系统的安装
linux·运维·ubuntu·openclaw
奋斗的小乌龟1 小时前
动态创建Agent01
java·笔记
彦为君1 小时前
Java文件处理效率库Commons-IO(速览)
java·开发语言·mfc
呉師傅2 小时前
UPS滴滴告警!如何测量UPS电池内阻【UPS学习】
运维·服务器·网络·学习·电脑
她的男孩2 小时前
后台权限不只是菜单隐藏:Forge Admin 的 RBAC 权限链路拆解
java·后端·架构
一个人旅程~2 小时前
linux如何“抢”过windows的usb移动硬盘权限对0磁道损坏的移动硬盘进行尝试修复
linux·windows·经验分享·电脑