恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
OpenSSH升级实战:修复scp命令注入漏洞CVE-2020-15778
首页
资讯中心
/
OpenSSH升级实战:修复scp命令注入漏洞CVE-2020-15778
OpenSSH升级实战:修复scp命令注入漏洞CVE-2020-15778
发布时间:2026/10/19 14:54:47
最近在整改一台内网业务机的漏扫问题时遇到了一个很典型的案例报告里第一条就是CVE-2020-15778对应OpenSSH的scp命令注入漏洞而这台机器上装的是老版本的OpenSSH刚好落在受影响版本范围里。业务侧要求尽快完成修复我给的方案也比较直接——通过RPM包将OpenSSH升级到8.6p1一次性把这个漏洞和其他已知问题都处理掉。整个过程看着不复杂真正动手时还是踩了几个坑比如依赖缺失、sshd_config被覆盖、升级瞬间当前会话直接断开等。这篇文章就把我从漏洞原因梳理、升级前置准备到实际执行、排障验证的全过程写出来给同样要做OpenSSH版本升级的朋友一个参考。1. 先厘清CVE-2020-15778和版本关系1.1 这个漏洞的本质CVE-2020-15778是OpenSSH的scp组件中的一个命令注入漏洞影响范围是OpenSSH 8.3p1及更早版本。NVD给出的CVSS 3.1评分为6.8属于中危级别。要理解这个漏洞得先知道scp的运作方式。scp在设计上继承了很多古老的rcp协议思路它本身不实现复杂的文件传输协议而是通过调用远端shell来执行类似“scp -t 目标路径”的命令。问题就出在“目标路径”的解析上当路径字符串里包含某些特殊字符时远端shell在解释这段路径时可能连带执行一段额外的命令。本质上不是sshd服务本身被绕过而是scp对“文件路径”和“可执行命令”的边界没有严格区分。这个漏洞的实际利用前提不算低。攻击者需要先拥有这台机器的ssh账号权限或者拿到可用于登录的密钥才有机会使用scp发起远程传输。所以它不像心脏滴血那种可以匿名触发的漏洞这也是它只被评定为中危的原因。但中危不代表可以不管尤其在内网安全合规的场景下漏扫报了你就得整改这是很多运维同学都懂的现状。1.2 为什么把8.6p1当作升级目标有朋友可能会问既然漏洞在8.4p1就修复了为什么非要升到8.6p1从“覆盖CVE”的角度看确实只要升到8.4p1及以上就够了。但实际运维时选版本不能只看漏洞修复状态还要考虑版本成熟度、兼容性调整和线上验证情况。8.4和8.5这两个版本在社区反馈中存在一些配置和算法层面的调整而8.6p1属于当时相对稳定的修复序列既包含了8.4p1对CVE-2020-15778的修复又陆续补齐了一些已知问题。对企业内网环境来说选择一个经过一段时间验证的版本更稳妥所以我当时把目标定在8.6p1。这里还要澄清一个容易混淆的点如果机器上本身已经是8.6p1甚至更高版本其实并不受CVE-2020-15778影响。漏扫报告如果还报这个问题多半是扫描器的漏洞库没更新或者目标指纹识别有误重新扫描确认即可不需要画蛇添足做升级。2. 升级前准备版本确认、包来源和备份2.1 先确认当前版本是否受影响升级前第一件事不是急着下载RPM包而是先在机器上确认OpenSSH现状。两条命令就够ssh -V输出大概是这样的形式OpenSSH_8.6p1, OpenSSL 1.1.1f 31 Mar 2020再用RPM查询确认已安装的包rpm -qa | grep openssh输出类似openssh-server-7.4p1-21.el7.x86_64 openssh-7.4p1-21.el7.x86_64 openssh-clients-7.4p1-21.el7.x86_64怎么判断受不受影响就看版本号是否小于等于8.3p1。只要版本号是8.4p1及以上CVE-2020-15778就已经修复了如果是7.4、8.0、8.2这类老版本就继续往下走。我当时查出来是7.4p1显然是必须处理的。2.2 RPM包从哪里获取很多发行版默认仓库里的OpenSSH版本都比较老比如CentOS 7自带仓库最高只能到7.4根本没有8.6p1的RPM包。这种情况通常有两条路第一条是从可信的第三方源获取现成的RPM包第二条是用官方SPEC文件在当前系统上自己构建RPM包。我这次选择的是直接获取可信源的预编译RPM包因为自建RPM涉及源码编译耗时更长而且生产环境里往往没有完整的编译工具链。这里要特别强调一定要选择与当前发行版、CPU架构完全匹配的包并在安装前校验SHA256。很多人在这步图省事结果装出依赖错乱或者二进制不兼容的问题。把openssh、openssh-clients、openssh-server三个核心RPM包放到同一个目录比如/opt/openssh-rpm后续统一安装比较方便。2.3 备份和保底登录通道OpenSSH升级有一点和普通软件包不一样升级过程中sshd服务会重启当前SSH连接会被强制断开。如果这是一台远程服务器而你手里只有一条SSH会话升级失败后很可能直接“失联”。所以我强烈建议动手之前先做两件事。第一件事是完整备份/etc/ssh目录cp -a /etc/ssh /etc/ssh.bak.$(date %Y%m%d)这条命令不能偷懒。升级后很多配置文件可能被覆盖或者被保留成.rpmnew文件没有备份的话回滚和配置对比都会非常被动。第二件事是确认至少有一条不依赖sshd的保底登录通道。物理服务器看带外管理口虚拟机看虚拟化管理平台的控制台功能。如果都没有至少准备一个定时任务或者让一个同事在不影响的网络位置待命。这一步太重要了我后面排障时深有体会。3. RPM升级实操全过程3.1 依赖检查不能省进入RPM包所在目录后别急着直接安装。用rpm命令直接装很容易报依赖错误常见的依赖缺失包括OpenSSL版本不够、libcrypto库版本低、PAM组件不一致等。可以先执行一次试装检查cd /opt/openssh-rpm rpm -Uvh --test *.rpm如果弹出类似“需要libcrypto.so.1.1”或者“需要openssl 1.1.1”的提示就先把对应依赖装上。比如缺少OpenSSL 1.1时需要从当前发行版的仓库中获取匹配的openssl和openssl-libs包按依赖顺序先装好。这一步在非标准环境下最容易出问题不少自制镜像为了“精简”删掉了openSSL相关库和PAM模块升级时全部暴露出来。3.2 安装顺序有讲究依赖确认没问题后开始安装。建议按这个顺序来rpm -Uvh openssh-8.6p1-*.x86_64.rpm rpm -Uvh openssh-clients-8.6p1-*.x86_64.rpm rpm -Uvh openssh-server-8.6p1-*.x86_64.rpm我习惯把openssh-server放到最后目的是很明确的先更新公共包和客户端最后再碰服务端包避免sshd过早重启导致当前会话立即断开。三个包一条命令装完也不是不行但一旦刚装完就出问题排查范围会一下子变大。安装过程中如果出现这样的提示warning: /etc/ssh/sshd_config created as /etc/ssh/sshd_config.rpmnew这说明新版RPM包发现/etc/ssh/sshd_config已经被修改过所以没有覆盖你的自定义配置而是把新默认配置保存成了.sshd_config.rpmnew。这不是报错是你后续需要手动合并配置的信号。3.3 配置合并与验证包装完后第一件事就是配置对比。用diff把备份和当前配置做比较diff /etc/ssh.bak.20250208/sshd_config /etc/ssh/sshd_config并行查看RPM包生成的默认配置diff /etc/ssh/sshd_config.rpmnew /etc/ssh/sshd_config这一步值得多说两句。新版本OpenSSH对默认配置做了一些调整比如PasswordAuthentication、PermitRootLogin的默认值有变化部分老配置项可能被标记为废弃。我的经验是先以原配置为基线把.rpmnew文件里与安全相关的新增项合并回来比如新版本新增的Include配置、更新的Ciphers和MACs算法列表。千万不要直接把旧的sshd_config整个覆盖过去那样很可能丢掉新版本的安全默认项同样也不能拿.rpmnew直接覆盖旧配置否则业务侧的自定义端口、认证方式全部丢失。合并完成后立即执行配置语法检查sshd -t这一步相当于让sshd自己审查一遍配置能够在重启前发现绝大多数导致服务起不来的错误比如配置项拼写错误、值超出取值范围等。没有输出就是最好的输出说明语法没问题。3.4 重启服务并逐项验证确认配置没问题后重启sshd服务systemctl restart sshd systemctl status sshd验证建议分四个维度依次做。一是版本确认ssh -V输出必须是OpenSSH_8.6p1二是服务状态systemctl status sshd显示active (running)三是新开一个SSH会话确认登录仍然正常四是执行一次scp文件传输确认scp功能完好。版本确认命令很简单ssh -V输出应该是OpenSSH_8.6p1, OpenSSL 1.1.1f 31 Mar 2020同时再用RPM查询确认一次rpm -qa | grep openssh输出应该是三个包都变成了8.6p1版本。只要版本号是8.6p1CVE-2020-15778的修复状态就已经确认了因为这个漏洞在8.4p1就已经被修复。最后让漏扫平台重新扫描一次漏洞清单里的CVE-2020-15778就会从“待整改”变成“已修复”。4. 实测最常踩的坑和排查清单4.1 五个高频问题升级OpenSSH的坑大多集中在“服务掉线”“依赖缺失”“配置覆盖”三个层面。下面是我这次实测过程中遇到和预判的高频问题整理成一个速查表现象根因处理方法升级server包时当前SSH连接断开sshd进程被重启当前会话中断升级前准备带外控制台或保底登录通道rpm -Uvh报libcrypto/openssl依赖缺失系统基础库版本过旧或被精简镜像删除先从仓库安装匹配的openssl及openssl-libssshd服务起不来status为failed配置文件语法错误或权限不正确执行sshd -t定位语法问题检查密钥和目录权限旧密钥登录失效日志提示bad permissions新版本对authorized_keys和私钥权限检查更严格将相关文件权限调整为600老客户端用ssh-rsa签名登录失败新版本默认不再启用弱算法升级客户端或显式配置算法列表优先升级客户端这里挑几个重点说一下排查时的关键点。第一个坑当前SSH会话断开。这几乎是每次升级sshd都会遇到的情况升级到server包时服务端进程被重启当前终端就像被拔了网线一样卡住。有一个不依赖sshd的登录通道是最稳的做法实在没有的话就用tmux或screen把命令挂住或者确保命令窗口里有nohup。第二个坑PAM库版本不一致。报错信息往往类似于“libpam.so.0: cannot open shared object file”。原因通常是操作系统里的pam运行库太旧或者升级时没有同步更新pam相关包。处理方式是先查看当前pam版本然后从对应发行版仓库里安装兼容的pam和pam-devel再重新执行升级。第三个坑sshd_config被覆盖后配置丢失。这里最需要注意的是PermitRootLogin、PasswordAuthentication、UsePAM这些安全关键项。合并配置时我的建议是把.rpmnew文件里新增的安全项合并回来把旧配置里自定义的业务项保留下来而不是无脑用一个文件覆盖另一个。合并完别忘了sshd -t验证再重启。第四个坑密钥权限问题。新版OpenSSH对私钥文件权限的检查非常严格如果authorized_keys或用户私钥权限过宽比如644sshd会直接拒绝登录。先查看/var/log/messages或者journalctl -u sshd里的日志一旦出现“bad permissions”或者“Authentication refused”基本就是权限问题把权限改到600就能解决。第五个坑老客户端算法兼容性问题。如果升级后有些老设备或老客户端使用ssh-rsa签名方式登录失败这是因为OpenSSH新版默认加强了对弱算法的限制。解决方案有两个方向一是对客户端做升级二是显式在sshd_config里配置允许的算法列表。但放开弱算法会引入安全风险强烈建议优先推动客户端升级而不是在服务端做妥协。4.2 升级后的自查清单为了不让整个整改虎头蛇尾我习惯在收尾时再快速跑一遍自查清单检查项命令期望结果版本号ssh -VOpenSSH_8.6p1RPM包状态rpm -qa | grep openssh三个包均为8.6p1服务状态systemctl status sshdactive (running)配置语法sshd -t无输出无报错端口监听ss -tlnp | grep 22sshd监听22端口新会话登录ssh root本机IP正常登录scp功能scp文件到本机/tmp传输成功以上每一项都在升级后顺手执行一遍整个链路就能确认到位再提给漏扫平台复扫成功率会高很多。5. 一点个人经验OpenSSH升级这类操作最难的不是命令本身而是要意识到这个操作会影响什么、什么时候会断、断了之后怎么回来。每次升级前把/etc/ssh完整备份、保底登录通道准备好、按server包放最后的顺序安装、重启前一定跑sshd -t这四件事做到位整个流程基本不会出大乱子。如果你所在的环境不允许轻易重启生产机器我的建议是先在测试环境里用同样的RPM包完整演练一遍记录下依赖清单、输出日志和配置差异再上生产操作就不会手忙脚乱。