首页/安全/应急响应速查/SSH 授权公钥全盘排查

SSH 授权公钥全盘排查

拿到一次 shell 的攻击者常往 authorized_keys 塞自己的公钥实现免密回访:所有家目录的该文件都要过一遍。

应急响应速查安全更新于 2026-10-13

authorized_keys 是什么

SSH 公钥认证的本质是:客户端用私钥签名,服务端用该用户 authorized_keys 文件里登记的公钥验签,验签通过即登录成功。所以文件里多出的任何一行,等于给对应私钥的持有者发了一张长期免密通行证。攻击者拿到一次 shell 后往这里追加公钥,就同时绕过了口令强度要求、失败锁定与部分审计手段,比留 webshell 更安静。排查目标很明确:把每个可能登录的账号的这份文件都看一遍,逐行确认归属。

基本信息

默认路径~/.ssh/authorized_keys(root 为 /root/.ssh/authorized_keys)
生效路径由谁定sshd_config 的 AuthorizedKeysFile,可被改成 /etc/ssh/authorized_keys/%u 等自定义位置
权限要求StrictModes 开启时 .ssh 需 700、authorized_keys 需 600,属主必须是该用户,否则登录直接被拒
可否带限制选项可以,行首可加 command="..."、from="IP"、no-pty、restrict、no-port-forwarding 等前缀
指纹工具ssh-keygen -lf 文件(对 authorized_keys 整体取指纹亦可)
常见忽略点注释字段(行末 comment)由写文件的人随意填写,不能作为归属依据

典型使用场景

  • SSH 爆破或可疑登录告警后,确认是否已被写入攻击者公钥
  • 木马清理完成后做反弹复查,确认免密通道已彻底关闭
  • 离职或交接时核对哪些公钥还在,避免遗留账号长期可登录
  • 运维侧推行密钥认证时核对存量用户是否合规配置
  • 与 last、auth.log 联用,把公钥写入时间与登录时间对上

全用户扫描与指纹比对

全用户扫描与指纹比对
for h in /root /home/*; do f="$h/.ssh/authorized_keys";   # 遍历所有家目录
  if [ -f "$f" ]; then echo "== $f"; ls -l --time-style=full-iso "$f"; cat "$f"; fi; done
sudo sshd -T | grep -i authorizedkeysfile                    # 先确认生效的密钥文件路径
ssh-keygen -lf /root/.ssh/authorized_keys                    # 生成指纹,与台账逐条比对
sudo grep -RIn 'command=\|no-pty\|from=' /root/.ssh /home/*/.ssh 2>/dev/null   # 带限制前缀的可疑行
sudo sha256sum /root/.ssh/authorized_keys | tee /evidence/ak_hash.txt           # 先存证再动手

逐行读法

行内元素含义判断要点
算法前缀ssh-rsa、ssh-ed25519、ecdsa-sha2-*ssh-rsa 若只有 1024 位属老旧弱密钥,需重点关注
公钥体Base64 编码内容无法肉眼判断归属,必须用 ssh-keygen -lf 取指纹比对台账
注释字段行末自由文本,常是 user@host可以被随意伪造,不能凭它认定是谁的密钥
选项前缀command=、from=、restrict、no-ptycommand= 常被用来做固定动作后门,from= 说明来源被限定
文件权限与属主600 属主为该用户,.ssh 为 700权限不对会导致登录失败,排查时顺手核对
mtime文件最后修改时间与入侵时间窗对得上就是强线索,务必先记录
保全优先于清理:先把文件复制到独立介质、算好 sha256 并记录 mtime,最安全的现场处理是把可疑行用 # 注释掉(sshd 会忽略注释行),确认无人受影响后再删除。
只清理 authorized_keys 不算完:AuthorizedKeysFile 可能被改成其他路径,sshd_config 里还可能有 AuthorizedKeysCommand,PAM 与 sshd 的 ForceCommand 也要一起核对,否则通道照样存在。

配套检查项

配套检查项
sudo ls -la /root/.ssh /home/*/.ssh 2>/dev/null | head -n 40      # 目录整体过一遍
sudo ls -la /etc/ssh/authorized_keys* /etc/ssh/ssh_host_* 2>/dev/null  # 排查自定义集中存放位置
sudo grep -RIn 'authorizedkeys\|forcecommand' /etc/ssh/sshd_config /etc/ssh/sshd_config.d 2>/dev/null
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub              # 顺手核对主机密钥有没有被换
换过主机密钥(HostKey)的主机第一次连接会报指纹不匹配,这既可能是重装系统,也可能是中间人;应急现场发现指纹变化要记录时间点并核对重装记录。

SSH 后门的常见形态

形态痕迹位置清除要点
追加公钥各用户 .ssh/authorized_keys按行核对指纹,污染行注释保全后再删
固定命令后门authorized_keys 中带 command= 前缀的行删除整行,并检查被它调用的脚本文件
集中公钥路径sshd_config 的 AuthorizedKeysFile 被改向恢复配置并清理被指向目录中的全部条目
外部密钥命令sshd_config 的 AuthorizedKeysCommand恢复为空并检查被调用的脚本是否存在
提权账号/etc/passwd 新增 uid 0 条目与密钥排查同批完成,避免只堵一条路

清理前后核对清单

  • 清理前:复制文件内容、记录 mtime 与 sha256、导出当前在线会话与来源 IP
  • 清理中:只注释不删除,确认无业务账号依赖该公钥后再移除
  • 清理后:用 ssh -o PreferredAuthentications=publickey 重试登录确认通道失效
  • 清理后:复查 sshd -T 的生效配置与 /etc/ssh 下所有相关文件
  • 归档:把证据目录、变更记录与验证结果写入处置报告

易错点

  • 只查 root 的 authorized_keys:业务账号、部署账号、备份账号同样能登录,遗漏一个等于没清
  • 凭注释字段判断归属:comment 内容由写文件的人决定,必须用指纹与台账、工单记录比对
  • 直接删文件不留证:内容、mtime、哈希都没保存,后续无法证明攻击者如何进来、也无法复盘
  • 忽略 AuthorizedKeysFile 被改:不看 sshd -T 的输出就动手,容易清了一个改过的假路径
  • 清理后不验证:应当用 ssh -o PreferredAuthentications=publickey 试登录确认通道确实关闭,并复查一轮文件内容

数据来源与参考

  • OpenSSH sshd(8) 手册:AuthorizedKeysFile
  • SANS SSH 后门排查实践

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌