泄漏描述
OpenSSH是一套用于安全网络通信的工具,提供了包括远程登录、远程执行命令、文件传输等功能 2024年7月1日,OpenSSH 官方发布安全通告,披露CVE-2024-6387 OpenSSH Server 远程代码执行漏洞。 漏洞成因为条件竞争,因此若要成功利用该漏洞,需要经过多次尝试,并需要绕过相关系统保护措施(如ASLR),在实际网络环境下利用难度较大,目前仅有针对32位机器的利用方案。 同时基于代码引入时间、系统保护措施、系统安装OpenSSH版本等,目前已知 CentOS 7/8、RedHat 6/7/8、Debian 11 等系统默认安装的OpenSSH Server、Windows操作系统上的OpenSSH Server等均不受该漏洞影响。 OpenSSH官方及各操作系统发行方已发布安全更新,建议相关受影响客户进行更新升级。 影响范围 8.5p1 <= OpenSSH < 9.8p1
修复和改进建议
1、升级OpenSSH至安全版本9.8及其以上,或者各发行版本的安全修复版本。 2、若暂无法升级,建议使用安全组设置OpenSSH端口仅对可信地址开放。 3、应用漏洞暂只支持获取openssh自身版本,若您确定已为各发行版本安全修复版本,可予忽略。
针对此漏洞,编写了修复脚本文件 ssh_upgrade.sh,具体如下:
#!/bin/bash
set enforce 0
# 安装依赖
sudo apt install build-essential zlib1g-dev libssl-dev libpam0g-dev
# 下载并编译
wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.8p1.tar.gz
tar -xzf openssh-9.8p1.tar.gz
cd openssh-9.8p1
# 配置、编译并安装 OpenSSH
./configure --prefix=/usr/local/openssh --with-zlib=/usr/local/zlib --with-ssl-dir=/usr
make && make install
# 配置 SSH
echo'PermitRootLogin yes' >>/usr/local/openssh/etc/sshd_config
echo'PubkeyAuthentication yes' >>/usr/local/openssh/etc/sshd_config
echo'PasswordAuthentication yes' >>/usr/local/openssh/etc/sshd_config
# 备份并替换系统默认的 SSH 配置和二进制文件
mv /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
cp /usr/local/openssh/etc/sshd_config /etc/ssh/sshd_config
mv /usr/local/sbin/sshd /usr/local/bin/sshd.bak
cp /usr/local/openssh/sbin/sshd /usr/local/sbin/sshd
mv /usr/local/bin/ssh /usr/local/bin/ssh.bak
cp /usr/local/openssh/bin/ssh /usr/local/bin/ssh
mv /usr/bin/ssh-keygen /usr/bin/ssh-keygen.bak
cp /usr/local/openssh/bin/ssh-keygen /usr/bin/ssh-keygen
mv /etc/ssh/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ecdsa_key.pub.bak
cp /usr/local/openssh/etc/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ecdsa_key.pub
# 修改 systemd 配置并重启 SSH 服务
sed -i "s/Type\=notify/Type\=simple/g" /lib/systemd/system/ssh.service
systemctl daemon-reload && systemctl restart sshd
# 验证是否升级成功
ssh -V
如果需要使用Ansible工具进行批量执行,则需要编写 playbook,如下 ssh_upgrade.yaml
---
-name:Copyandexecutea.shscriptonallhosts
hosts:all
become:yes
tasks:
-name:Copyssh_upgrade.shscripttoremotehost
copy:
src:ssh_upgrade.sh# 控制主机上的脚本路径
dest:/opt/ssh_upgrade.sh# 目标主机上的存放路径
mode:'0755'# 给予脚本执行权限
-name:Executessh_upgrade.shscriptonremotehost
shell:/opt/ssh_upgrade.sh # 目标主机上的脚本路径
编写需要被执行的目标主机,如 hosts.ini
[bares]
147.111.96.13
xx.xx.xx.xx
...
执行:ansible-playbook ssh_upgrade.yaml -i hosts.ini -u username -k
结果如下:
注意,上述脚本适合于单次执行的情况,为了方便识别操作了哪些步骤,简化了,若需要可多次执行,则使用下面改进版本的。
#!/bin/bash
set -euo pipefail # 严格错误中断模式
exec > >(tee -a /var/log/openssh_upgrade.log) 2>&1 # 记录完整日志
# 参数化配置
OPENSSH_VER="9.8p1"
INSTALL_DIR="/usr/local/openssh"
TAR_FILE="openssh-${OPENSSH_VER}.tar.gz"
SOURCE_URL="https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/${TAR_FILE}"
# 检查root权限
if [[ $EUID -ne 0 ]]; then
echo"必须使用root权限运行此脚本" >&2
exit 1
fi
# 禁用SELinux(仅临时生效)
set enforce 0 || true
# 安装依赖(仅首次执行)
declare -a DEPS=(build-essential zlib1g-dev libssl-dev libpam0g-dev)
for pkg in"${DEPS[@]}"; do
if ! dpkg -s "$pkg" &>/dev/null; then
apt install -y "$pkg"
fi
done
# 下载源码(避免重复下载)
if [[ ! -f "$TAR_FILE" ]]; then
wget --tries=3 --timeout=30 --no-check-certificate "$SOURCE_URL"
else
echo"[INFO] 源码包已存在,跳过下载: $TAR_FILE"
fi
# 解压源码(清理旧编译目录)
if [[ -d "openssh-${OPENSSH_VER}" ]]; then
rm -rf "openssh-${OPENSSH_VER}"
fi
tar -xzf "$TAR_FILE"
cd"openssh-${OPENSSH_VER}"
# 编译安装(避免重复编译)
if [[ ! -f "$INSTALL_DIR/sbin/sshd" ]]; then
./configure --prefix="$INSTALL_DIR" \
--with-zlib=/usr/local/zlib \
--with-ssl-dir=/usr
make -j$(nproc)
make install
else
echo"[INFO] OpenSSH已编译安装,跳过此步骤"
fi
# 安全备份配置文件(避免覆盖旧备份)
backup_file() {
local file="$1"
if [[ -f "$file" && ! -f "${file}.bak" ]]; then
cp -p "$file""${file}.bak"
echo"[INFO] 已备份: $file → ${file}.bak"
fi
}
# 更新SSH配置
declare -a CFG_LINES=(
"PermitRootLogin yes"
"PubkeyAuthentication yes"
"PasswordAuthentication yes"
)
for line in"${CFG_LINES[@]}"; do
if ! grep -q "^$line""$INSTALL_DIR/etc/sshd_config"; then
echo"$line" >> "$INSTALL_DIR/etc/sshd_config"
fi
done
# 替换系统文件(增量更新)
replace_system_file() {
local src="$1"
local dest="$2"
if ! cmp -s "$src""$dest"; then
backup_file "$dest"
cp -f "$src""$dest"
echo"[INFO] 已更新文件: $dest"
fi
}
replace_system_file "$INSTALL_DIR/etc/sshd_config""/etc/ssh/sshd_config"
replace_system_file "$INSTALL_DIR/sbin/sshd""/usr/local/bin/sshd"
replace_system_file "$INSTALL_DIR/bin/ssh""/usr/local/bin/ssh"
replace_system_file "$INSTALL_DIR/bin/ssh-keygen""/usr/bin/ssh-keygen"
# 修改systemd配置(幂等操作)
SERVICE_FILE="/lib/systemd/system/ssh.service"
if grep -q "Type=notify""$SERVICE_FILE"; then
sed -i "s/Type=notify/Type=simple/""$SERVICE_FILE"
systemctl daemon-reload
fi
# 重启服务(带状态检查)
if systemctl is-active --quiet sshd; then
systemctl restart sshd
echo"[INFO] SSH服务已重启"
sleep 3
if ! systemctl is-active --quiet sshd; then
echo"[ERROR] SSH服务启动失败,请检查日志" >&2
exit 1
fi
fi
# 验证版本
echo"当前OpenSSH版本:"
ssh -V