这是一个特殊的案例,在修复ssh登陆之前,这个系统还经历了系统C库文件损坏,系统无法启动的恢复操作。
问题现象:
通过控制台管理终端可以登陆到系统内部,ssh登陆提示密码不正确,无论修改成什么密码,ssh都提示密码不正确。
在问题排查之前,我们先看下SSH 登录关联因素示意图:
问题排查:
1. 确保密码正确性:
尝试手动修改密码(通过管理终端执行passwd命令修改,我有轻微强迫症,密码还是自己改一下觉得可靠些),修改密码后对比/etc/shadow里面root用户的密文确实有变化,但是SSH依然无法登陆,提示密码不正确,而系统日志/var/log/secure日志也仅有一条failed passwd的提示 (也可以通过退出管理终端重新登录进行验证)
PASS
2. 排除网络干扰因素:
通过管理终端在系统内部执行 ssh root@localhost,(排查了系统加载的模块lsmod,没有安全狗,云锁之类的模块,hosts.deny,iptables也不存在问题)
PASS
3. 检查配置文件:
查看ssh配置文件,对比正常的文件也没有发现明显异常
PASS
4. 空密码验证:
清空root密码并允许空密码登陆ssh,本机以及外部测试依然提示密码不对
PASS
5. 登陆模块排查:
视线回归到ssh的登陆过程,空密码提示密码错误说明实际并没有到密码验证的阶段,应是/etc/pam.d下面的验证模块(常见如 system-auth ,passwd,login,sshd等)的问题
FAILED
确认原因:
排查过程中发现/etc/pam.d/sshd文件为空,找一台同系统版本的实例对比恢复,测试后恢复正常
疑问:
为什么/etc/pam.d/sshd文件为空就一直提示密码不对呢?
这个文件的内容又是什么?
SSH登陆验证的顺序是怎样的 ?
探秘:
为了排查这个问题,我们需要先了解一下什么是PAM?
PAM(插入式验证模块(Pluggable Authentication Module,PAM))
简单来说,就是提供了一组身份验证、密码验证的统一抽象接口,应用程序员可以使用这些API接口来实现与安全性相关的功能,例如:
1) 用户验证
2) 数据加密
3) LDAP
PAM 模块的基本流程
PAM 模块是按模块类型归类的。任何给定的模块至少要实现四种模块类型功能之一:
1. 验证模块(auth): 用于验证用户或设置/销毁凭证
2. 帐户管理模块(account): 将执行与访问、帐户及凭证有效期、密码限制/规则等有关的操作
3. 会话管理模块(session): 用于初始化和终止会话。
4. 密码管理模块(password)将执行与密码更改/更新有关的操作
我们看下这个文件的内容(/etc/pam.d/sshd):
#%PAM-1.0
auth required pam_sepermit.so
auth include password-auth
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
做一个小实验,修改/etc/ssh/sshd_config中的验证方式
UsePAM=yes/no
PasswordAuthentication=yes
在清空/etc/pam.d/sshd以及PasswordAuthentication=yes的情况下:
设置UsePAM=yes,提示验证失败(实际验证的时候发现不同的系统版本提示不太一样,客户端是Authentication failed.secure日志有所不同,failed passwd ,pam提示都有)
设置UsePAM=no,使用正确的passwd登录成功
通过这个测试可以确定,当开启UsePAM的时候,先去找验证模块,由验证模块决定下一步的验证
(如/etc/pam.d/sshd文件里面的auth include password-auth)即使密码是正确的,如果验证模块自身有问题也无法登录