2026年5月,Linux内核遭遇罕见"漏洞风暴":Copy Fail(潜伏9年)、Dirty Frag(已被在野利用)、Fragnesia(本地提权)、ssh-keysign-pwn(可窃取SSH主机密钥和root密码)——3周内4个高危漏洞连环爆发。当内核层面的防线不再可靠,SSH作为服务器入口的加固就成了最后一道门。本文给出PAM模块+Google Authenticator双因素认证的10分钟部署方案。


一、5月Linux内核漏洞风暴:为什么SSH加固刻不容缓

时间线

日期 漏洞名称 CVE编号 危害 状态
4月29日 Copy Fail CVE-2026-40838 本地提权,潜伏9年 已修复
5月7日 Dirty Frag CVE-2026-43284/43500 本地提权 → root 🔴 已被在野利用
5月13日 Fragnesia 待分配 本地提权 已修复
5月14日 ssh-keysign-pwn CVE-2026-46333 窃取SSH主机密钥和root密码,潜伏6年 🔴 高危

在这里插入图片描述

为什么这波漏洞特别危险?

Copy Fail 由 AI 代码审计工具在1小时内发现——这意味着攻击者同样可以用AI工具批量审计内核代码。Dirty Frag 在补丁未就绪时就被公开,微软已确认其被黑客实际利用。而 ssh-keysign-pwn 是其中最致命的一个:

任何未获特权的本地用户利用该漏洞,都可能读取服务器的 SSH 主机私钥,或直接拿到 /etc/shadow 文件中的密码 Hash。

换句话说:攻击者只要想办法拿到一个低权限 shell(比如通过 Web 应用的 RCE),就能顺着这个漏洞直达 root,甚至伪装成你的服务器发起中间人攻击。

纵深防御:SSH双因素认证的价值

Linux 内核漏洞是不可预测的(这月4个就是最好的证明),但我们可以增加攻击者的成本:

攻击者拿到低权限shell
    ↓
尝试利用内核漏洞提权 → 被安全更新阻止(如果你及时打了补丁)
    ↓
尝试窃取SSH密钥横向移动 → 被ssh-keysign-pwn利用成功
    ↓
尝试用窃取的密钥SSH登录其他服务器
    ↓
🚫 被双因素认证拦截!即使有私钥,没有OTP令牌也进不来

SSH双因素认证 = 内核漏洞的最后一道防线。


二、技术原理:PAM模块如何实现SSH双因素认证

2.1 PAM(可插拔认证模块)简介

在这里插入图片描述

PAM(Pluggable Authentication Modules)是 Linux 系统的认证中间层。当用户执行 ssh 登录时,认证请求经过如下链路:

SSHD 收到登录请求
    ↓
调用 PAM 认证栈(/etc/pam.d/sshd)
    ↓
按顺序执行 PAM 模块:
  auth [success=1] pam_unix.so     ← 第1步:验证密码
  auth required    pam_google_authenticator.so  ← 第2步:验证OTP令牌
  auth requisite   pam_deny.so      ← 任一步失败则拒绝
    ↓
全部通过 → 授予 shell

2.2 TOTP(基于时间的一次性密码)原理

Google Authenticator 使用的是 TOTP(RFC 6238)算法:

TOTP = HMAC-SHA1(Secret_Key, floor(Unix_Time / 30))
  • Secret_Key:16字节随机密钥,在服务器和用户手机之间共享(通过二维码分发)
  • 30秒时间窗口:每30秒生成一个新的6位数字
  • 容差机制:通常允许±1个时间窗口(即前后30秒),应对时钟偏差

三、10分钟部署实战

3.1 环境准备

# 确认系统版本
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="22.04.3 LTS"

# 确认SSH版本
$ ssh -V
OpenSSH_8.9p1 Ubuntu-3ubuntu0.6, OpenSSL 3.0.2

3.2 Step 1:安装Google Authenticator PAM模块

# Ubuntu/Debian
sudo apt update
sudo apt install libpam-google-authenticator -y

# RHEL/CentOS/Rocky Linux
sudo dnf install google-authenticator -y
# 或从EPEL安装
sudo yum install epel-release -y
sudo yum install google-authenticator -y

# 验证安装
$ ls /lib/security/pam_google_authenticator.so
/lib/security/pam_google_authenticator.so  ✅

3.3 Step 2:为用户生成TOTP密钥

⚠️ 重要:用目标用户的身份执行,不要用 root!

# 切换到目标用户(例如 devops)
su - devops

# 运行初始化
google-authenticator

交互过程:

Do you want authentication tokens to be time-based (y/n) y

此时终端会显示:

  • 一个 二维码(用手机 Google Authenticator 扫描)
  • 一个 Secret Key(26位字符,备用)
  • 5个紧急备用码(8位数字,每个只能用一次)
Your new secret key is: XXXX XXXX XXXX XXXX XXXX
Your verification code is: 123456
Your emergency scratch codes are:
  12345678
  23456789
  34567890
  45678901
  56789012

操作要点

  1. 用手机 Google Authenticator / Authy / Microsoft Authenticator 扫描二维码
  2. 立即将5个紧急备用码截图或打印保存——这是你唯一能绕过OTP的后门
  3. 验证码输入测试码确认绑定成功

后续问题建议全部选 y

Do you want me to update your "~/.google_authenticator" file? (y/n) y
Do you want to disallow multiple uses of the same token? (y/n) y
# 建议y:防止重放攻击
By default, a new token is generated every 30 seconds...
Do you want to allow a time skew of up to 4 minutes? (y/n) y
# 建议y:容忍时钟偏差,避免因NTP未同步导致无法登录
Do you want to enable rate-limiting? (y/n) y
# 建议y:防止暴力破解OTP(每30秒最多3次尝试)

配置文件路径:~/.google_authenticator

3.4 Step 3:配置PAM

编辑 /etc/pam.d/sshd

sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak.$(date +%Y%m%d)
sudo vim /etc/pam.d/sshd

在文件顶部添加(注意顺序:先密码,再OTP):

# /etc/pam.d/sshd

# Step 1: 密码认证(如果使用密钥认证则跳过)
auth [success=1 default=ignore] pam_unix.so nullok

# Step 2: OTP认证(所有用户强制执行)
auth required pam_google_authenticator.so

# 原来的内容保留在下方
# @include common-auth
# ...

不同认证策略的配置

# 方案A:密码 + OTP(推荐,双重验证)
auth required pam_unix.so
auth required pam_google_authenticator.so

# 方案B:仅OTP(无密码,简化用户体验)
auth sufficient pam_google_authenticator.so

# 方案C:密钥认证后可跳过OTP(灵活但安全性降低)
auth [success=2 default=ignore] pam_unix.so
auth [success=1 default=ignore] pam_google_authenticator.so
auth requisite pam_deny.so

3.5 Step 4:配置SSHD

编辑 /etc/ssh/sshd_config

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d)
sudo vim /etc/ssh/sshd_config

必须修改的参数:

# 启用PAM认证
UsePAM yes

# 启用键盘交互认证(Google Authenticator依赖此项)
KbdInteractiveAuthentication yes

# 启用质询响应认证(兼容旧版OpenSSH)
ChallengeResponseAuthentication yes

# 密码认证:视需求开启(如果只用密钥+OTP,可关闭)
PasswordAuthentication yes

# 公钥认证:建议保留
PubkeyAuthentication yes

# 禁止root直接登录(安全最佳实践)
PermitRootLogin no

# 认证方式组合
AuthenticationMethods publickey,keyboard-interactive
# 含义:需要同时通过"公钥认证"和"键盘交互认证(OTP)"

重要:修改 sshd_config 后,不要关闭当前SSH会话!先开一个新终端测试登录:

# 测试配置语法
sudo sshd -t

# 如果输出为空,说明语法正确
# 如果报错,根据错误信息修正后再继续

3.6 Step 5:重启SSHD服务

# 重启前:先确认当前有一个正常工作的SSH会话!
sudo systemctl restart sshd

# 检查服务状态
sudo systemctl status sshd

⚠️ 安全红线:千万不要在只有一个SSH会话的情况下重启 sshd!如果配置有误导致 sshd 启动失败,你会被锁在服务器外面。正确做法:

# 创建一个备用SSH会话
# 终端A:保持当前的root会话,不要关闭
# 终端B:用普通用户新建SSH连接

# 在终端A中重启sshd
sudo systemctl restart sshd

# 在终端B中测试登录
ssh devops@your-server
# 输入密码后 → 输入Google Authenticator上的6位验证码

# 如果终端B登录成功 → 配置正确 ✅
# 如果终端B被拒绝 → 在终端A中回滚配置,检查错误日志

四、验证与测试

4.1 正常登录流程

$ ssh devops@192.168.1.100
(devops@192.168.1.100) Password:        # 输入系统密码
(devops@192.168.1.100) Verification code: # 输入OTP 6位数字
Welcome to Ubuntu 22.04.3 LTS...
devops@server:~$

4.2 OTP容错测试

# 故意输入错误的OTP
$ ssh devops@192.168.1.100
Password: ********
Verification code: 000000
Permission denied, please try again.

4.3 紧急备用码测试

# 模拟手机丢失场景,使用紧急备用码
$ ssh devops@192.168.1.100
Password: ********
Verification code: 12345678  # 使用8位备用码代替6位OTP
Welcome to Ubuntu 22.04.3 LTS!

每个备用码只能使用一次,用后自动失效。


五、踩坑记录与故障排查

坑1:SSH配置锁死——被锁在服务器外

症状:修改 sshd_config 后重启 sshd,新建连接被拒绝,现有会话也断开。

根因AuthenticationMethods 配置不正确,或PAM模块路径不存在。

自救方法

# 通过VNC/IPMI/云厂商控制台登录,然后:
sudo cp /etc/ssh/sshd_config.bak.YYYYMMDD /etc/ssh/sshd_config
sudo cp /etc/pam.d/sshd.bak.YYYYMMDD /etc/pam.d/sshd
sudo systemctl restart sshd

预防措施

# 使用 at 命令设置一个5分钟后的自动回滚(测试用)
echo "sudo cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config && sudo systemctl restart sshd" | at now + 5 minutes

# 如果5分钟内确认配置正确,取消自动回滚
atq   # 查看任务ID
atrm <任务ID>  # 取消任务

坑2:时钟不同步导致OTP始终无法通过

症状:密码正确,但OTP无论如何输入都显示 “Permission denied”。

根因:TOTP依赖精确的时间同步。如果服务器时钟偏差超过容忍窗口(默认±90秒),验证必然失败。

诊断

# 检查系统时间
$ date
Wed May 27 10:32:15 UTC 2026

# 检查NTP同步状态
$ timedatectl status
System clock synchronized: no   # ⚠️ 未同步!

修复

# 安装并启用NTP
sudo apt install chrony -y
sudo systemctl enable --now chrony

# 验证同步
$ chronyc tracking
Reference ID    : 0A0A0A0A (10.10.10.10)
Stratum         : 3
System time     : 0.000012345 seconds slow of NTP time

坑3:密钥认证被跳过OTP

症状:配置了密钥+OTP,但用密钥登录时直接进入系统,没有要求OTP。

根因AuthenticationMethods 使用了 publickey keyboard-interactive 但 PAM 配置中密钥认证成功后直接 success,跳过了 OTP 模块。

修复:检查 /etc/pam.d/sshd 中是否有 pam_google_authenticator.so 之前就返回了 success

# 确保PAM配置正确
auth required pam_google_authenticator.so
# 而不是
# auth sufficient pam_google_authenticator.so  ← 这会让OTP变成可选的

坑4:sudo免密配置与双因素认证冲突

症状:配置了 NOPASSWD 的 sudo 用户执行 sudo 时被要求输入OTP。

根因:如果 /etc/pam.d/sudo 中也引入了 pam_google_authenticator.so,每次 sudo 都需要OTP验证。

如果不想 sudo 也走 OTP(大部分场景的建议):

# 确保 /etc/pam.d/sudo 中没有引入 google_authenticator
grep google_authenticator /etc/pam.d/sudo
# 应该无输出

如果确实需要 sudo 也验证 OTP(高安全场景):

# 在 /etc/pam.d/sudo 中添加
auth required pam_google_authenticator.so

六、进阶:多服务器统一管理

当你需要管理的服务器超过10台时,逐台配置 google-authenticator 就不现实了。推荐两种方案:

方案A:LDAP统一管理(适用有AD域的企业)

通过 LDAP 集中分发 ~/.google_authenticator 密钥文件,或在企业内部部署统一的 TOTP 认证服务(如 FreeRADIUS + OTP 插件),标准 RADIUS 协议接入,5分钟完成对接。

方案B:国产商用统一双因素方案(适用等保合规企业)

对于需要满足等保2.0/密评要求的企业,建议采用国产商用方案:

  • AD域集成:直接在Windows AD域控上集成双因素认证,Linux通过SSSD或PAM RADIUS对接
  • 离线支持:工业/隔离网络环境下的离线OTP(不依赖时钟同步)
  • 统一管控:一个管理平台统管所有服务器的认证策略和用户令牌
  • 国密算法:支持SM2/SM3/SM4国产密码算法,满足密评要求

七、总结

2026年5月这波Linux内核漏洞风暴告诉我们一个朴素的道理:操作系统层面的漏洞是常态,不是意外。与其祈祷内核不出漏洞,不如在应用层加一道独立于内核的防线。

SSH 双因素认证的独特价值在于:即使攻击者拿到了你的 SSH 私钥和密码(通过内核漏洞或社工),没有你手机上的 6 位数字,他也进不来。

10分钟部署,换来的是对内核漏洞的全面免疫。这笔账怎么算都划算。


💬 话题讨论:你的生产环境SSH开了双因素认证吗?遇到过哪些踩坑经历?欢迎评论区分享。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐